Quick Answer
To return a custom response from an n8n workflow, set the Webhook node's Respond field to "Using ‘Respond to Webhook’ Node", then add a Respond to Webhook node at the end of the workflow. Set status code, headers, and body there. Common mistake: forgetting to change the Webhook node setting — without it, the Respond node is ignored.
n8n Respond to Webhook — Complete Guide
The Respond to Webhook node lets an n8n workflow return a custom response to the webhook caller. This guide covers how to wire it up correctly, the common errors, and what to do when you need more control than n8n offers.
When You Need Respond to Webhook
- Building a JSON API — the caller expects a structured response back
- Stripe Connect or platform webhooks that require a specific 200 body shape
- Returning validation errors (400) to a form submission
- Redirecting via a 302 Location header
- Returning custom rate-limit or auth errors (401, 403, 429)
The Correct Setup
Three steps — if any are missed, the node silently does nothing:
- Webhook node config: set Respond to Using ‘Respond to Webhook’ Node. (Default is "Immediately" — which means the workflow returns 200 the moment the trigger fires, ignoring any downstream Respond node.)
- Add the Respond node: drag in a Respond to Webhook node. Every branch that should return to the caller must eventually reach it. If a branch never reaches Respond, the caller hangs until n8n's timeout.
- Configure the response: status code, headers, and body can all reference expressions from prior nodes.
Example: JSON API Workflow
A workflow that validates a payload, looks up a record, and returns JSON:
Status: 200
Content-Type: application/json
Body:
{
"ok": true,
"id": "{{ $json.id }}",
"email": "{{ $json.email }}"
}On a validation failure branch, a second Respond node returns 400 with an error message.
Common Errors
"Webhook responded before workflow finished"
The Webhook node is set to "Immediately" respond. Switch it to "Using Respond to Webhook Node".
"Caller hangs and times out"
Some branch of the workflow does not reach a Respond node. Every branch — success, validation failure, error — must terminate in one.
"Returns 200 with empty body"
Usually the Respond node's Body field is set to a JSON expression that evaluates to undefined. Check that expressions resolve — use the test data panel.
"Binary data is base64-encoded"
The Respond node encodes binary fields as base64 by default. To return binary content (file download), set the Response Mode to "Binary".
"Queue mode makes it slow"
Respond to Webhook is the one n8n operation that loses the queue-mode latency benefit — the main process waits for the worker before responding. If the caller is latency-sensitive, consider returning an immediate 202 Accepted and processing async.
When Respond to Webhook Falls Short
- You need conditional response based on complex logic across many branches
- You want to simulate response scenarios for testing (delays, failures, random 5xx)
- You need mirror or echo mode — return the request body back to the caller unchanged
- You want to mock third-party APIs with rich response configs without building a workflow for each case
Requex.me Alternative: Response Config + Workflows
Requex splits the concerns: every webhook endpoint has a built-in response config (status code, body, headers, delays, failure simulation, template vars), and workflows handle the side effects separately.
Response modes available without writing any workflow:
- Normal: return a fixed body with templated variables
- Echo: return the incoming body back to the caller
- Mirror: return the full request details (headers, method, body)
- Empty: return 200 with no body
Template variables {{body.x}}, {{query.x}}, {{headers.x}}, and {{method}} work in the response body and headers. For dynamic logic, the workflow runs after the response is returned — senders see fast, consistent replies while the heavy work happens async.
FAQ
Can I return different responses based on the request?
Yes. Use an IF or Switch node and wire different branches to different Respond to Webhook nodes. Each one can return its own status code, headers, and body.
How do I return a 302 redirect?
Set status code 302 and add a Location header with the target URL. Body can be empty.
Why is my response JSON wrapped in quotes?
The Body field is being serialised as a string. Set the Response Mode to "First Incoming Item" or "All Incoming Items" to return the raw object, or configure the content type header to application/json.
Is there a faster way for simple mock responses?
If you only need static or templated responses without workflow logic, a purpose-built webhook tool is faster. See our mock server comparison for options.