Skip to Content
BuildTriggersWebhook

Webhook Trigger

Give your automation an HTTP URL that external apps, forms, and backends can call. Each accepted request starts a run with the posted payload.

At a glanceVerified in app · Oct 29, 2026
Use it to
Start a run when an external app, form, payment provider, or script sends an HTTP request
Find it
Tools → Start → Webhook
Cost
Free (0 Step credits to receive; downstream Steps use their normal rate)
Limits
10 MiB max request body · 60 s max held response · 1 MiB max custom response
Output
{{ 1.body.<field> }}, {{ 1.headers.<name> }}, {{ 1.query.<param> }}, {{ 1.method }}
Instead
Scheduler (recurring time-based runs) or Form Trigger (hosted web form)
Open in Glow ↗Connect AI via MCP ↗
Clones a Draft copy or builds deterministically via Glow MCP (0 Step credits, 0 AI tokens). Nothing runs automatically.
POST to your webhook URL
{
  "customer_name": "Acme Corp",
  "amount": 4500
}

Typeform, Stripe, GitHub or your own script sends JSON to the URL.

Set up and test your webhook

  1. Open your automation in the editor.
  2. Select Tools → Start → Webhook in the dock (or right-click the canvas).
  3. Click the Webhook Step to open its setup panel.
Verify it works
Run
Send the sample POST request above (or click Run step in Test & Debug)
You should see
The Executions tab records a Completed run, and {{ 1.body.amount }} resolves to 4500.

Reading what arrived

Default settingBody only: Off
  • Outputs method, path, query, headers, body, and bodyRaw.
  • Read posted JSON or form fields under {{ 1.body.<field> }}.
  • Use {{ 1.bodyRaw }} to verify vendor signatures in a Code Step.
Unwrapped payloadBody only: On
  • Emits the parsed body at the top level ({{ 1.<field> }}).
  • Scalar payloads sit under {{ 1.value }}; {{ 1.$full_result }} returns the full output.
  • Update downstream references when toggling Body only.
ReferenceWhat it reads (when Step 1 is the Webhook)
{{ 1.body.<field> }}Field from parsed JSON or form body (or {{ 1.<field> }} when Body only is on)
{{ 1.headers.<name> }}Lowercase request header (credential and signature headers read as [REDACTED])
{{ 1.query.<param> }}URL query parameter (?source=stripe → {{ 1.query.source }})
{{ 1.method }}HTTP method (POST, GET, PUT, etc.)
{{ 1.path }}Request path
{{ 1.bodyRaw }}Unparsed body string for verifying third-party signatures in a Code Step

For {"customer_name": "Acme Corp", "amount": 4500, "currency": "USD"}, pick fields from Workflow data ({{ 1.body.customer_name }}, {{ 1.body.amount }}, {{ 1.body.currency }}).

Filtering allowed HTTP methods

Tools → Start → Webhook accepts POST, GET, PUT, PATCH, DELETE, and HEAD. To reject other methods with 405 Method Not Allowed, use HTTP → New webhook request from Apps and select the allowed HTTP methods.

Locking the URL to one sender

Treat the webhook URL as a secret. Requests are unauthenticated until you set Shared Secret / Signature verification:

FieldBehavior
Shared secretOptional ({{ $secret.WEBHOOK_SECRET }}). Rejects unsigned or mismatched requests with 401 before starting a run.
Signature headerHMAC-SHA256 digest of raw body in hex or base64 (optional sha256= prefix). Defaults to x-glow-signature; set X-Hub-Signature-256 etc.

With Signature header left blank, only x-glow-signature is checked: a sender signing under another header name is rejected until you switch it to x-glow-signature or enter its header name in Signature header.

sign-webhook.mjs
import crypto from "node:crypto"; const rawBody = JSON.stringify({ event: "order.paid", orderId: "ord_123" }); const signature = crypto .createHmac("sha256", process.env.WEBHOOK_SECRET) .update(rawBody) .digest("hex"); await fetch(process.env.GLOW_WEBHOOK_URL, { method: "POST", headers: { "content-type": "application/json", "x-glow-signature": `sha256=${signature}`, }, body: rawBody, });

When Body only is off, Glow masks credential headers (authorization, proxy-authorization, cookie, set-cookie, x-api-key, x-glow-api-key) as [REDACTED]. Built-in signature headers (x-glow-signature, x-hub-signature, x-hub-signature-256) and any other header carrying the same signature (in hex or base64, with or without sha256=) are masked too. Vendor headers (stripe-signature, svix-*, x-slack-signature, x-shopify-hmac-sha256) stay readable for verification against bodyRaw in a Code editor Step.

Expand Poll execution results via API (optional) to poll results or pass an x-glow-correlation-id header.

Examples to copy

A form submission

Webhook ({{ 1.body.email }})CRM / Sheet Step

Point your form tool at the URL and send one test entry. Top-level fields resolve at {{ 1.body.name }} and {{ 1.body.email }}. Nested objects keep their structure inside body.

What to expect when it runs

What format to send

Send JSON (Content-Type: application/json) or form-encoded payloads. Other content types arrive as text.

Limits

LimitValueWhen exceeded
Maximum request body size10 MiB (10,485,760 bytes)Rejected before starting a run. Send a file URL or ID and fetch it downstream.
Held response timeout (lastStep / respondToWebhookStep)60 secondsCaller gets 504 {"error": "timeout"}; the run continues in the background.
Maximum custom response body1 MiBReturns 202 {"received": true} in Immediately mode, or 500 {"error": "response_not_sendable"} when held.

What the sender gets back

Set When to respond (responseMode) to reply immediately or wait for a Step result:

ModeValueBehavior
Immediately (default)"immediately"Replies on acceptance using Response status code (200), Response Content-Type (application/json), and Response body ({"success": true}).
When the last step finishes"lastStep"Holds up to 60 s and returns the unwrapped output of the last passing Step.
Using a Respond to Webhook step"respondToWebhookStep"Holds up to 60 s until the first passing Respond to Webhook Step sends its status, headers, and body.

In Immediately mode, returning an error status code does not cancel the run.

Status & responseMeaning
200 {"success": true}Active Webhook in Immediately mode accepted the request (or HEAD probe).
202 {"received": true}Automation is in Draft or trigger is disabled; no run started.
401Missing or invalid signature header for Shared secret.
409 {"error": "duplicate"}Held mode (lastStep / respondToWebhookStep) received a duplicate x-glow-correlation-id; no second run started.
500Held mode failed ({"error": "workflow_failed"}), missed Respond to Webhook ({"error": "no_response"}), or exceeded 1 MiB ({"error": "response_not_sendable"}).
503 with Retry-AfterTemporary capacity or rate-limit refusal; retry after delay.
504 {"error": "timeout"}Held response exceeded 60 seconds; run continues in background.

Duplicate deliveries

Each accepted request can start a new run. Prevent duplicates when senders retry:

  • Held response modes: Send a unique x-glow-correlation-id header per event. Retries return 409 {"error": "duplicate"} without starting a second run.
  • Immediately mode: Store event IDs in a Data Store (route lookups with Conditions) or serialize runs in Concurrency & queueing. Also pass an idempotency key to external write APIs.

What’s Next?

Last updated on

Search documentation

Start with a guide, or search by Step, task or error.