How to Test Webhooks by Returning Custom Responses
Most webhook debugging tools let developers inspect incoming requests. But many integrations also depend on the response the endpoint returns—and testing only one side of that conversation is often not enough.
Payment providers retry on 500. CRMs disable integrations on repeated 4xx responses. Automation platforms pause workflows on timeouts. To test integrations properly, developers need to control both what they receive and what they send back.
Why Webhook Responses Matter
Webhooks are not one-way notifications. The calling service reads the HTTP response your endpoint returns and often makes decisions based on it. Depending on the status code, the sender may:
- Retry the request — most providers retry on 5xx responses and timeouts, sometimes for hours or days.
- Mark the webhook as failed — repeated non-2xx responses can flag the delivery as permanently failed.
- Disable the integration — some platforms automatically pause or disable webhook endpoints after sustained failures.
- Trigger alerts — 4xx responses may immediately notify the sender's monitoring system.
- Pause downstream workflows — automation tools like Zapier or Make halt a zap when the receiving endpoint returns an error.
Common response codes and their typical semantics in webhook integrations:
- 200 OK — delivery confirmed. No retry.
- 202 Accepted — payload received; processing asynchronously.
- 401 Unauthorized — authentication failure; may disable the endpoint.
- 404 Not Found — endpoint does not exist; no retry expected.
- 500 Internal Server Error — transient failure; retry expected.
For a broader breakdown of status code behavior, see HTTP status codes every developer should test.
The Problem with Traditional Request Catchers
Traditional request catchers—tools like Webhook.site and RequestBin—are built around one primary use case: inspecting what arrives at a URL. They do that well. Developers can:
- View the full request payload.
- Inspect HTTP headers, query parameters, and method types.
- Capture multiple requests in a session and compare them.
But most basic request catchers return a fixed 200 OK to every request. That means developers cannot:
- Test how the sender behaves when the endpoint returns a 500.
- Verify retry logic without setting up a real backend service.
- Simulate authentication failures to check integration error handling.
- Test delayed responses to see how timeouts are handled.
This gap forces developers to spin up custom Express servers, deploy temporary endpoints to staging, or write throwaway scripts just to simulate realistic response behavior. For more context on this limitation, see the best Webhook.site alternatives comparison.
What Is Custom Response Testing?
Custom response testing means configuring exactly what your endpoint returns to the calling service—before you write any production code. Instead of receiving requests passively, the endpoint actively participates in the integration test by returning a controlled response.
A configurable response typically includes:
- HTTP status code — control whether the sender sees a success, client error, or server error.
- Response body — return JSON, plain text, or an empty body to test how the sender parses responses.
- Response headers — include custom headers like
X-Request-ID,Retry-After, orContent-Type. - Response delay — introduce latency to simulate slow processing, network conditions, or timeout scenarios.
With these controls, a single request catcher URL becomes a realistic integration testing endpoint—not just a passive observer.
Example: Testing a Payment Webhook
Consider a Stripe-style payment webhook. Stripe sends a POST request to your endpoint when a payment succeeds:
POST /webhooks/stripe
Content-Type: application/json
Stripe-Signature: t=1234567890,v1=abc...
{
"type": "payment_intent.succeeded",
"data": {
"object": {
"amount": 4900,
"currency": "usd",
"id": "pi_3NxYZA..."
}
}
}Scenario 1: Successful delivery. Configure the request catcher to return 200 OK with an empty body. Stripe considers the webhook delivered and does not retry.
HTTP/1.1 200 OK
Content-Type: application/json
{}Scenario 2: Endpoint failure. Switch the response to 500 Internal Server Error. Stripe schedules a retry. Inspect the retried requests in the catcher to verify the retry interval, whether the payload is identical, and whether Stripe includes any retry-specific headers.
HTTP/1.1 500 Internal Server Error
Content-Type: application/json
{
"error": "Internal server error"
}This two-scenario test validates both the happy path and the retry path without writing a single line of backend code.
Example: Testing Retry Logic
Most webhook providers implement automatic retries when the receiving endpoint fails. Common retry triggers include:
500 Internal Server Error502 Bad Gateway503 Service Unavailable- Connection timeout (no response within the provider's threshold)
To test retry behavior, configure the request catcher to return one of these error codes, then watch the incoming requests panel. You can verify:
- How many retry attempts the provider makes.
- The time intervals between retries (exponential backoff vs fixed).
- Whether the payload is byte-identical across retries.
- Whether retry-specific headers like
X-Webhook-Attemptare included. - When the provider gives up and marks the delivery as failed.
To simulate a timeout, set a response delay longer than the provider's timeout threshold. The request will hang, and the provider will eventually close the connection and retry. This lets teams confirm retry behavior before it happens in production.
Example: Testing Authentication Failures
Integrations often include authentication tokens or signatures in the request headers. Testing how the integration handles authentication failures requires returning the right error codes:
HTTP/1.1 401 Unauthorized
Content-Type: application/json
WWW-Authenticate: Bearer realm="api"
{
"error": "Invalid or missing authentication token"
}Or simulate a permission error where the caller is authenticated but not authorized:
HTTP/1.1 403 Forbidden
Content-Type: application/json
{
"error": "This endpoint does not accept requests from this source"
}Returning these responses from a real URL lets you observe exactly how the sending platform behaves. Does it retry? Does it notify someone? Does it silently fail? Does it disable the integration? You can answer these questions during development rather than in production.
For a deeper dive into testing authentication-related status codes, see how to test API error responses.
How MockFlow Helps Test Both Sides of an Integration
MockFlow includes a Request Catcher that goes beyond passive request inspection. Developers get a live URL that receives requests and responds with whatever configuration they set.
Request inspection:
- Capture every incoming request in real time.
- Inspect the full request body, headers, query parameters, and method.
- View request metadata including timing and origin IP.
- Compare multiple requests side by side to verify payload consistency.
Response controls:
- Custom status code — return any HTTP status (200, 202, 401, 404, 500, and more).
- Custom response body — return JSON, plain text, or an empty body.
- Custom response headers — add any headers the sending service expects or reads.
- Configurable response delay — add milliseconds of latency to simulate slow processing or trigger timeout behavior.
This combination means developers can test both sides of the integration conversation without standing up temporary backend services or writing custom middleware.
For context on the broader webhook debugging workflow, see how to debug webhooks and inspect incoming requests.
Real-World Use Cases
Custom response testing applies across every type of integration that relies on webhooks or HTTP callbacks.
Webhook Development
During early development, before a real webhook handler exists, use a request catcher as a placeholder. Inspect payloads from the live provider, understand the data structure, and return appropriate status codes to prevent the provider from piling up retry attempts while the handler is being built.
Payment Provider Testing
Stripe, Paddle, and similar payment platforms send webhook events for payment success, failure, refunds, disputes, and subscription changes. Testing each event type—and each possible response code—confirms that your integration handles every payment lifecycle scenario, not only successful charges.
CRM Integrations
CRM platforms like HubSpot and Salesforce push updates when contacts, deals, or records change. Returning a 500 from the receiving endpoint shows whether the CRM will queue the update and retry, or silently drop it. Knowing this behavior before production prevents data loss in the integration.
Zapier Automations
Zapier sends webhooks as part of multi-step zap workflows. When a webhook step returns an error, the zap may pause, retry, or fail permanently. Testing these scenarios with controlled responses helps teams understand what happens to the rest of the workflow when one step fails.
Third-Party SaaS Integrations
Many SaaS tools offer webhook-based event notifications for user activity, billing changes, or status updates. Custom response testing confirms that slow responses do not cause duplicate deliveries, that auth headers are validated correctly, and that provider retry windows align with your system's recovery time.
Internal API Testing
Internal services that emit webhooks—job queues, data pipelines, event buses—benefit from the same approach. Use a request catcher to validate that internal producers send the correct payload format, include required headers, and handle receiver errors according to your team's SLAs.
Request Catcher vs Traditional Mock APIs
Request catchers and mock APIs overlap in some areas but serve different primary use cases. Here is a practical comparison:
| Capability | Request Catcher | Mock API |
|---|---|---|
| Receive Requests | Yes | Yes |
| Inspect Payloads | Yes — live view | Typically no |
| Inspect Headers | Yes | Typically no |
| Return Custom Responses | Yes — when supported | Yes |
| Simulate Delays | Yes — when supported | Yes |
| Replay Workflows | Partial | Limited |
| Integration Testing | Ideal | Good for outbound calls |
| Frontend Testing | Not primary use | Ideal |
Use a request catcher when a third-party service is pushing data to your endpoint and you need to observe what arrives and control what you return. Use a mock API when your own application is making outbound calls and you need to simulate the responses it receives. Many real workflows require both.
For a full overview of available tools, see the best mock API tools for developers guide, or read the API testing checklist for frontend teams.
Best Practices for Integration Testing
Effective integration testing with a request catcher goes beyond sending one request and calling it done. Here are practices that produce more reliable integrations:
- Test success responses first. Confirm the payload format is correct and the provider marks the delivery as complete before moving to error scenarios.
- Test failure responses intentionally. Return 500, 502, and 503 to understand how retries work for each provider before relying on them in production.
- Test retry behavior explicitly. Count incoming retry attempts, measure intervals, and confirm the payload is consistent across attempts.
- Simulate response delays. Test how the sender handles slow responses and verify that your timeout thresholds are set appropriately.
- Inspect request headers carefully. Authentication signatures, idempotency keys, and correlation IDs are often in headers—verify they are present and well-formed.
- Validate payload structure. Confirm field names, types, nesting, and optional fields match your integration contract before writing handlers.
- Verify authentication handling. Return 401 and 403 to confirm the sending platform does not silently ignore authentication failures.
- Test edge cases. Missing fields, empty arrays, unexpected types, and duplicate event IDs—catch these during testing, not in production.
- Document expected responses. Record which status codes trigger which provider behavior, and include this in integration documentation or runbooks.
Why This Workflow Saves Time
Without a request catcher that supports custom responses, testing integration behavior typically requires:
- A temporary Express or Fastify server deployed somewhere publicly accessible.
- Custom middleware to return different status codes based on test scenarios.
- A local tunnel like ngrok to expose the server to the external webhook provider.
- Manual coordination between the developer and the third-party service.
- Teardown and cleanup after testing is complete.
This setup can take significant time per integration and per test scenario. A request catcher with configurable responses removes most of this overhead. The endpoint is already public, the response is configurable in seconds, and all incoming requests are captured automatically.
The result is faster integration cycles, more thorough testing across response scenarios, and fewer surprises when a real webhook handler is deployed.
See how this fits into a broader testing strategy in the webhook debugging guide and the API error response testing guide.
FAQ
Why do webhook responses matter?
Webhook senders change behavior based on the HTTP response they receive. A 200 confirms delivery, a 500 triggers a retry, and a 401 may disable the integration. Controlling both sides of the conversation is necessary for thorough integration testing.
Can request catchers return custom responses?
Yes—when the tool supports it. Modern request catchers like MockFlow's Request Catcher let you configure the status code, body, headers, and delay returned to the caller. Basic tools typically return a fixed 200 OK and do not support custom response configuration.
How do I test retry behavior?
Configure the request catcher to return 500, 502, or 503, or set a long enough response delay to trigger a timeout. Most webhook providers retry automatically. Watch the incoming requests to count retries, check the intervals, and verify the payload is consistent.
What status codes should I test when building a webhook endpoint?
At minimum: 200 OK, 202 Accepted, 400 Bad Request, 401 Unauthorized, 404 Not Found, 500 Internal Server Error, and timeout. Each exercises different sender behavior and is worth documenting explicitly for each provider you integrate with.
Can I simulate delayed webhook responses?
Yes. A configurable response delay lets you test how integrations handle slow endpoints and connection timeouts without building custom infrastructure. Set the delay above the provider's timeout threshold to observe timeout behavior directly.
Start testing integrations faster with MockFlow
Use MockFlow's Request Catcher to inspect incoming webhook payloads and control the response your endpoint returns—status code, body, headers, and delay—all from one place.