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).
Related
- Serve Flags — full flag reference
for
swamp serve