Input & Output
Timing metadata and execution context available to all downstream nodes after a scheduled trigger fires.
No External Input Data
The Scheduled Trigger fires based purely on time — there is no incoming request, no user payload, and no external data at the trigger moment. All output data is timing metadata generated by BizFirstAI's scheduler. Downstream nodes use this metadata to determine which time period to process, detect late executions, and build date-aware queries.
Output Ports
| Port Name | When Triggered | Description |
|---|---|---|
main |
At every scheduled fire time when enabled is true |
The primary output port. Carries scheduling metadata as a structured data object. Downstream nodes use this to determine the time window they should process, calculate date ranges, and write to audit logs. |
Output Data
| Key | Type | Description |
|---|---|---|
scheduled_time |
ISO 8601 String | The exact UTC time the workflow was supposed to fire, as determined by the cron expression. This is always a clean, rounded time. Example: 2024-06-15T02:00:00.000Z. Use this for date-range calculations (e.g., "process all records from yesterday") because it is deterministic and repeatable. |
actual_time |
ISO 8601 String | The actual UTC time the workflow execution began. May differ from scheduled_time by seconds due to scheduler overhead, or by longer intervals in catch-up execution scenarios. Example: 2024-06-15T02:00:02.143Z. |
scheduled_time_local |
ISO 8601 String with offset | The scheduled time expressed in the configured timezone with its UTC offset. Example for America/New_York: 2024-06-14T22:00:00.000-04:00. Useful for generating human-readable timestamps in reports and emails. |
timezone |
String | The IANA timezone name configured for the trigger, e.g., America/New_York. Passed through for use in date formatting downstream. |
is_catch_up |
Boolean | true if this execution is a catch-up run for a previously missed scheduled time. false for normal on-time executions. Use this flag in your workflow logic to skip notifications on catch-up runs or to handle catch-up data differently. |
execution_id |
String | Unique identifier for this execution instance. Use in audit logs, database records, and error reporting to correlate all activity within a single scheduled run. |
cron_expression |
String | The cron expression that triggered this execution. Included for audit and debugging purposes. |
retry_attempt |
Integer | The current retry attempt number. 0 means this is the first (non-retry) attempt. 1 means the first retry, and so on. Use to conditionally change behavior on retries (e.g., send an alert email on retry attempt 3). |
Data Flow Example
Below is the output object produced by the Scheduled Trigger when a nightly data sync workflow fires at 2:00 AM UTC. This is the data available to all downstream nodes.
{
"scheduled_time": "2024-06-15T02:00:00.000Z",
"actual_time": "2024-06-15T02:00:01.847Z",
"scheduled_time_local": "2024-06-15T02:00:00.000+00:00",
"timezone": "UTC",
"is_catch_up": false,
"execution_id": "exec_sched_4Nm7kRt9Wz",
"cron_expression": "0 2 * * *",
"retry_attempt": 0
}
Accessing Timing Data in Downstream Nodes
Use these expressions to build date-range queries and audit entries in downstream nodes:
| Expression | Returns | Common Use |
|---|---|---|
{{ $trigger.scheduled_time }} | "2024-06-15T02:00:00.000Z" | Anchor point for date-range calculations |
{{ $trigger.actual_time }} | "2024-06-15T02:00:01.847Z" | Audit log timestamps |
{{ $trigger.is_catch_up }} | false | Skip non-critical steps on catch-up runs |
{{ $trigger.retry_attempt }} | 0 | Trigger escalation alerts on repeated failures |
{{ $trigger.execution_id }} | "exec_sched_4Nm7kRt9Wz" | Reference key for all records written in this run |
Building Date Ranges from Scheduled Time
A common pattern is to compute the previous day's date range from the scheduled time, ensuring the query always covers the correct 24-hour window regardless of minor execution delays:
{
"query_date_from": "{{ new Date($trigger.scheduled_time).toISOString().split('T')[0] }}T00:00:00Z",
"query_date_to": "{{ new Date($trigger.scheduled_time).toISOString().split('T')[0] }}T23:59:59Z",
"report_label": "Daily Sync — {{ new Date($trigger.scheduled_time).toLocaleDateString('en-US', { timeZone: $trigger.timezone }) }}"
}
Always Use scheduled_time for Queries, Not actual_time
When building date-range queries in downstream nodes (e.g., "fetch all records from yesterday"), always use
$trigger.scheduled_time as your anchor, not $trigger.actual_time. The scheduled time is deterministic and consistent regardless of execution delays or retries. Using actual_time can lead to overlapping or missing data windows across runs.