All field notes
Webhook guide 3 min read

How to Mock 400, 429, and 500 Webhook Responses

Turn a temporary endpoint into a controlled failure simulator and observe whether your webhook sender stops, waits, retries, duplicates work, or records a useful error.

Published August 3, 2026Facts verified August 3, 2026By Webhook Tester
mock webhook error responsewebhook 400 response testwebhook 429 retry testwebhook 500 response simulatortest Retry-After webhook

Interactive example

Failure response lab

Compare three failure contracts. The one-click action creates the 429 scenario by default.

POSTCaptured request
Content-Type
application/json
X-Event-Id
evt_invalid_400
{"event":"invoice.created","data":{"invoice_id":null}}

Configured response

400 Bad Request

Content-Type: application/json

{"error":"invalid_payload","field":"data.invoice_id"}

Synthetic data only. Never paste production tokens, signing secrets, personal data, or payment information into a public test endpoint.

One-click test setup

Creates a temporary bucket and applies this guide's expected response. You can inspect and delete it from the dashboard.

01

Use Controlled Failures Instead of Production Incidents

Happy-path webhook tests prove only that one request can receive a 2xx response. Real integrations must also handle invalid input, rate limits, and temporary receiver failures without losing events or creating duplicate side effects.

A temporary endpoint with a configurable response lets you repeat those failures on demand. Keep the sender code and synthetic event constant while changing only the HTTP response. That isolates retry policy from payload generation and network routing.

02

Choose the Correct Failure Contract

Use 400 when the receiver cannot process the request because the request itself is invalid. Repeating the same body usually cannot fix a missing identifier or malformed JSON. Use 429 when the receiver is rate limiting an otherwise valid request. Use 500 when the receiver encountered an unexpected condition and a later attempt may succeed.

The exact retry decision belongs to the sender’s documented contract. This lab is designed to reveal the current behavior, not to assume every provider treats a status identically.

Failure responses and the sender behavior to verify
ResponseMeaning in the testBehavior to verify
400 Bad RequestThe synthetic request is invalidStop or quarantine until the payload changes
429 Too Many RequestsThe receiver is temporarily rate limitingWait, apply jitter, and retry within a bound
500 Internal Server ErrorThe receiver failed unexpectedlyRetry transiently, then dead-letter or alert
2xx after failuresThe receiver recoveredProcess once and stop scheduled retries

Status codes communicate the HTTP outcome. Your application still needs a documented retry ceiling, idempotency key, and terminal failure path.

03

Run the 429 Scenario

The one-click action creates a bucket that responds with 429, an actual Retry-After: 30 response header, and a JSON body containing the same synthetic retry interval. Send an event with a stable X-Event-Id, record the time of every attempt, and observe whether the sender retries immediately or waits.

Open Response settings to change the header, body, or delay without changing the sender. A response delay is useful for testing timeout handling, while Retry-After shows whether a rate-limited sender honors explicit server guidance.

  • Record attempt timestamps and calculate the real delay
  • Confirm retries have a maximum attempt or time limit
  • Use jitter so many failed events do not retry simultaneously
  • Keep the same event ID across attempts so duplicates are detectable
04

Run the 400 and 500 Scenarios

For the 400 case, configure the response editor with the status and body shown in the lab, then send the invalid synthetic invoice. The sender should expose a useful terminal error or route the event for correction instead of repeatedly sending the same body.

For the 500 case, run enough attempts to observe the complete retry schedule. Then change the endpoint response to 200 without changing the event ID. Verify that the sender accepts recovery, cancels future retries, and causes the downstream business action at most once.

05

Verify Idempotency and Terminal Handling

Retries create at-least-once delivery. The receiver must claim a stable event identifier before performing a charge, message, fulfillment, or state transition. A database uniqueness constraint is stronger than an in-memory duplicate check when concurrent deliveries are possible.

Finish the test by checking the terminal path: dead-letter queue, failed execution record, alert, or manual review. A sender that silently stops after its last retry is difficult to operate even when its backoff timing is correct.

  • Count captured attempts for one stable event ID
  • Confirm successful recovery produces one business result
  • Confirm the last failed attempt creates an actionable record
  • Delete the temporary bucket when the retry experiment finishes

Common questions

Frequently asked questions

Should a webhook sender retry a 400 response?
Usually not without changing the request. A 400 response means the receiver considers the request invalid, so repeating the same payload can create a retry storm. Follow the specific provider contract.
What should happen after a 429 response?
A sender should respect the receiver’s retry guidance when provided, apply bounded backoff with jitter, and stop after a documented limit. Do not run many concurrent retries against a rate-limited service.
Why test a 500 response more than once?
A single attempt proves only error handling. Repeated controlled failures reveal the retry schedule, maximum attempts, duplicate-delivery behavior, logging quality, and final dead-letter or manual-review path.

Primary sources

Official references

Try it with a real request

Turn the guide into a test.

Open a temporary endpoint, send your payload, and inspect exactly what arrived.

Open the tester