Triggers
API, cron, webhook, and event starts for workflows.
A trigger is the condition that causes a workflow to run. A workflow revision declares one trigger: API, cron, webhook, or event. The current trigger is visible in oxygen workflows get.
Four kinds
| Kind | Fires when |
|---|---|
api | A user or agent calls oxygen workflows call or oxygen_workflows_call |
cron | A cron expression matches the current minute |
webhook | An HTTP POST hits the workflow webhook URL |
event | A subscribed event is emitted (internal or from an integration) |
Every fire produces a run.
Cron
trigger:
type: cron
cron: "0 9 * * 1"
timezone: "America/New_York"Cron expressions are standard five-field, so the fastest cadence is once per minute — the scheduler evaluates schedules every minute. For sub-minute cadence use a webhook or event trigger (fires per delivery, no cadence floor), or batch the work inside one scheduled run.
Schedules faster than every 15 minutes come back with a warning on apply/enable, and every 2 minutes or faster with a stronger one. Neither blocks — confirm the cadence is intentional.
Use cron for recurring work such as weekly TAM refreshes, daily CRM hygiene, or scheduled enrichment audits.
Scheduled runs execute on Oxygen's managed workers; there is no separate per-run compute fee. Live workflow steps, tool calls, row writes, and retries each meter one automation action, priced in the pricing reference; dry_run and smoke_test cost nothing.
The per-run action count is not what the graph looks like. A recipe bills 1 action per checkpoint its code emits at runtime, so one that loops over 100 items bills 100+ actions on every fire, and a bulk row write bills 1 action per row — on a minute-level schedule that is a different order of magnitude from the same-looking three-node graph. Before arming a hot schedule read the observed burn, not the estimate: oxygen workflows get <id> --json returns usage.estimate (a floor), usage.observed (measured actions per run and the projected 30-day total), and usage.allowance.
Webhook
trigger:
type: webhook
trigger_id: inbound-leadoxygen workflows get <id> --json returns the webhook URL when the workflow has a webhook trigger. POST a JSON payload; the workflow receives it as input.
Workflow webhooks require an Oxygen secret by default because they can enqueue live workflow runs. Send it in x-oxygen-workflow-secret. Use secret_required: false only for provider callbacks that cannot send custom headers and whose downstream workflow effects are safe to expose publicly.
First publish and duplication return the shared secret once; Oxygen stores only its hash. Rotate a leaked or changed sender credential with a preview followed by explicit approval:
oxygen workflows webhooks rotate <workflow> --json
oxygen workflows webhooks rotate <workflow> --approved --jsonThe prior secret stops authenticating immediately when rotation commits, and the replacement is shown once. Rotation does not publish, enable, or run a workflow. The visual trigger inspector exposes the same confirmation and one-time handoff.
Inspect every received delivery—including rejected authentication and verified deliveries that did not start a run—with:
oxygen workflows webhooks deliveries --workflow-id <workflow-uuid> --jsonA verified delivery with outcome=ran that started a run can be replayed as a
new safe dry run from its exact original revision and payload:
oxygen workflows webhooks replay <delivery-id> --jsonReplay never sends the webhook again, mutates the original run, spends credits,
calls a paid provider, performs an external write, or runs that historical
revision live. It creates a durable, inspectable Workflow run and stores source
delivery/run lineage on that run, but it does not append a synthetic inbound row
to webhook delivery history. Supply --request-key when retrying an uncertain
client response: the same delivery/key returns the existing replay run instead
of creating another. Without one, the CLI generates a key for that invocation.
Oxygen internal reads and oxygen.http_json_request outbound GETs can still
execute.
Event
Start with the workspace catalog. It combines every trigger-safe event Oxygen produces internally, provider definitions for active connections with exact subscription readiness, and source/event pairs used by existing workflows:
oxygen workflows events list --kind builtin --json
oxygen workflows events get <catalog-id> --jsonget returns a ready-to-copy trigger with its source, event, and any preset
filters. Built-in events stay visible when setup is incomplete. In that case
readiness.status is needs_setup and includes the exact action to take. You
can keep that trigger in a disabled draft, but publish/enable refuses to arm it
until Oxygen can verify its producer.
The visual inspector turns those filters into explicit AND clauses. Each clause
selects a payload path and one supported operator: eq, neq, exists, or
not_exists. Comparison values keep their declared type, so text "true" is
different from boolean true. Editing a preset stores the clauses in the
revisioned trigger manifest and never changes the producer's catalog entry.
The built-in catalog includes Sequencer activity and terminal outcomes, CRM
timeline and signal events, and Meeting Notetaker completion. Connected
integration definitions are merged into the same picker before their event
subscription is enabled; those rows stay selectable as needs_setup and expose
the exact repair command. Publish requires both an active provider account and
the exact active subscription. Workspace-owned custom events emitted through
workflows events emit need no provider setup. The lower-level
integrations events commands manage provider subscriptions:
trigger:
type: event
source: instantly
event: email.reply_received
idempotency_key_path: message.idEnable an integration event before it can deliver provider events:
oxygen integrations events list --json
oxygen integrations events enable --source instantly --event email.reply_received --json
oxygen integrations events disable --source instantly --event email.reply_received --json
oxygen integrations events deliveries --jsondeliveries shows delivery status for provider events, which helps confirm that an external system actually sent the event.
API calls
oxygen workflows call <workflow-id> --input-json '{"id":"123"}' --mode dry_run --json
oxygen workflows call <workflow-id> --input-json '{"id":"123"}' --mode live --approved --max-credits 50 --json--mode is required, and a live call is refused without both --approved and --max-credits (see Modes). call is fire-and-forget: it enqueues the workflow and returns the run id. Use oxygen workflows tail <workflow-run-id> --json to wait for completion.
Emitting events from a workflow
oxygen workflows events emit --source tenant --event lead.qualified --payload-json '{"id":"lead_123","score":87}' --mode dry_run --jsonOther workflows subscribed to lead.qualified will fire. Live emission carries the same --approved / --max-credits pair, where --max-credits is the per-delivery ceiling.
Related
- Workflows — what triggers fire.
- Modes — the gate on a live call.
- Integrations — provider events that can act as triggers.
- Approvals — even triggered fires require approval before live external writes.