How to move a Pipedream HTTP trigger to an n8n Webhook
Updated October 13, 2026
Replace the Pipedream HTTP trigger with an n8n Webhook node. The URL changes from https://<id>.m.pipedream.net (or your Pipedream custom domain) to https://<your-n8n-host>/webhook/<path>, so every service that calls the old URL has to be updated. If the workflow sends its own response with $.respond() or the Return HTTP Response action, set the Webhook's Respond option to Using 'Respond to Webhook' Node and add a Respond to Webhook node. A Pipedream custom token becomes Header Auth on the Webhook node. Pipedream stops running workflows on March 31, 2027, so leave time to move every sender.
What changes between the two
| Pipedream HTTP trigger | n8n Webhook node | |
|---|---|---|
| URL | https://<id>.m.pipedream.net, any path and query |
https://<host>/webhook/<path>, plus a separate test URL |
| Methods | Any method | One method, or several with one output each |
| Default response | 200 with a short Pipedream HTML page |
Respond Immediately: a short message that the workflow started |
| Custom response | $.respond() or the Return HTTP Response action |
Respond to Webhook node |
| Authorization | None by default, a custom token, or Pipedream OAuth | None, Basic, Header or JWT auth |
| Request body size | 512 KB by default | 16 MB by default |
| Event data | body, headers, method, path, query, url, client_ip |
body, headers, params, query, webhookUrl, executionMode |
Both lower-case header names, so code that reads headers["content-type"] keeps working.
Step 1: Set up the Webhook node
- Add a Webhook node and name it
trigger. Pipedream code readssteps.trigger.event, so the same name keeps references easy to follow:steps.trigger.event.body.emailbecomes$('trigger').first().json.body.email. - Pick the HTTP method. Pipedream accepted any method. If your senders only POST, choose POST. Otherwise allow multiple methods, and n8n gives each method its own output.
- Set the path. Use something stable, such as
orders-created. Route parameters likeorders/:idwork too. Two published workflows can't share the same method and path. - Choose how to respond. Leave Respond on Immediately if Pipedream sent its default response. Pick Using 'Respond to Webhook' Node if any step called
$.respond()or used the Return HTTP Response action. - Set authentication, as in step 2.
- Publish the workflow. n8n registers the production URL only when you publish. Until then, only the test URL answers.
Workflow Exit does this when it converts a workflow. The path is the workflow name plus a short code, for example new-order-to-slack-3f9a1c, and it stays the same if you convert again, so senders only change once. If the input doesn't say which methods the endpoint accepted, the Webhook listens on GET, POST, PUT, PATCH, DELETE and HEAD, and a pass-through node named trigger joins the outputs.
Step 2: Carry over authorization
Pipedream HTTP triggers are public unless you set authorization, so check the trigger's configuration in Pipedream before you rebuild it:
- Custom token. Senders pass
Authorization: Bearer <token>. In n8n, set the Webhook's Authentication to Header Auth and create a credential with the nameAuthorizationand the valueBearer <token>. Senders keep the header they already send. No Pipedream export includes the token, so copy it from a sender's settings or your password manager. - Pipedream OAuth. Callers sent access tokens issued by your Pipedream OAuth client, and n8n has no way to check those. Move these callers to Header Auth or JWT auth.
- Checks in code. A code step that verified a token or signature from the headers keeps working, because the Webhook output has the same lower-cased
headers.
The IP(s) Allowlist option adds a second layer when senders have fixed addresses. When the Pipedream endpoint required authorization, a converted workflow gets a checklist item to set Header Auth, because otherwise anyone with the URL can call it.
Step 3: Rebuild custom responses
In Pipedream, $.respond() took a status, optional headers and a body. By default the response went out when the workflow finished. With immediate: true it went out at once, and the rest of the workflow kept running. If a workflow that uses $.respond() ended without calling it, Pipedream answered 400 with "No $.respond called in workflow".
n8n's Respond to Webhook node sends the response when it runs, and the nodes after it keep running. Put it where your code called $.respond(): at the end for the default timing, or earlier for immediate: true. Choose JSON or Text under Respond With, then set the Response Code and Response Headers options.
Take this Pipedream step:
export default defineComponent({
async run({ steps, $ }) {
const { email } = steps.trigger.event.body ?? {};
if (!email) {
await $.respond({ status: 422, body: { error: "email is required" } });
return $.flow.exit("missing email");
}
await $.respond({ immediate: true, status: 202, body: { queued: true } });
return { email: email.toLowerCase() };
},
});
Built by hand in n8n:
- Webhook node
trigger, with Respond set to Using 'Respond to Webhook' Node. - An If node that checks that
{{ $('trigger').first().json.body.email }}is not empty. - On the false output, a Respond to Webhook node with the JSON body
{"error": "email is required"}and Response Code422. Nothing comes after it. - On the true output, a Respond to Webhook node with the JSON body
{"queued": true}and Response Code202, followed by the rest of the workflow.
Watch these differences:
- A path with no response. If an n8n run finishes without reaching a Respond to Webhook node, the caller gets a standard
200, not Pipedream's400. An error before the Respond node returns500. - One response per request. The node answers once, from the first item it receives. A second Respond node in the same run is ignored.
- Mismatched settings fail. A Webhook set to respond through a node, with no Respond to Webhook node after it, stops with an error. So does a Respond node behind a Webhook set to Immediately.
- HTML pages. Since n8n 1.103.0, HTML responses are wrapped in a sandboxed iframe. Scripts can't reach the parent window and relative links break, so use absolute URLs.
- Files and streams. A step that answered with a Buffer or a stream needs the Respond to Webhook node's Binary File option instead.
When Workflow Exit converts a code step that calls $.respond(), it adds two nodes after it: an If node, <step> responded?, and a Respond to Webhook node, <step> respond. The Respond node sends the status the code set (200 if none) and its body. It takes the Content-Type from the code's headers, or uses text/plain for text and application/json for objects, and it forwards every other header name the code sets literally. When the step also calls $.flow.exit() after responding, another If node stops the run there. A Return HTTP Response action becomes a Respond to Webhook node, and a static response set on the trigger becomes the Webhook's own Response Code, Response Data and Response Headers options.
Step 4: Map the event data
Pipedream gave every step a steps.trigger.event object. The Webhook node's output has a similar shape, with a few gaps:
| Pipedream | n8n |
|---|---|
steps.trigger.event.body.email |
$('trigger').first().json.body.email |
steps.trigger.event.headers["x-signature"] |
$('trigger').first().json.headers["x-signature"] |
steps.trigger.event.query.page |
$('trigger').first().json.query.page |
steps.trigger.event.url |
$('trigger').first().json.webhookUrl |
steps.trigger.event.method |
The method you set, or the output the request arrived on |
steps.trigger.event.path |
No field. Use separate paths or route parameters (params). |
steps.trigger.event.client_ip |
No field. Read x-forwarded-for if your proxy sets it. |
Body-only events. A Pipedream HTTP trigger could pass just the request body as the event, so code read steps.trigger.event.email rather than steps.trigger.event.body.email. n8n always puts the body under body. Workflow Exit reads that setting from the export, or from Pipedream's payload-only HTTP source, and maps steps.trigger.event to the body for you. GitHub Sync repositories don't store trigger settings, so check those expressions by hand.
Large payloads. Pipedream limited request bodies to 512 KB unless the sender added pipedream_upload_body=1, in which case a step downloaded the body from raw_body_url. n8n accepts up to 16 MB directly, so drop the download step and the extra query parameter.
Form data. n8n puts multipart/form-data fields in body and uploaded files in binary data.
Inside converted code steps, the compatibility layer rebuilds Pipedream's event: method from the output the request came in on, url from webhookUrl, client_ip from the x-forwarded-for or x-real-ip header, and path as /. If a workflow branches on the path, split it into one Webhook per path. There's more on code in code steps on n8n Cloud.
Step 5: Test, then move the senders
- List every sender. Payment providers, Git hosts, form tools, internal apps and scheduled scripts can all hold the old URL. The events in Pipedream's inspector show who called recently.
- Test with the test URL. Click Listen for Test Event in the Webhook node and send a saved request:
curl -i -X POST "https://n8n.example.com/webhook-test/orders-created" \
-H "Authorization: Bearer $ORDERS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"email": "ana@example.com", "total": 120}'
- Compare responses. Check the status code, headers and body against what Pipedream returned for the same request.
- Publish, then switch one sender at a time. Senders use the production URL, with
/webhook/instead of/webhook-test/. Watch the workflow's Executions tab after each change. - Disable the Pipedream workflow. A disabled Pipedream HTTP workflow answers
404, so any sender you missed starts logging errors, which shows you what's left. - Finish before March 31, 2027. After that, the old URLs stop answering for good.
If your senders call a Pipedream custom domain that you own, there's one more option: point that hostname at a reverse proxy that forwards requests to n8n. Senders keep their URL, and you take on running the proxy.
The free migration report lists every HTTP trigger in your export, which ones need a Respond to Webhook node and which used authorization. It runs in your browser. For the rest of the move, see the Pipedream to n8n guide, and finish before the shutdown.
Frequently asked questions
Can I keep my Pipedream webhook URL?+
No. Pipedream endpoints stop answering when Workflows shuts down on March 31, 2027, and each n8n Webhook node has its own URL on your n8n instance. If your senders use a Pipedream custom domain you own, you can point that domain at a proxy that forwards to n8n.
What is the n8n equivalent of $.respond()?+
The Respond to Webhook node. Set the Webhook node's Respond option to Using 'Respond to Webhook' Node, then place a Respond to Webhook node where your code called $.respond(), with the same status, headers and body.
Why does n8n return 200 where Pipedream returned 400?+
When a workflow that uses $.respond() ended without calling it, Pipedream answered 400. In n8n, a run that ends without reaching a Respond to Webhook node gets a standard 200, so add a Respond node on every path where callers expect an error code.
How do I protect an n8n webhook like Pipedream's custom token?+
Set the Webhook node's Authentication to Header Auth and create a credential with the name Authorization and the value Bearer followed by your token. Senders keep sending the header they already use.
How large can a request to an n8n webhook be?+
16 MB by default, and self-hosted instances can change it with N8N_PAYLOAD_SIZE_MAX. Pipedream's default limit for a request body was 512 KB.