trigger.webhook
Webhook (trigger.webhook)
Start a workflow from an HTTP call. Activating the workflow registers a
public URL — /hooks/{environment}/{path} — and every delivery to it becomes
one execution.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
path | string | — | Letters, digits, -, _. Unique per environment; a collision with another workflow fails activation with a 409. |
method | select | POST | GET / POST / PUT / PATCH / DELETE. Other methods get a 405. |
response_mode | select | immediate | immediate answers 200 {execution_id} as soon as the run is queued; wait_for_completion holds the request open for the workflow's response. |
verify_signature | boolean | false | Reject deliveries whose HMAC-SHA256 signature over the raw body doesn't match the attached webhook_hmac credential. |
signature_header | string | X-Signature-256 | Header carrying the hex signature (visible when verification is on). |
The trigger item
Each delivery becomes one item:
{
"headers": { "content-type": "application/json", "...": "..." },
"params": { "path": "your-path" },
"query": { "src": "ad" },
"body": { "msg": "ping" }
}
body is parsed by content type:
- JSON content types parse to the JSON value. If a caller claims JSON but sends something unparseable, the raw text is kept — the payload is never silently dropped.
- Form bodies (
urlencodedormultipart) become a dict of fields. Multipart file parts land in$binary(name → file ref), so an inbound attachment flows to any binary-aware node downstream. - Anything else arrives as raw text (invalid UTF-8 is replaced, never an
error). An empty body is
null.
Response modes
immediate— the caller gets200 {"execution_id": …}instantly.wait_for_completion— the request stays open until the run finishes. Pair with Respond to Webhook to build the status/body/headers; without one, the last node's output items are returned. A failed run answers500with the error message and execution id; if the run outlives the wait timeout (30s default) the caller gets202 {execution_id}and the execution keeps running.
Signature verification
Attach a webhook_hmac credential (the secret never lives in the workflow
JSON) and enable verify_signature. The signature is HMAC-SHA256 over the
raw request body, sent as hex in the configured header — a GitHub-style
sha256= prefix and uppercase hex are both accepted. Every rejection is the
same 401, so a prober can't distinguish a missing header from a wrong secret.
Quirks & tips
- Test without activating: the ▸ control on the node registers a one-shot
listen URL (
/hooks-test/...) — the first delivery fires the workflow and lands on the canvas like a run. - Repeated query keys (
?a=1&a=2) flatten to a dict — the last wins. Same for repeated form field names. - A
\u0000(NUL) character anywhere in the payload is replaced with�— Postgres can't store it, and a public endpoint must not 500 on hostile input. - The unprefixed URL
/hooks/{path}serves the default environment; dev and prod each own theirpathnamespace. - Deactivating the workflow (or deleting it) removes the registration — the URL 404s immediately.
Related
- Respond to Webhook — build the response under
wait_for_completion. - Form trigger — hosted page instead of raw HTTP.
- HTTP Request — the outbound counterpart.