Respond to Webhook
Respond to Webhook (respondToWebhook) sends a custom HTTP response to the caller of a Webhook Trigger. Set the trigger’s When to respond mode to Using a Respond to Webhook step.
At a glance
Last verified: Nov 4, 2026- Use it to
- Return a custom HTTP status code, headers, JSON/text body, or redirect to a waiting Webhook caller
- Cost
- 1 Step credit per execution
- Limits
- 1 MiB max response body · Caller waits up to 60 seconds
- Find it
- Tools → Data → Dev tools → Respond to Webhook
- Output
{{ N.statusCode }},{{ N.headers }},{{ N.body }}- Instead
- Webhook Trigger in When the last step finishes mode (when the final Step's output is the reply)
- Applies to
- All workspaces (Free & Paid)
- Owner
- Glow Docs & Engineering
In held-request mode (when the Webhook Trigger has When to respond set to Using a Respond to Webhook step), Glow holds the caller’s HTTP connection open for up to 60 seconds. When the first passing Respond to Webhook Step finishes, Glow sends its status code, headers, and body immediately. Downstream Steps continue running in the background. When When to respond is Immediately instead, a Live automation replies 200 OK with {"success": true}. A Draft automation returns 202 Accepted with {"received": true} without starting a run.
Setting it up
Set the Webhook Trigger to wait for this Step
Select your Webhook Trigger at Step 1 and set When to respond (responseMode) to Using a Respond to Webhook step.
Add Respond to Webhook
Open Tools → Data → Dev tools in the dock and select Respond to Webhook. Connect it on the branch that should reply to the caller.
Configure the response
Choose how to reply under Respond with (respondWith):
| Option | Value | Fields & behavior |
|---|---|---|
| JSON (default) | "json" | Sends Body (body) as application/json (leave objects, lists, numbers, and booleans unquoted like "profile": {{ 2 }} to preserve native JSON types). Set Status code from 200 to 599 (default 200). |
| Text | "text" | Sends Body as text/plain; charset=utf-8 (unless you set a custom Content-Type header). |
| Redirect | "redirect" | Sends a Location header to Redirect URL (redirectUrl, must start with https://, up to 2,048 characters) with status 301, 302, 303, 307, or 308 (defaults to 302). |
| No body | "noData" | Sends status and headers with an empty body (Status code 204, 205, or 304 also send no body automatically). |
Under Optional Props, add up to 50 Headers ({ name, value } pairs). Allowed headers include content-type, cache-control, content-language, etag, last-modified, expires, vary, retry-after, and custom x-* headers. Hop-by-hop, cookie, CORS, and security headers are refused.
Do not return credentials in a webhook response. Workspace secrets and API keys ({{ $secret.* }}, {{ $key.* }}, or sealed variables) are refused with SECRET_IN_UNSAFE_SINK.
What it passes on
The Step records the response it sent so downstream Steps (or your test trace) can inspect it:
| Reference | Type | What it holds |
|---|---|---|
{{ N.statusCode }} | Number | The HTTP status code sent to the caller (for example 200 or 302). |
{{ N.headers }} | Record | Normalized lowercase map of the headers sent with the reply. |
{{ N.body }} | Text or null | The exact response text sent, or null for No body and Redirect. |
If multiple Respond to Webhook Steps run, the first passing Step sends the HTTP reply. Later executions record their output without overwriting the sent response.
Limits and held-request statuses
Callers can pass an optional x-glow-correlation-id request header when calling a held webhook (Using a Respond to Webhook step or When the last step finishes) to prevent duplicate executions on client retries. Every held-webhook error response returns a JSON object with {"error", "message", "executionId"}:
| Limit or situation | Behavior |
|---|---|
| Maximum held request wait | 60 seconds. If the Step has not run within 60 seconds, the caller receives 504 (error: "timeout") with executionId, and the run continues in the background. |
| Maximum response body size | 1 MiB (1,048,576 bytes). Larger or invalid bodies return 500 (error: "response_not_sendable") with executionId. |
| Run finishes without reaching Respond to Webhook | The caller receives 500 (error: "no_response") with executionId. |
| Run fails before reaching Respond to Webhook | The caller receives 500 (error: "workflow_failed") with executionId. |
Request received but no run started (not_started) | The caller receives 500 (error: "not_started") with executionId when the webhook was changed, turned off, or the run was refused. |
Duplicate x-glow-correlation-id on a held webhook mode | Returns 409 (error: "duplicate") with the existing run’s executionId immediately without starting a second run. |
Examples to copy
1. Return a JSON lookup
Look up a customer record in a Data Store and return it synchronously as JSON, then log the access in the background:
- Set the Webhook Trigger at Step 1 to When to respond: Using a Respond to Webhook step.
- Add Data Store → Get a record (or create it) at Step 2 using
{{ 1.body.customerId }}(with Include record details off so Step 2 outputs{"tier": "enterprise", "seats": 25}). - Add Respond to Webhook at Step 3 with Respond with: JSON, Status code:
200, and Body:
{
"customerId": "{{ 1.body.customerId }}",
"profile": {{ 2 }}
}Caller request (curl):
curl -X POST "https://api.getglow.ai/webhooks/wh_01J9..." \
-H "Content-Type: application/json" \
-H "x-glow-correlation-id: req-1042" \
-d '{"customerId": "cust_42"}'HTTP response received by the caller (200 OK):
{
"customerId": "cust_42",
"profile": {
"tier": "enterprise",
"seats": 25
}
}Verify it works
- Run
- Set the Webhook Trigger to Using a Respond to Webhook step, configure Status code 200 and a JSON body, and run a test
- You should see
- The Step outputs
{{ N.statusCode }},{{ N.headers }}, and{{ N.body }}, and the test trace records the webhook response.
What’s Next?
- Webhook Trigger →: configure signature verification and response modes.
- Make outbound API calls with HTTP Request.