Triggers
Every workflow has exactly one trigger (dsl.Trigger), defining how an execution starts. The trigger's type and config are stored on the workflow DSL; OrcFlows wires up the corresponding webhook route, Temporal Schedule, or poller automatically when the workflow is enabled.
"trigger": {
"type": "schedule",
"config": { "cron": "0 9 * * 1-5", "timezone": "America/New_York" }
}
HTTP / Webhook
type: "http" — the workflow is triggered by an HTTP request to:
POST https://your-instance/webhooks/{workflowId}
GET https://your-instance/webhooks/{workflowId} (ping/test)
- The request body, headers, and query params are available to steps as
{{trigger.body...}},{{trigger.headers...}},{{trigger.query...}}. - If the workflow has a
webhook_api_keyset, requests must includeX-API-Key: <key>(manage via/api/v1/workflows/{id}/api-keys). - Synchronous mode:
POST /webhooks/{workflowId}/syncblocks until the workflow completes and returns its final output directly — useful for request/response integrations. Use awebhook_responsenode to shape that response.
Manual
type: "manual" — only runs when explicitly triggered from the dashboard or POST /api/v1/workflows/{id}/trigger. Combine with input_schema to render a form for ad-hoc runs.
Schedule (cron)
type: "cron" (config key schedule in the UI) — runs on a cron expression via a Temporal Schedule:
"trigger": { "type": "cron", "config": { "cron": "0 9 * * 1-5", "timezone": "America/New_York" } }
- Standard 5-field cron syntax, optional IANA timezone (defaults to UTC).
- Enabling/disabling the workflow pauses/unpauses the underlying Temporal Schedule (
PauseSchedule). GET /api/v1/workflows/{id}/schedulereturns next/recent fire times and fire count.- You can fire it immediately regardless of the cron via the schedule's "Run now" action (
TriggerScheduleNow).
Event triggers (pollers)
type: "event" with a config.source covers a family of polling triggers — a Temporal Schedule periodically checks an external service for new items and starts a workflow execution per item found:
| Source | What it polls for |
|---|---|
email | New emails matching filters (from, to, cc, subject, date) via IMAP. |
telegram | New messages, edited messages, callback queries, channel posts, inline queries via Telegram's getUpdates long-poll. |
slack | New messages, mentions, reactions, channels, members, DMs, thread replies in connected Slack workspaces. |
airtable | New/updated records in a base/table. |
typeform | New form responses. |
notion | New/updated pages in a database. |
google-sheets | New/updated rows in a spreadsheet. |
Each poller has its own Temporal Schedule (e.g. emailPollerScheduleID), so it can be paused/resumed independently when the workflow is enabled/disabled, and inspected via GET /api/v1/workflows/{id}/schedule.
Channel-specific webhooks
Some channels need their own webhook handling because the provider has a custom verification handshake:
- WhatsApp:
GET /webhooks/whatsapp/{workflowId}handles Meta'shub.challengeverification;POST /webhooks/whatsapp/{workflowId}receives inbound messages (Meta Cloud API or Twilio). - Instagram: same pattern —
GET/POST /webhooks/instagram/{workflowId}.
LiveKit (real-time voice)
type: "livekit" — the workflow is started by a LiveKit room/session event delivered to POST /webhooks/livekit (JWT-signature-verified). Used for voice agents and cold-calling flows — see LiveKit & Voice Agents.
Public API run
Independent of the configured trigger, any workflow can be invoked via the generic public endpoint:
POST /run/{workflowId}
protected by a workflow-scoped API key (see Deploying Workflows).
Enabling/disabling
PUT /api/v1/workflows/{id}/enable and .../disable turn the trigger on/off:
- For
http/manual triggers, this just toggles whether/webhooks/{id}accepts requests. - For
cronand event/poller triggers, this pauses/unpauses the corresponding Temporal Schedule — so disabling a workflow stops new executions without losing the schedule's history.
Next
- Workflows & the DSL
- Executions & Monitoring
- Deploying Workflows — chat widgets, public API keys, batch runs.