Skip to content

Webhooks API

Trigger pipelines via HTTP webhooks.

POST /api/webhooks/:pipeline-id

Execute a pipeline in response to an HTTP request. The pipeline can read the incoming request and optionally send an HTTP response before continuing execution in the background.

Signature Validation (Optional)

The server automatically detects the webhook provider from the request headers and applies provider-specific signature verification.

ProviderDetection headerSignature header
githubX-GitHub-EventX-Hub-Signature-256: sha256=<hex>
slackX-Slack-SignatureX-Slack-Signature: v0=<hex> + X-Slack-Request-Timestamp
generic(fallback)X-Webhook-Signature: <hex> or ?signature=<hex>

If the pipeline has a webhook_secret configured, requests must pass the provider's signature check. Requests that fail validation receive 401 Unauthorized.

Example

bash
curl -X POST http://localhost:8080/api/webhooks/my-pipeline \
  -H "Content-Type: application/json" \
  -H "X-Webhook-Signature: ..." \
  -d '{"event": "push", "branch": "main"}'

Pipeline API

Inside the pipeline, access the incoming request and respond:

typescript
const pipeline = async () => {
  const req = http.request();
  if (req) {
    // req.provider    — "github" | "slack" | "generic"
    // req.eventType   — e.g. "push", "pull_request", "event_callback"
    http.respond({
      status: 200,
      body: JSON.stringify({ acknowledged: true, provider: req.provider }),
      headers: { "Content-Type": "application/json" }
    });
  }

  // Pipeline continues running in the background
  await runtime.run({ ... });
};
export { pipeline };

Conditional execution — webhookTrigger(expression)

Gate execution on webhook metadata using an expr-lang boolean expression. Returns true for manual (non-webhook) runs so jobs are never silently skipped.

typescript
// Only run when a GitHub push event targets main
if (
  !webhookTrigger(
    'provider == "github" && eventType == "push" && payload.ref == "refs/heads/main"',
  )
) {
  return;
}

Available variables: provider, eventType, method, headers, query, body, payload (JSON-decoded body, or nil).

YAML pipelines use the webhook_trigger field on a job:

yaml
jobs:
  - name: deploy
    webhook_trigger: 'provider == "github" && eventType == "push"'
    plan:
      - task: deploy
        ...

When the expression returns false the job is recorded as "skipped". Manual triggers bypass the filter entirely.

See Webhooks guide for detailed examples (GitHub, Slack, conditional execution, custom signatures, etc.).