TrigRun
Guides

Workflows and Webhook Triggers

Build step-driven jobs with HTTP steps, webhook waits, approval gates, and public trigger URLs.

TrigRun supports two step-driven job kinds:

  • workflow for schedule-driven multi-step jobs
  • webhook_trigger for multi-step jobs that start from an inbound POST instead of a schedule

These jobs use steps[] rather than the top-level request block used by standard cron, recurring, scheduled, and one-time jobs.

When to use them

KindStarts fromBest for
workflowA saved scheduleMulti-step API orchestration, approval flows, fan-out/fan-in jobs
webhook_triggerPOST /v1/triggers/:tokenInbound webhooks that need validation, transformation, and downstream calls

If you only need one outbound HTTP call on a schedule, stay with a normal job from the Jobs guide.

Supported step types

Step typeWhat it does
httpMakes an outbound HTTP request
wait_for_webhookParks the execution until a callback resumes it
approvalParks the execution until someone approves or rejects it

Every step needs a stable id. TrigRun stores per-step execution records under step_executions so you can see what happened at each stage.

Create a scheduled workflow

This example runs every hour, enriches a record, waits for approval, then writes the approved payload downstream.

curl -X POST https://api.trigrun.com/v1/jobs \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "hourly-review-pipeline",
    "kind": "workflow",
    "schedule": {
      "cron": "0 * * * *"
    },
    "steps": [
      {
        "type": "http",
        "id": "fetch",
        "url": "https://api.example.com/items/next",
        "method": "POST",
        "extract": {
          "item_id": "$.id",
          "item_name": "$.name"
        }
      },
      {
        "type": "approval",
        "id": "review",
        "message": "Approve this item before it is written downstream.",
        "on_timeout": "reject"
      },
      {
        "type": "http",
        "id": "store",
        "url": "https://api.example.com/items/store",
        "method": "POST",
        "body_template": {
          "id": "{{context.item_id}}",
          "name": "{{context.item_name}}"
        }
      }
    ],
    "max_workflow_duration_seconds": 1800,
    "max_concurrent_executions": 1,
    "on_success_url": "https://api.example.com/hooks/trigrun-success",
    "on_failure_url": "https://api.example.com/hooks/trigrun-failure"
  }'

Create an inbound webhook-triggered job

webhook_trigger jobs do not use a schedule. TrigRun generates a secret webhook_token for the job, and every inbound POST creates an execution with structured trigger_input.

curl -X POST https://api.trigrun.com/v1/jobs \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "github-dispatch",
    "kind": "webhook_trigger",
    "webhook_secret": "replace-with-your-shared-secret",
    "steps": [
      {
        "type": "http",
        "id": "fanout",
        "url": "https://api.example.com/github-events",
        "method": "POST",
        "headers": {
          "Content-Type": "application/json"
        },
        "body_template": {
          "event": "{{trigger.headers.x-github-event}}",
          "delivery_id": "{{trigger.headers.x-github-delivery}}",
          "action": "{{trigger.body.action}}",
          "payload": "{{trigger.body}}"
        }
      }
    ]
  }'

The job response includes:

  • webhook_token
  • webhook_secret_configured

To fire the job:

curl -X POST https://api.trigrun.com/v1/triggers/WEBHOOK_TOKEN \
  -H "Content-Type: application/json" \
  -H "X-Webhook-Secret: replace-with-your-shared-secret" \
  -d '{ "action": "opened", "number": 42 }'

If the token does not exist, TrigRun returns 200 { "received": true } to avoid token enumeration. If the shared secret is configured and does not match, TrigRun returns 401 unauthorized.

Template variables inside workflow steps

Workflow steps use a different template context than standard request jobs.

context.*

Values extracted by earlier steps are available under context.

{
  "body_template": {
    "id": "{{context.item_id}}",
    "score": "{{context.risk_score}}"
  }
}

trigger.*

Webhook-triggered jobs expose inbound request data under trigger.

{
  "body_template": {
    "delivery_id": "{{trigger.headers.x-github-delivery}}",
    "action": "{{trigger.body.action}}",
    "source_ip": "{{trigger.source_ip}}"
  }
}

Available roots are:

  • context
  • trigger

For standard request jobs, use the execution-scoped variables documented in Request Templates and Response Matching.

Extracting and persisting data

http, wait_for_webhook, and approval steps can all extract data.

FieldScope
extractStores values in the in-memory workflow context for the current execution
extract_to_contextPersists values to the cross-run job context store

The persisted store is available at:

  • GET /v1/jobs/:id/context
  • PATCH /v1/jobs/:id/context

PATCH /v1/jobs/:id/context accepts a simple object of string keys to string-or-null values. Setting a key to null deletes it.

Waiting for external input

wait_for_webhook

This step parks the execution and exposes a generated resume_url in the execution's waiting_payload.

The public resume endpoint is:

POST /v1/resume/:token

If the waiting token is still valid, the callback payload becomes the step input and the workflow continues.

approval

This step parks the execution and exposes:

  • review_url
  • approve_url
  • reject_url

Public approval endpoints:

GET  /v1/approvals/:token
POST /v1/approvals/:token/approve
POST /v1/approvals/:token/reject

Approval notifications can target the on_approval_required event documented in Notifications.

Concurrency, time limits, and callbacks

FieldMeaning
max_concurrent_executionsCaps parallel executions for the job. 0 means unlimited. Step-driven jobs default to 1.
max_workflow_duration_secondsMaximum total workflow runtime. Default 1800, max 7200.
on_success_urlOptional callback fired after a successful execution
on_failure_urlOptional callback fired after a failed execution

Success and failure callbacks receive the execution result after the workflow finishes. They are separate from notification channels.

Execution details you can inspect

Step-driven executions expose more fields than standard jobs:

  • step_executions
  • trigger_input
  • waiting_reason
  • waiting_payload
  • waiting_expires_at
  • final_output

Fetch them with:

curl "https://api.trigrun.com/v1/executions/EXECUTION_ID" \
  -H "Authorization: Bearer $TOKEN"

Current interface coverage

The REST API and OpenAPI spec expose the full step-driven surface.

The current CLI and MCP tooling focus on standard request-based jobs, executions, secrets, notifications, and monitors. For workflows and inbound webhook-triggered jobs today, use the API directly.