OXYGENOxygen/ Docs
Execution

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

KindFires when
apiA user or agent calls oxygen workflows call or oxygen_workflows_call
cronA cron expression matches the current minute
webhookAn HTTP POST hits the workflow webhook URL
eventA 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 a schedule can be written 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.

Your plan sets the fastest schedule it runs. After the repricing takes effect, Free runs at most every 15 minutes; paid plans can run every minute. oxygen limits show --section workflow --json reports your workspace's current minimum as workflow_limits.cron_min_interval_minutes, and --section all --band free also returns the Free band's values under plan_bands. A band filter does not change your current plan. The check uses the two closest fires, not the average: 0,5 9 * * * fires once a day but twice five minutes apart. A schedule whose fires come closer together than your plan allows is refused on apply, enable and Agent trigger creation with cron_interval_below_plan_minimum, which names the plan's minimum and a schedule that fits. A schedule that was already running when that happens keeps running at your plan's interval and is never deleted.

The builder's schedule picker names your plan's minimum and shows the refusal beside the cadence while you edit, before you publish. A running schedule held to your plan's interval shows a Schedule slowed banner on the workflow's page, and oxygen workflows get <id> --json returns it as workflow.trigger.slowedToPlanMinimum with the interval it fires at (planMinimumIntervalMinutes). The field disappears on the first fire after the schedule fits again, whether you upgraded or changed the schedule.

Schedules faster than every 15 minutes come back with a warning on apply/enable, and every 2 minutes or faster with a stronger one. The warning does not block — 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, and retries each bill one step, priced in the pricing reference; writing rows is free, and dry_run and smoke_test cost nothing. A month of a schedule is runs × steps per run × the step price: a 5-step workflow every 15 minutes runs 2,880 times, or 14,400 steps.

The per-run step count is not always what the graph looks like. A recipe bills 1 step per checkpoint its code emits at runtime, so one that loops over 100 items bills 100+ steps on every fire — 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 steps per run and the projected 30-day total), usage.credits_per_step, and usage.allowance.

enable refuses a schedule only when its cheapest possible month costs more than both your plan's monthly credits and the credits you can spend now; the refusal names the fastest cadence that fits.

Webhook

trigger:
  type: webhook
  trigger_id: inbound-lead

oxygen 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.

Each webhook trigger accepts a number of deliveries a minute that grows with your plan size: 600 on free, 1,500 on $49 and $99, 3,000 on $199 and $499, 6,000 on $999 and 12,000 on $1,999. Two limits apply at once, all deliveries to the trigger together and each sender IP on it (scope: per_trigger_and_sender_ip); they are equal, so one sender IP may use the whole rate and several IPs together still share it. Each accepted delivery starts one run with the whole body as its input, so sending several events in one delivery lowers the count only if the workflow reads an array. A delivery over the limit gets HTTP 429 with a Retry-After header and starts no run, so the sender can redeliver after that many seconds. oxygen workflows get and oxygen workflows apply return the trigger's own rate beside its URL under rate_limit (requests_per_window a window_seconds window, and what a delivery over it gets back under over_limit), the builder shows it under the URL, and an Agent webhook trigger carries the same rate_limit in oxygen agent trigger-create and oxygen agent triggers. oxygen limits show --json returns your plan's rate under webhook_ingress; the pricing reference lists every size.

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 --json

The 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> --json

rejected means the x-oxygen-workflow-secret header was missing or did not match. Stored delivery headers never include that header, so its absence there does not show which, and a rejected delivery starts no run and costs nothing.

A 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> --json

Replay 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> --json

get 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.id

Enable 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 --json

deliveries 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 --json

Other workflows subscribed to lead.qualified will fire. Live emission carries the same --approved / --max-credits pair, where --max-credits is the per-delivery ceiling.

  • 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.

On this page