Skip to main content

WEBHOOKS

The --webhook flag on swamp serve registers an HTTP endpoint that triggers a workflow when an incoming request arrives. The flag is repeatable — pass it multiple times to register several endpoints.

Spec format

--webhook '<route>:<workflow>:<secret>[:<scheme>[:<header>[:<prefix>]]]'
Field Required Description
route Yes URL path for the endpoint (e.g., /hooks/github)
workflow Yes Workflow to trigger on valid requests
secret Yes Signing secret or secret indirection reference
scheme No Provider scheme (default: github). See Provider schemes
header No Custom header name (generic scheme only)
prefix No Expected value prefix (generic scheme only)

Provider schemes

Each scheme defines how the incoming request signature is verified.

Scheme Algorithm Signature header Notes
github HMAC-SHA256 X-Hub-Signature-256 Default when scheme is omitted
linear HMAC-SHA256 Linear-Signature
stripe HMAC-SHA256 Stripe-Signature Stripe signing protocol (timestamp + payload)
slack HMAC-SHA256 X-Slack-Signature
generic HMAC-SHA256 Custom (via <header>) Requires a header name; optional prefix

Secret sources

The <secret> field supports indirection so signing secrets do not appear as literal values in process arguments.

Prefix Source Example
@env=VAR_NAME Environment variable VAR_NAME @env=WEBHOOK_SECRET
@file=/path File contents (trailing newline trimmed) @file=/run/secrets/webhook
(plain string) Literal value (backward compatible) mysecret

The server reads the resolved secret at startup. If the environment variable is unset or the file cannot be read, the server refuses to start.


CEL context

When a workflow is triggered by a webhook, the webhook.* namespace is available in CEL expressions within that workflow.

Field Type Description
webhook.body dyn Parsed JSON body (object or array), or raw string for non-JSON payloads
webhook.headers map<string, string> Request headers
webhook.route string Matched route path
webhook.body.action == "opened"
webhook.headers["X-GitHub-Event"] == "issues"

Examples

GitHub (default scheme)

swamp serve --webhook '/hooks/github:on-push:@env=GITHUB_WEBHOOK_SECRET'

Linear

swamp serve --webhook '/hooks/linear:on-issue:@env=LINEAR_SECRET:linear'

Stripe

swamp serve --webhook '/hooks/stripe:on-payment:@env=STRIPE_WEBHOOK_SECRET:stripe'

Slack

swamp serve --webhook '/hooks/slack:on-command:@env=SLACK_SIGNING_SECRET:slack'

Generic

swamp serve --webhook '/hooks/custom:on-event:@env=CUSTOM_SECRET:generic:X-Custom-Token:Bearer'

The generic scheme computes an HMAC-SHA256 digest of the request body using the resolved secret as the key, then compares it against the value of the X-Custom-Token header (after stripping the Bearer prefix).