Webhook Guides
Webhook Debugging Guide
Debugging webhooks in production is hard when all you have is one failed request, one provider dashboard status, or one receiver log line. A webhook can fail before ingress, during source authentication, while routing, during destination delivery, inside the receiver, or after an apparently successful acknowledgment.
A reliable debugging workflow keeps every stage visible: the inbound request, the routed event, destination attempts, response bodies, retry timing, and the final recovery action.
What is webhook debugging?
Webhook debugging is the process of tracing an event through the delivery path until you can name the exact failure boundary. Instead of asking only whether the provider sent a webhook, you compare what FastHook captured, what routes matched, what destination was called, what response came back, and whether retry or replay is safe.
The best debugging runbooks separate ingress evidence from delivery evidence. This matters because a provider can receive 200 OK while a downstream destination still fails later.
Common webhook debugging symptoms
- The provider says it sent the webhook, but no request appears in your receiver logs.
- The provider shows
200 OK, but the expected downstream side effect never happened. - A destination returns
401,403,404,429, or5xx. - Signature verification fails because the receiver uses parsed JSON instead of the raw request body.
- A payload field changed and the receiver started returning validation errors.
- Retries created duplicate side effects because the receiver did not enforce idempotency.
- A route was paused, disabled, filtered, deduplicated, or pointed at the wrong destination URL.
FastHook debugging workflow
- Search a narrow time window for failed events or rejected requests.
- Open the event detail to read
failure_message,response_status, and payload data. - Open attempts for that event to compare each
attempt_number,trigger, response body, and requested URL. - Open the original request when you need raw payload, headers, query parameters, method, or rejection cause.
- Fix the receiver, destination URL, credentials, filter, transformation, or source authentication issue.
- Retry a single event first. Use request replay only when you need to run the original request through current routing again.
FastHook API behavior used by these examples
These examples match the current FastHook API implementation. Control API calls use a project API key or session token, tenancy is selected with x-team-id, and the examples use the /v1 prefix for requests, events, attempts, and retries.
- Event lists support
status,source_id,connection_id,destination_id,from,to,q, cursors, andlimit. Event statuses are uppercase, such asFAILEDandSUCCESSFUL. - Event detail at
/v1/events/:idincludes the event model and payload data when the payload is available. - Attempt lists support
event_id,order_by=created_at,dir, andlimit. Attempt models includeresponse_status,attempt_number,trigger,error_code,body,requested_url, andhttp_method. - Request lists support
status=acceptedorstatus=rejected,source_id,from,to,verified, cursors, andinclude=data. POST /v1/events/:id/retryredelivers one routed event through the same branch.POST /v1/requests/:id/retryreplays the original request through current source routing.
Webhook debugging examples
Find failed delivery events
curl "https://api.fasthook.io/v1/events?status=FAILED&source_id=src_q6z62b6py5o79b&from=now-24h&to=now&limit=20" \
-H "Authorization: Bearer fhp_xxx" \
-H "x-team-id: tm_3b5335b627084a838b"Retrieve one event with payload data
curl "https://api.fasthook.io/v1/events/evt_01jv8c4n9p3x7r2t6q5m1k0s8b" \
-H "Authorization: Bearer fhp_xxx" \
-H "x-team-id: tm_3b5335b627084a838b"Inspect delivery attempts for one event
curl "https://api.fasthook.io/v1/attempts?event_id=evt_01jv8c4n9p3x7r2t6q5m1k0s8b&order_by=created_at&dir=desc&limit=100" \
-H "Authorization: Bearer fhp_xxx" \
-H "x-team-id: tm_3b5335b627084a838b"Retrieve the original request
curl "https://api.fasthook.io/v1/requests/req_01jv8c3m7b2p4q9x6r5t1n0k8s" \
-H "Authorization: Bearer fhp_xxx" \
-H "x-team-id: tm_3b5335b627084a838b"Find rejected ingress requests
curl "https://api.fasthook.io/v1/requests?source_id=src_q6z62b6py5o79b&status=rejected&from=now-24h&to=now&limit=20&include=data" \
-H "Authorization: Bearer fhp_xxx" \
-H "x-team-id: tm_3b5335b627084a838b"Retry the failed routed event
curl -X POST "https://api.fasthook.io/v1/events/evt_01jv8c4n9p3x7r2t6q5m1k0s8b/retry" \
-H "Authorization: Bearer fhp_xxx" \
-H "x-team-id: tm_3b5335b627084a838b"Replay the original request through current routing
curl -X POST "https://api.fasthook.io/v1/requests/req_01jv8c3m7b2p4q9x6r5t1n0k8s/retry" \
-H "Authorization: Bearer fhp_xxx" \
-H "x-team-id: tm_3b5335b627084a838b"Failed event record example
{
"id": "evt_01jv8c4n9p3x7r2t6q5m1k0s8b",
"request_id": "req_01jv8c3m7b2p4q9x6r5t1n0k8s",
"connection_id": "web_nbbweTiOtzsm",
"destination_id": "des_TU9ioCk5EHUU",
"source_id": "src_q6z62b6py5o79b",
"status": "FAILED",
"attempts": 3,
"response_status": 504,
"failure_message": "timeout after 15s",
"error_code": "timeout",
"last_attempt_at": "2026-05-31T10:12:45.000Z"
}Failed attempt record example
{
"id": "att_01jv8c7r1a9m2k4p6x0z3n5q8s",
"event_id": "evt_01jv8c4n9p3x7r2t6q5m1k0s8b",
"destination_id": "des_TU9ioCk5EHUU",
"attempt_number": 3,
"trigger": "AUTOMATIC",
"status": "FAILED",
"response_status": 504,
"error_code": "timeout",
"requested_url": "https://billing.example.com/webhooks",
"http_method": "POST",
"body": {
"error": "receiver timed out before acknowledging the event"
}
}Automate a debugging snapshot with Node.js
const apiBase = "https://api.fasthook.io";
const token = process.env.FASTHOOK_API_KEY;
const teamId = process.env.FASTHOOK_TEAM_ID;
const eventId = "evt_01jv8c4n9p3x7r2t6q5m1k0s8b";
const headers = {
authorization: `Bearer ${token}`,
"x-team-id": teamId
};
const event = await fetch(`${apiBase}/v1/events/${eventId}`, { headers }).then((res) => res.json());
const attempts = await fetch(
`${apiBase}/v1/attempts?event_id=${eventId}&order_by=created_at&dir=desc&limit=20`,
{ headers }
).then((res) => res.json());
console.log({
event_status: event.status,
response_status: event.response_status,
failure_message: event.failure_message,
latest_attempt: attempts.models[0]
});Debugging checklist
- Use a narrow
fromandtorange before expanding the search. - Confirm whether the request was accepted or rejected before debugging destination code.
- Compare event status with the latest attempt status and response body.
- Check whether the failure is route configuration, credentials, schema drift, receiver timeout, or receiver code.
- Read destination response bodies before retrying; many receivers explain the exact validation or auth problem.
- Verify idempotency before retrying traffic that can create external side effects.
- Retry a single event before replaying a wider request or batch window.
Webhook debugging FAQ
What is webhook debugging?
Webhook debugging is the process of inspecting the inbound request, routing result, destination event, delivery attempts, response status, response body, and retry history to understand why a webhook integration failed.
Why can a provider show 200 OK while my app still fails?
A 200 response only means the webhook request was accepted at the ingress layer. Downstream routing, destination delivery, receiver processing, database writes, and async jobs can still fail after that acknowledgment.
Which FastHook record should I inspect first?
Start with the request record when you are unsure whether traffic reached FastHook. Start with failed events when you know ingress succeeded but a destination did not process the event.
When should I retry a failed webhook event?
Retry a failed event after you have identified the failure, fixed the receiver or route, and verified idempotency so the retry cannot create duplicate external side effects.
Try FastHook
Use FastHook to inspect request history, failed events, destination attempts, response bodies, and replay actions in one place. That gives your team enough evidence to fix webhook failures without guessing from isolated provider logs or receiver logs.