Skip to content

Situate REST API Reference for Automation ​

This document provides a comprehensive reference for automating Situate workflows via the REST API. It is designed for use with AI coding assistants like Claude Code to generate Python scripts.

Connection Setup ​

Base URL ​

https://<server>/situate

Authentication ​

All requests require an API key passed in the X-API-Key header.

python
import requests

BASE_URL = "https://<server>/situate"
API_KEY = "your-api-key-here"

headers = {
    "X-API-Key": API_KEY,
    "Content-Type": "application/json",
    "Accept": "application/json"
}

# For XML responses
headers_xml = {
    "X-API-Key": API_KEY,
    "Content-Type": "application/xml",
    "Accept": "application/xml"
}

# Disable SSL warnings for self-signed certs (development only)
requests.packages.urllib3.disable_warnings()

Workflows ​

List All Workflows ​

python
def list_workflows(state=None, queue=None):
    """
    List all workflows, optionally filtered by state and queue.

    Args:
        state: 'submitted' or 'approved'
        queue: queue name (default: all)

    Returns:
        List of workflow objects
    """
    params = {}
    if state:
        params['state'] = state
    if queue:
        params['queue'] = queue

    response = requests.get(
        f"{BASE_URL}/workflows",
        headers=headers,
        params=params,
        verify=False
    )
    response.raise_for_status()
    return response.json()


def find_workflow_by_group_and_name(group_path, workflow_name, state="approved"):
    """
    Find a workflow ID by its group path and name.

    Workflows are organized in a group hierarchy like a filesystem.
    This function finds a workflow given its logical location.

    Args:
        group_path: Group path like "a/b/c" or "Production/Daily Jobs"
        workflow_name: Name of the workflow
        state: 'submitted' or 'approved' (default: approved)

    Returns:
        Workflow ID string, or None if not found

    Example:
        workflow_id = find_workflow_by_group_and_name(
            "Production/Batch/Nightly",
            "DataBackup"
        )
    """
    result = list_workflows(state=state)

    # Normalize group path (remove leading/trailing slashes)
    group_path = group_path.strip('/')

    workflows = result.get('workflows', [])
    for wf in workflows:
        attrs = wf.get('attrs', {})
        wf_name = attrs.get('name')
        wf_group = attrs.get('groupPath', '').strip('/')

        if wf_name == workflow_name and wf_group == group_path:
            return attrs.get('id')

    return None


def get_workflow_by_group_and_name(group_path, workflow_name, state="approved", format="xml"):
    """
    Get a workflow by its group path and name.

    Args:
        group_path: Group path like "a/b/c"
        workflow_name: Name of the workflow
        state: 'submitted' or 'approved'
        format: 'json' or 'xml' (default: xml for schedule modification)

    Returns:
        Workflow XML document (default) or JSON object

    Raises:
        ValueError: If workflow not found

    Note:
        Use format='xml' (default) when you need to modify schedules or
        other workflow internals. JSON is useful for reading metadata only.
    """
    workflow_id = find_workflow_by_group_and_name(group_path, workflow_name, state)
    if not workflow_id:
        raise ValueError(f"Workflow '{workflow_name}' not found in group '{group_path}'")

    return get_workflow(workflow_id, state=state, format=format)

Get Workflow by ID ​

python
def get_workflow(workflow_id, state=None, format="json"):
    """
    Retrieve a specific workflow.

    Args:
        workflow_id: The workflow's unique ID
        state: 'submitted' or 'approved'
        format: 'json' or 'xml'

    Returns:
        Workflow object (JSON) or XML document
    """
    params = {}
    if state:
        params['state'] = state

    h = headers_xml if format == "xml" else headers

    response = requests.get(
        f"{BASE_URL}/workflows/{workflow_id}",
        headers=h,
        params=params,
        verify=False
    )
    response.raise_for_status()

    if format == "xml":
        return response.text
    return response.json()

Execute a Workflow ​

python
def execute_workflow(workflow_id, trigger_name, parameters=None):
    """
    Execute a workflow with the specified trigger.

    Args:
        workflow_id: The workflow's unique ID
        trigger_name: Name of the trigger to use
        parameters: Dict of parameters to pass to the workflow

    Returns:
        Execution response
    """
    params = {"trigger": trigger_name}
    data = parameters or {}

    response = requests.post(
        f"{BASE_URL}/workflows/{workflow_id}",
        headers=headers,
        params=params,
        json=data,
        verify=False
    )
    response.raise_for_status()
    return response.json()

Create New Workflow ​

python
def create_workflow(workflow_xml, preserve_acl=False):
    """
    Submit a new workflow to Situate.

    Args:
        workflow_xml: Complete workflow XML document
        preserve_acl: If True, preserve ACL (requires admin)

    Returns:
        Validation response with workflow ID
    """
    params = {}
    if preserve_acl:
        params['preserveAcl'] = 'true'

    response = requests.post(
        f"{BASE_URL}/workflows",
        headers=headers_xml,
        params=params,
        data=workflow_xml,
        verify=False
    )
    response.raise_for_status()
    return response.json()

Update Existing Workflow ​

python
def update_workflow(workflow_id, workflow_xml):
    """
    Update an existing workflow. Places workflow in 'submitted' state.

    Args:
        workflow_id: The workflow's unique ID (must match ID in XML)
        workflow_xml: Complete workflow XML document

    Returns:
        Validation response
    """
    response = requests.put(
        f"{BASE_URL}/workflows/{workflow_id}",
        headers=headers_xml,
        data=workflow_xml,
        verify=False
    )
    response.raise_for_status()
    return response.json()

Approve and Enable Workflow ​

python
def approve_workflow(workflow_id, enable=True):
    """
    Approve a submitted workflow and optionally enable it.

    Args:
        workflow_id: The workflow's unique ID
        enable: If True, enable the workflow for execution

    Returns:
        Approval response
    """
    data = {
        "approveWorkflow": True,
        "enableWorkflow": enable
    }

    response = requests.patch(
        f"{BASE_URL}/workflows/{workflow_id}",
        headers=headers,
        json=data,
        verify=False
    )
    response.raise_for_status()
    return response.json()

Delete Workflow ​

python
def delete_workflow(workflow_id, state="approved"):
    """
    Delete a workflow.

    Args:
        workflow_id: The workflow's unique ID
        state: 'submitted' or 'approved'
    """
    params = {"state": state}

    response = requests.delete(
        f"{BASE_URL}/workflows/{workflow_id}",
        headers=headers,
        params=params,
        verify=False
    )
    response.raise_for_status()

Complete Workflow Update Cycle ​

python
def update_and_approve_workflow(workflow_id, workflow_xml):
    """
    Complete workflow update: submit changes and approve.

    Args:
        workflow_id: The workflow's unique ID
        workflow_xml: Modified workflow XML

    Returns:
        Final approval response
    """
    # Step 1: Submit the updated workflow
    update_response = update_workflow(workflow_id, workflow_xml)

    # Check for validation errors
    if update_response.get('validationErrors'):
        raise Exception(f"Validation errors: {update_response['validationErrors']}")

    # Step 2: Approve and enable
    return approve_workflow(workflow_id, enable=True)

Workflow Triggers ​

Enable/Disable a Trigger ​

python
def set_trigger_enabled(workflow_id, trigger_name, enabled=True):
    """
    Enable or disable a specific trigger on a workflow.

    Args:
        workflow_id: The workflow's unique ID
        trigger_name: Name of the trigger
        enabled: True to enable, False to disable
    """
    data = {
        "action": "enable",
        "enable": enabled
    }

    response = requests.patch(
        f"{BASE_URL}/workflows/{workflow_id}/triggers/{trigger_name}",
        headers=headers,
        json=data,
        verify=False
    )
    response.raise_for_status()
    return response.json()

Modify Schedule Trigger (XML Manipulation) ​

Schedule triggers are embedded in the workflow XML. Situate uses SubSchedule types (not cron expressions).

SubSchedule Types ​

TypeDescriptionKey Properties
DailySubScheduleEvery N daysevery, startHour, startMinute, startSecond
WeeklySubScheduleSpecific days of weekdaysMask (boolean[7] Sun-Sat), every (weeks)
PeriodicSubScheduleEvery N seconds/minutes/hoursevery, everyScale (0=hours, 1=minutes, 2=seconds)
MonthlyDateSubScheduleSpecific dates of monthsdays (int[]), months (boolean[12]), lastDayOfMonth
CalendarSubScheduleDates from a calendarcalendar (calendar name)

Repeat Modes (intra-day recurrence) ​

Each subschedule supports repeating throughout the day:

repeatModeDescription
0No repeat (run once)
1Repeat until specific time
2Repeat until end of day
3Repeat N times
python
import xml.etree.ElementTree as ET

def modify_daily_schedule_time(workflow_xml, trigger_name, hour, minute, second=0):
    """
    Modify a DailySubSchedule trigger's start time.

    Args:
        workflow_xml: The workflow XML string
        trigger_name: Name of the schedule trigger to modify
        hour: New start hour (0-23)
        minute: New start minute (0-59)
        second: New start second (0-59)

    Returns:
        Modified workflow XML string
    """
    root = ET.fromstring(workflow_xml)

    # Find triggers and locate by name
    for trigger in root.iter('trigger'):
        name_elem = trigger.find('name')
        if name_elem is not None and name_elem.text == trigger_name:
            # Find the DailySubSchedule within includeSchedules
            for daily in trigger.iter('com.xona.wf.schedule.DailySubSchedule'):
                start_hour = daily.find('startHour')
                start_minute = daily.find('startMinute')
                start_second = daily.find('startSecond')

                if start_hour is not None:
                    start_hour.text = str(hour)
                if start_minute is not None:
                    start_minute.text = str(minute)
                if start_second is not None:
                    start_second.text = str(second)
                break

    return ET.tostring(root, encoding='unicode')


def modify_weekly_schedule(workflow_xml, trigger_name, days_of_week, hour, minute):
    """
    Modify a WeeklySubSchedule trigger.

    Args:
        workflow_xml: The workflow XML string
        trigger_name: Name of the schedule trigger
        days_of_week: List of day names ('sunday', 'monday', etc.) or indices (0=Sun, 6=Sat)
        hour: Start hour (0-23)
        minute: Start minute (0-59)

    Returns:
        Modified workflow XML string
    """
    # Convert day names to indices
    day_names = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday']
    day_indices = []
    for day in days_of_week:
        if isinstance(day, str):
            day_indices.append(day_names.index(day.lower()))
        else:
            day_indices.append(day)

    root = ET.fromstring(workflow_xml)

    for trigger in root.iter('trigger'):
        name_elem = trigger.find('name')
        if name_elem is not None and name_elem.text == trigger_name:
            for weekly in trigger.iter('com.xona.wf.schedule.WeeklySubSchedule'):
                # Update time
                start_hour = weekly.find('startHour')
                start_minute = weekly.find('startMinute')
                if start_hour is not None:
                    start_hour.text = str(hour)
                if start_minute is not None:
                    start_minute.text = str(minute)

                # Update days mask
                days_mask = weekly.find('daysMask')
                if days_mask is not None:
                    # Clear existing and rebuild
                    days_mask.clear()
                    for i in range(7):
                        bool_elem = ET.SubElement(days_mask, 'boolean')
                        bool_elem.text = 'true' if i in day_indices else 'false'
                break

    return ET.tostring(root, encoding='unicode')


def update_workflow_schedule(workflow_id, trigger_name, hour, minute):
    """
    Complete process to update a workflow's schedule trigger time.

    Args:
        workflow_id: The workflow's unique ID
        trigger_name: Name of the schedule trigger
        hour: New start hour
        minute: New start minute
    """
    # Step 1: Get the workflow XML
    workflow_xml = get_workflow(workflow_id, format="xml")

    # Step 2: Modify the schedule
    modified_xml = modify_daily_schedule_time(workflow_xml, trigger_name, hour, minute)

    # Step 3: Update and approve
    return update_and_approve_workflow(workflow_id, modified_xml)

Workflow Instances (Running Workflows) ​

List Running Instances ​

python
def list_workflow_instances(state=None, queue=None):
    """
    List workflow instances.

    Args:
        state: 'running', 'canceling', or 'unconfirmed'
        queue: queue name

    Returns:
        List of workflow instances
    """
    params = {}
    if state:
        params['state'] = state
    if queue:
        params['queue'] = queue

    response = requests.get(
        f"{BASE_URL}/workflowInstances",
        headers=headers,
        params=params,
        verify=False
    )
    response.raise_for_status()
    return response.json()

Cancel a Running Workflow ​

python
def cancel_workflow_instance(instance_id):
    """
    Cancel a running workflow instance.

    Args:
        instance_id: The instance's unique ID
    """
    response = requests.put(
        f"{BASE_URL}/workflowInstances/{instance_id}",
        headers=headers,
        verify=False
    )
    response.raise_for_status()

Workflow Logs ​

Query Workflow Logs ​

python
def get_workflow_logs(query_type="today"):
    """
    Get workflow execution logs.

    Args:
        query_type: Time period filter
            - 'today': Today
            - 'yesterday': Yesterday
            - 'L1': Last 1 hour
            - 'L4': Last 4 hours
            - 'L8': Last 8 hours
            - 'L12': Last 12 hours
            - 'L24': Last 24 hours
            - 'L48': Last 48 hours
            - 'LW': Last week
            - 'LM': Last month
            - 'L60': Last 60 days

    Returns:
        List of workflow log entries
    """
    params = {"queryType": query_type}

    response = requests.get(
        f"{BASE_URL}/workflowLogs",
        headers=headers,
        params=params,
        verify=False
    )
    response.raise_for_status()
    return response.json()

Get Specific Workflow Instance Log ​

python
def get_workflow_instance_log(workflow_id, instance_id, start=0):
    """
    Get detailed log entries for a specific workflow execution.

    Args:
        workflow_id: The workflow's unique ID
        instance_id: The instance's unique ID
        start: Offset index for pagination

    Returns:
        List of log entries
    """
    params = {"start": start}

    response = requests.get(
        f"{BASE_URL}/workflowLogs/{workflow_id}/{instance_id}",
        headers=headers,
        params=params,
        verify=False
    )
    response.raise_for_status()
    return response.json()

Workflow Groups ​

List Groups ​

python
def list_workflow_groups():
    """List all workflow groups."""
    response = requests.get(
        f"{BASE_URL}/workflowGroups",
        headers=headers,
        verify=False
    )
    response.raise_for_status()
    return response.json()

Create Group ​

python
def create_workflow_group(name, description=None, parent_id=None):
    """
    Create a new workflow group.

    Args:
        name: Group name
        description: Optional description
        parent_id: Parent group ID (None for root)
    """
    data = {"name": name}
    if description:
        data["description"] = description
    if parent_id:
        data["parentId"] = parent_id

    response = requests.post(
        f"{BASE_URL}/workflowGroups",
        headers=headers,
        json=data,
        verify=False
    )
    response.raise_for_status()
    return response.json()

Workflow Queues ​

List Queues ​

python
def list_workflow_queues():
    """List all workflow queues."""
    response = requests.get(
        f"{BASE_URL}/workflowQueues",
        headers=headers,
        verify=False
    )
    response.raise_for_status()
    return response.json()

Pause/Resume Queue ​

python
def set_queue_paused(queue_name, paused=True):
    """
    Pause or resume a workflow queue.

    Args:
        queue_name: Name of the queue (e.g., 'Master')
        paused: True to pause, False to resume
    """
    data = {"paused": paused}

    response = requests.patch(
        f"{BASE_URL}/workflowQueues/{queue_name}",
        headers=headers,
        json=data,
        verify=False
    )
    response.raise_for_status()
    return response.json()

Assets ​

List Assets ​

python
def list_assets(group_name=None, group_id=None):
    """
    List all assets (agents).

    Args:
        group_name: Filter by group name (e.g., 'dev/chicago')
        group_id: Filter by group ID

    Returns:
        List of asset objects
    """
    params = {}
    if group_name:
        params['groupName'] = group_name
    if group_id:
        params['groupId'] = group_id

    response = requests.get(
        f"{BASE_URL}/assets",
        headers=headers,
        params=params,
        verify=False
    )
    response.raise_for_status()
    return response.json()

Get Asset by ID ​

python
def get_asset(asset_id):
    """Get a specific asset by ID."""
    response = requests.get(
        f"{BASE_URL}/assets/{asset_id}",
        headers=headers,
        verify=False
    )
    response.raise_for_status()
    return response.json()

Calendars ​

List Calendars ​

python
def list_calendars():
    """List all calendars."""
    response = requests.get(
        f"{BASE_URL}/calendars",
        headers=headers,
        verify=False
    )
    response.raise_for_status()
    return response.json()

Update Calendar ​

python
def update_calendar(calendar_id, calendar_data):
    """
    Update a calendar.

    Args:
        calendar_id: The calendar's unique ID
        calendar_data: TraditionalCalendar JSON object
    """
    response = requests.put(
        f"{BASE_URL}/calendars/{calendar_id}",
        headers=headers,
        json=calendar_data,
        verify=False
    )
    response.raise_for_status()
    return response.json()

System ​

Get System Statistics ​

python
def get_system_statistics():
    """
    Get system statistics including:
    - active: Number of active workflows
    - approved: Number of approved workflows
    - assets: Number of registered assets
    - executed: Workflows executed since startup
    - version: Situate server version
    """
    response = requests.get(
        f"{BASE_URL}/system/statistics",
        headers=headers,
        verify=False
    )
    response.raise_for_status()
    return response.json()

Get Situate Properties ​

python
def get_situate_properties():
    """Get the server's situate.properties configuration."""
    response = requests.get(
        f"{BASE_URL}/system/situate-properties",
        headers=headers,
        verify=False
    )
    response.raise_for_status()
    return response.json()

Complete Example: Update a Schedule Trigger ​

This example demonstrates the full process of modifying a workflow's schedule using group path and workflow name (not hardcoded IDs):

python
#!/usr/bin/env python3
"""
Example: Update a workflow's schedule trigger to run at a new time.
Finds the workflow by group path and name.
"""

import requests
import xml.etree.ElementTree as ET

# Configuration
BASE_URL = "https://situate.example.com/situate"
API_KEY = "your-api-key"

# Identify workflow by group and name (not hardcoded ID)
GROUP_PATH = "Production/Batch/Nightly"
WORKFLOW_NAME = "DataBackup"
TRIGGER_NAME = "DailySchedule"
NEW_HOUR = 9
NEW_MINUTE = 0

headers_json = {
    "X-API-Key": API_KEY,
    "Content-Type": "application/json",
    "Accept": "application/json"
}

headers_xml = {
    "X-API-Key": API_KEY,
    "Content-Type": "application/xml",
    "Accept": "application/xml"
}

def find_workflow_id(group_path, workflow_name):
    """Find workflow ID by group path and name."""
    response = requests.get(
        f"{BASE_URL}/workflows",
        headers=headers_json,
        params={"state": "approved"},
        verify=False
    )
    response.raise_for_status()

    group_path = group_path.strip('/')
    for wf in response.json().get('workflows', []):
        attrs = wf.get('attrs', {})
        if (attrs.get('name') == workflow_name and
            attrs.get('groupPath', '').strip('/') == group_path):
            return attrs.get('id')
    return None


def main():
    # Step 1: Find the workflow ID by group and name
    print(f"Finding workflow '{WORKFLOW_NAME}' in group '{GROUP_PATH}'...")
    workflow_id = find_workflow_id(GROUP_PATH, WORKFLOW_NAME)
    if not workflow_id:
        print(f"  ERROR: Workflow not found!")
        return
    print(f"  Found workflow ID: {workflow_id}")

    # Step 2: Get the workflow XML
    print("Fetching workflow XML...")
    response = requests.get(
        f"{BASE_URL}/workflows/{workflow_id}",
        headers=headers_xml,
        verify=False
    )
    response.raise_for_status()
    workflow_xml = response.text

    # Step 3: Parse and modify the XML
    print(f"Updating trigger '{TRIGGER_NAME}' to {NEW_HOUR:02d}:{NEW_MINUTE:02d}")
    root = ET.fromstring(workflow_xml)

    # Find the trigger by name and update the subschedule
    for trigger in root.iter('trigger'):
        name_elem = trigger.find('name')
        if name_elem is not None and name_elem.text == TRIGGER_NAME:
            # Look for DailySubSchedule (or other subschedule types)
            for subschedule in trigger.iter('com.xona.wf.schedule.DailySubSchedule'):
                start_hour = subschedule.find('startHour')
                start_minute = subschedule.find('startMinute')

                if start_hour is not None:
                    print(f"  Old time: {start_hour.text}:{start_minute.text if start_minute is not None else '00'}")
                    start_hour.text = str(NEW_HOUR)
                if start_minute is not None:
                    start_minute.text = str(NEW_MINUTE)
                print(f"  New time: {NEW_HOUR:02d}:{NEW_MINUTE:02d}")
                break

    modified_xml = ET.tostring(root, encoding='unicode')

    # Step 4: Submit the updated workflow
    print("Submitting updated workflow...")
    response = requests.put(
        f"{BASE_URL}/workflows/{workflow_id}",
        headers=headers_xml,
        data=modified_xml,
        verify=False
    )
    response.raise_for_status()
    print("  Workflow submitted successfully")

    # Step 5: Approve and enable
    print("Approving workflow...")
    response = requests.patch(
        f"{BASE_URL}/workflows/{workflow_id}",
        headers=headers_json,
        json={"approveWorkflow": True, "enableWorkflow": True},
        verify=False
    )
    response.raise_for_status()
    print("  Workflow approved and enabled")

    print("Done!")

if __name__ == "__main__":
    main()

Error Handling ​

Common HTTP status codes:

StatusMeaning
200Success
201Created (workflow submitted/approved)
400Bad Request (invalid data, validation errors)
401Unauthorized (invalid/missing API key)
403Forbidden (license issue, permission denied)
404Not Found (workflow/resource doesn't exist)
500Server Error
python
def handle_api_error(response):
    """Handle API errors with useful messages."""
    if response.status_code == 400:
        raise Exception(f"Invalid request: {response.text}")
    elif response.status_code == 401:
        raise Exception("Authentication failed - check your API key")
    elif response.status_code == 403:
        raise Exception(f"Permission denied: {response.text}")
    elif response.status_code == 404:
        raise Exception("Resource not found")
    elif response.status_code >= 500:
        raise Exception(f"Server error: {response.text}")
    response.raise_for_status()

Schedule XML Reference ​

DailySubSchedule Example ​

Run every day at 8:00 AM:

xml
<com.xona.wf.schedule.DailySubSchedule>
  <every>1</every>
  <startHour>8</startHour>
  <startMinute>0</startMinute>
  <startSecond>0</startSecond>
  <repeatMode>0</repeatMode>
  <from>
    <day>1</day>
    <month>1</month>
    <year>2024</year>
  </from>
</com.xona.wf.schedule.DailySubSchedule>

WeeklySubSchedule Example ​

Run Monday through Friday at 9:30 AM:

xml
<com.xona.wf.schedule.WeeklySubSchedule>
  <every>1</every>
  <startHour>9</startHour>
  <startMinute>30</startMinute>
  <startSecond>0</startSecond>
  <repeatMode>0</repeatMode>
  <daysMask>
    <boolean>false</boolean>  <!-- Sunday -->
    <boolean>true</boolean>   <!-- Monday -->
    <boolean>true</boolean>   <!-- Tuesday -->
    <boolean>true</boolean>   <!-- Wednesday -->
    <boolean>true</boolean>   <!-- Thursday -->
    <boolean>true</boolean>   <!-- Friday -->
    <boolean>false</boolean>  <!-- Saturday -->
  </daysMask>
</com.xona.wf.schedule.WeeklySubSchedule>

PeriodicSubSchedule Example ​

Run every 2 hours:

xml
<com.xona.wf.schedule.PeriodicSubSchedule>
  <every>2</every>
  <everyScale>0</everyScale>  <!-- 0=hours, 1=minutes, 2=seconds -->
  <repeatMode>0</repeatMode>
</com.xona.wf.schedule.PeriodicSubSchedule>

MonthlyDateSubSchedule Example ​

Run on the 1st and 15th of every month at midnight:

xml
<com.xona.wf.schedule.MonthlyDateSubSchedule>
  <startHour>0</startHour>
  <startMinute>0</startMinute>
  <startSecond>0</startSecond>
  <repeatMode>0</repeatMode>
  <days>
    <int>1</int>
    <int>15</int>
  </days>
  <months>
    <boolean>true</boolean>   <!-- January -->
    <boolean>true</boolean>   <!-- February -->
    <boolean>true</boolean>   <!-- March -->
    <boolean>true</boolean>   <!-- April -->
    <boolean>true</boolean>   <!-- May -->
    <boolean>true</boolean>   <!-- June -->
    <boolean>true</boolean>   <!-- July -->
    <boolean>true</boolean>   <!-- August -->
    <boolean>true</boolean>   <!-- September -->
    <boolean>true</boolean>   <!-- October -->
    <boolean>true</boolean>   <!-- November -->
    <boolean>true</boolean>   <!-- December -->
  </months>
  <lastDayOfMonth>false</lastDayOfMonth>
</com.xona.wf.schedule.MonthlyDateSubSchedule>

CalendarSubSchedule Example ​

Run on dates defined in "BusinessHolidays" calendar:

xml
<com.xona.wf.schedule.CalendarSubSchedule>
  <startHour>6</startHour>
  <startMinute>0</startMinute>
  <startSecond>0</startSecond>
  <repeatMode>0</repeatMode>
  <calendar>BusinessHolidays</calendar>
</com.xona.wf.schedule.CalendarSubSchedule>

Repeat Mode Example ​

Daily at 9:00 AM, repeat every 30 minutes until 5:00 PM:

xml
<com.xona.wf.schedule.DailySubSchedule>
  <every>1</every>
  <startHour>9</startHour>
  <startMinute>0</startMinute>
  <startSecond>0</startSecond>
  <repeatMode>1</repeatMode>           <!-- 1 = repeat until time -->
  <repeatEvery>30</repeatEvery>
  <repeatEveryScale>1</repeatEveryScale> <!-- 1 = minutes -->
  <repeatHour>17</repeatHour>
  <repeatMinute>0</repeatMinute>
  <repeatSecond>0</repeatSecond>
</com.xona.wf.schedule.DailySubSchedule>

Complete Schedule Trigger Structure ​

xml
<trigger class="com.xona.wf.trigger.ScheduleTrigger">
  <name>MyScheduleTrigger</name>
  <triggerConfig class="com.xona.wf.config.ScheduleTriggerConfigObject">
    <schedule>
      <includeSchedules>
        <!-- One or more SubSchedule elements -->
      </includeSchedules>
      <excludeSchedules>
        <!-- Optional: SubSchedules that block execution -->
      </excludeSchedules>
      <timeZoneID>America/Chicago</timeZoneID>
      <preventConcurrency>true</preventConcurrency>
    </schedule>
  </triggerConfig>
</trigger>

Workload Automation and Orchestration