โ† All guides

Mock APIs for n8n โ€” test HTTP Request nodes, retries, error workflows, and webhook triggers

Every n8n workflow has two halves that are hard to test honestly. Outbound: HTTP Request nodes calling third-party APIs you can't make fail on demand โ€” so Retry On Fail, timeout settings, and error branches ship unexercised. Inbound: Webhook triggers that need realistic deliveries, ideally with real signature headers, to prove the workflow parses them.

n8n's built-in answer is data pinning โ€” pin a node's output and build downstream against it. It's genuinely useful, and the docs are plain about its boundary: it's a development feature, not available in production executions, and because the pinned node never runs, the HTTP layer is skipped entirely โ€” retries, timeouts, 429s, and error workflows never execute. This guide covers the other half: a live, stateful mock API your HTTP Request nodes can actually call, that fails exactly when you tell it to. Every curl below was verified against production before publishing.

1. A stand-in API for the HTTP Request node

The public demo project is a seeded e-commerce API. Drop an HTTP Request node in a workflow and set the URL to:

https://mockbird.mockbird.workers.dev/m/demo/products?limit=2

Execute the node โ€” you get two product records, and writes work too: POST /m/demo/products creates a record you can GET back from a later node. Same query conventions as json-server (_page/_limit/sortBy/filters), so pagination loops are testable. Want your own schema instead of ours? One curl or one click, below.

2. Verify Retry On Fail actually retries โ€” deterministically

n8n's HTTP Request node has Settings โ†’ Retry On Fail with Max Tries and Wait Between Tries (ms) (the editor caps them at 5 tries / 5,000 ms). The problem is proving it works: real APIs don't fail twice and then recover on cue. ?mock_seq does exactly that:

# 1st request โ†’ 500, 2nd โ†’ 500, 3rd and later โ†’ real 200 response
curl -s -o /dev/null -w '%{http_code}\n' \
  'https://mockbird.mockbird.workers.dev/m/demo/products?mock_seq=500,500,200&mock_seq_key=myflow'
# run it four times: 500 500 200 200

Point the HTTP Request node at that URL, enable Retry On Fail with Max Tries 3, execute once: tries one and two eat the 500s, try three succeeds, the node goes green. Every response carries x-mockbird-seq: pos/len so you can see which step of the sequence each attempt hit. Use a distinct mock_seq_key per workflow so parallel tests don't share a counter, and &mock_seq_reset=1 to restart a sequence. Failed writes are not applied โ€” a POST that draws a 500 inserts nothing, which is exactly the semantics your retry logic should assume.

3. Trigger your error workflow from a URL param

Error workflows (an Error Trigger node, linked in Workflow Settings) usually get tested by hoping something breaks. Make it break on purpose:

https://mockbird.mockbird.workers.dev/m/demo/products?mock_status=500

With the node's On Error left at the default (stop workflow), that request fails the node, fails the execution, and fires your error workflow โ€” Slack alert, incident ticket, whatever it does. Remove the param and the same node returns 200. One URL parameter is the whole toggle, which makes it easy to keep a disabled "break glass" node in the workflow for drills. mock_status takes any code; combine with &mock_delay=2000 for slow-then-fail.

4. Timeouts and slow upstreams

curl -s -o /dev/null -w '%{time_total}\n' \
  'https://mockbird.mockbird.workers.dev/m/demo/products/1?mock_delay=3000'
# 3.17s

Set the HTTP Request node's Timeout below the delay and you can watch the timeout path fire โ€” then decide whether that should retry (ยง2) or fail into the error workflow (ยง3). mock_delay goes up to 5,000 ms; mock_jitter adds a random component if you want latency that isn't suspiciously constant.

5. Practice 429 handling before the real API rations you

n8n's own rate-limit guidance is Retry On Fail with a wait longer than the provider's window. Rehearse it against a simulated limit:

# allow 3 requests per 60s per client, then 429 with Retry-After
'https://mockbird.mockbird.workers.dev/m/demo/products?mock_ratelimit=3&limit=1'
# 4 rapid requests โ†’ 200 200 200 429

Responses carry x-ratelimit-limit / x-ratelimit-remaining / x-ratelimit-reset, and the 429 includes Retry-After โ€” the headers your Loop Over Items + Wait pattern should be reading.

6. See exactly what your workflow sends

When a workflow POSTs to a partner API and the partner says "malformed payload", you want the request, verbatim. Point the node at a bin instead:

curl -s -X POST https://mockbird.mockbird.workers.dev/m/demo/hooks/order-created \
  -H 'content-type: application/json' -d '{"orderId":123,"total":49.9}'
# โ†’ {"ok":true,"caught":"POST /hooks/order-created","body":{...},"receivedAt":"โ€ฆ"}

The demo's catch-all route echoes what it caught, and every hit โ€” method, path, headers, body โ€” lands in the public demo request inspector. On your own project, an empty project plus one ANY /* custom route is a private bin with a per-project inspector โ€” webhook.site without the 7-day expiry.

7. Fire realistic signed deliveries at a Webhook trigger

Mockbird projects can send outbound webhooks on every record change โ€” signed POSTs with x-mockbird-event, x-mockbird-delivery, and x-mockbird-signature: sha256=โ€ฆ (HMAC-SHA256) headers. That's a realistic stand-in for any signed-webhook provider. Aim it at your n8n Webhook node:

# point your project's webhook at the n8n URL (returns the signing secret)
curl -s -X PUT https://mockbird.mockbird.workers.dev/api/projects/YOUR_ID/webhook \
  -H "x-admin-key: YOUR_ADMIN_KEY" -H "content-type: application/json" \
  -d '{"url":"https://YOURNAME.app.n8n.cloud/webhook-test/abc123"}'

# instant test delivery, no record edit needed:
curl -s -X POST https://mockbird.mockbird.workers.dev/api/projects/YOUR_ID/webhook/test \
  -H "x-admin-key: YOUR_ADMIN_KEY"

For the Test URL, click Listen for Test Event in the editor first โ€” n8n registers it for 120 seconds, which is plenty for the webhook/test curl โ€” and the payload appears right in the editor. Switch to the Production URL once the workflow is Active. Then verify the signature in a Code node with the returned secret, and you've tested the part of webhook handling everyone skips. Delivery attempts (status, error, duration) are listed at GET โ€ฆ/webhook/deliveries. One honest constraint: deliveries travel the public internet, so a self-hosted n8n on localhost needs tunnel mode or a public URL โ€” we refuse to POST to private addresses. More recipes: sending test webhooks.

8. Your own API instead of the shared demo

One curl (or one click), no signup:

curl -s -X POST https://mockbird.mockbird.workers.dev/api/projects \
  -H "content-type: application/json" \
  -d '{"preset":"ecommerce"}'
# โ†’ {"id":"abc123xyz9", "adminKey":"โ€ฆ", ...}

Presets: blog / ecommerce / saas โ€” or define resources by hand, or import an OpenAPI spec, db.json, CSV, or HAR recording of the real API. Every simulation param above works on your project's URLs. Projects have a 10,000 requests/day cap โ€” workflow testing barely dents it.

Where pinned data is still the right tool

Fair's fair: for shaping expressions and building downstream nodes against a known payload in the editor, data pinning is faster than any mock server โ€” no network, no setup, works offline. Use it for that. Reach for a hosted mock when the thing under test is the HTTP layer itself: retries, timeouts, 429s, error workflows, signature verification, or any execution that runs in production mode, where pinned data doesn't apply. They compose โ€” pin the happy path, mock the failure paths.

Related: the Make (Integromat) version of this guide, testing loading and error states, send test webhooks with real signatures, request bins compared, simulating rate limits, and mocking third-party APIs generally.

Verification: all demo curls on this page (seq 500โ†’500โ†’200โ†’200, mock_status 500, 3.17s delay, 200 200 200 429 rate-limit run, bin echo + inspector log) were run against production on 5 Sep 2026 before publishing. n8n behavior โ€” pinned data unavailable in production executions, Retry On Fail settings and editor caps, Error Trigger linking, 120-second test-webhook window, tunnel mode for localhost โ€” is from n8n's official docs. We don't run your n8n instance; if a step here doesn't work, that's a bug: tell us.