Triggers Reference
Complete configuration reference for every workflow trigger type — schedule, webhook, record events, ITSM events, event bus, and manual.
Overview
A trigger is what starts a workflow run. Every workflow has exactly one trigger. The trigger defines what event to listen for and can include filters so the workflow only runs when conditions are met. Trigger payloads are available to nodes as {{trigger.*}}.
Schedule Trigger
Runs the workflow on a POSIX cron schedule. The trigger payload contains the scheduled fire time and workspace metadata.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| type | literal | required | — | Must be "schedule" |
| cron | string | required | — | POSIX cron expression: "min hour day month weekday". Seconds not supported. |
| timezone | string | optional | UTC | IANA timezone identifier. e.g. "America/New_York". Cron is evaluated in this timezone. |
| startAt | timestamp | optional | — | ISO 8601. Schedule is inactive before this datetime. |
| endAt | timestamp | optional | — | ISO 8601. Schedule is automatically deactivated after this datetime. |
| maxConcurrentRuns | integer | optional | 1 | Max simultaneous runs. If a run is still active when the schedule fires, behaviour depends on skipIfRunning. |
| skipIfRunning | boolean | optional | true | If true and a run is still active, skip this fire instead of queuing. |
{
"trigger": {
"type": "schedule",
"cron": "0 8 * * MON-FRI",
"timezone": "America/New_York",
"skipIfRunning": true
}
}
// Trigger payload available to nodes:
// trigger.scheduledAt — ISO timestamp of the scheduled fire time
// trigger.actualFiredAt — ISO timestamp of actual execution start
// trigger.workspace.slugCommon cron expressions
| Expression | Schedule |
|---|---|
| 0 * * * * | Every hour at :00 |
| 0 9 * * * | Every day at 9:00 AM |
| 0 9 * * MON-FRI | Weekdays at 9:00 AM |
| */15 * * * * | Every 15 minutes |
| 0 0 1 * * | 1st of every month at midnight |
| 0 8,17 * * MON-FRI | Weekdays at 8 AM and 5 PM |
| 0 0 * * SUN | Every Sunday midnight |
Webhook (Inbound) Trigger
FlowOS generates a unique inbound URL for each workflow with a webhook trigger. External systems POST to this URL to start a run.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| type | literal | required | — | Must be "webhook" |
| method | enum | optional | POST | POST · GET · PUT · PATCH. The HTTP method the webhook URL accepts. |
| authentication | enum | optional | none | none · hmac_sha256 · bearer · basic. How incoming requests are validated. |
| secret | string | optional | — | Required for hmac_sha256 and bearer auth. Stored encrypted. |
| allowedIps | string[] | optional | — | CIDR ranges allowed to call this webhook. Empty = allow all. |
| responseMode | enum | optional | async | async (200 immediately, run async) · sync (wait up to 30s, return run output). |
| responseBody | string | optional | — | Static JSON body to return immediately (async mode). Template expressions supported. |
| conditions | object[] | optional | — | Run only if body/header conditions match. See condition schema. |
{
"trigger": {
"type": "webhook",
"method": "POST",
"authentication": "hmac_sha256",
"secret": "{{secrets.GITHUB_WEBHOOK_SECRET}}",
"conditions": [
{ "field": "body.action", "operator": "in", "value": ["opened", "reopened"] },
{ "field": "body.pull_request.base.ref", "operator": "equals", "value": "main" }
]
}
}
// Generated URL: https://acme.flowos.io/webhooks/wf_01HZ.../inbound
// trigger.body.* — parsed request body
// trigger.headers.* — request headers
// trigger.method — HTTP method
// trigger.ip — sender IP addressRecord Event Trigger
Fires when a record in a DB Studio table is created, updated, or deleted. Supports field-level conditions.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| type | enum | required | — | record_created · record_updated · record_deleted · record_any |
| tableSlug | string | required | — | Slug of the table to watch. |
| conditions | object[] | optional | — | Filter conditions on the record fields. All must pass for the trigger to fire. |
| changedFields | string[] | optional | — | For record_updated: only fire if one of these fields changed. Empty = any change. |
{
"trigger": {
"type": "record_updated",
"tableSlug": "incidents",
"changedFields": ["status"],
"conditions": [
{ "field": "status", "operator": "equals", "value": "resolved" },
{ "field": "severity", "operator": "in", "value": ["P1","P2"] }
]
}
}
// trigger.record.* — full record after the change
// trigger.before.* — field values before the change (record_updated only)
// trigger.changes — array of { field, from, to } for changed fieldsITSM Event Trigger
Fires on specific ITSM lifecycle events — incident escalations, change approvals, SLA breaches, etc.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| type | literal | required | — | Must be "itsm_event" |
| event | string | required | — | The event type to watch. See the full event catalog in the Webhooks & Events docs. |
| conditions | object[] | optional | — | Conditions on the event payload fields. |
{
"trigger": {
"type": "itsm_event",
"event": "incident.sla_breached",
"conditions": [
{ "field": "resource.severity", "operator": "in", "value": ["P1","P2"] }
]
}
}
// trigger.event.* — full event payload (see event catalog)
// trigger.resource.* — the incident/change/problem record
// trigger.actor.* — who triggered the event (user or system)Event Bus Trigger
Fires when a message is published to a named event bus topic.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| type | literal | required | — | Must be "event_bus" |
| topic | string | required | — | Name of the event bus topic to subscribe to. |
| eventType | string | optional | — | Filter to a specific event type within the topic. Empty = all. |
| conditions | object[] | optional | — | Conditions on the event payload fields. |
| batchSize | integer | optional | 1 | Batch up to N messages into a single run. Available as trigger.batch array. |
| batchWindowMs | integer | optional | 0 | Collect messages for this many ms before starting the run (batching window). |
Event Trigger
Fires when a named platform event is emitted — e.g. request.created when a service catalog request is submitted. No polling; the workflow is invoked synchronously as the event is dispatched.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| type | literal | required | — | Must be "event" |
| eventName | string | required | — | Name of the platform event to listen for. e.g. "request.created" |
| conditions | object[] | optional | — | Filter conditions on the event payload fields. All must pass for the workflow to fire. |
// Trigger any workflow on every catalog request submission:
{
"trigger": {
"type": "event",
"config": {
"eventName": "request.created"
}
}
}
// Trigger payload available to nodes as ctx.payload.*:
// requestId — MongoDB ObjectId of the new request
// requestNumber — human-readable number, e.g. "REQ-0030"
// catalogItemId — ID of the catalog item requested
// requestedBy — user ID of the submitter
// workspaceId — workspace the request belongs to
// title — request title
// variables — key-value map of form field responses (catalog item variables)ctx.payload.catalogItemId to limit a workflow to a specific catalog item.Manual Trigger
Workflow can only be started via API call or the "Run now" button in the studio. No automatic firing.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| type | literal | required | — | Must be "manual" |
| inputSchema | object | optional | — | JSON Schema defining the expected input fields. Validated on trigger calls. |
| requiredScopes | string[] | optional | — | Token scopes required to trigger this workflow via API. Default: workflows:trigger. |
Trigger Condition Schema
All trigger types that accept conditions use this schema for each condition object:
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| field | string | required | — | Dot-notation path into the trigger payload. e.g. "body.event.severity" or "record.status". |
| operator | enum | required | — | equals · not_equals · in · not_in · contains · starts_with · ends_with · gt · gte · lt · lte · is_null · is_not_null · regex |
| value | any | optional | — | The value to compare against. For "in"/"not_in", pass an array. |