200–299 status within 10 seconds and the delivery is complete. Anything else — a 5xx, a timeout, a DNS failure, a refused connection — is retried automatically.
Schedule
A maximum of 5 attempts per delivery: the initial POST plus up to 4 retries with these delays:
After the 5th failed attempt the delivery is recorded as failed and no further retries are scheduled. Each attempt fetches your endpoint with a 10-second timeout.
Terminal failures are not retried
A4xx response is your endpoint’s explicit rejection — bad URL, auth failure, gone — so it is recorded as terminal and never retried. If your handler throws before reading the body (unknown route, missing auth), fix the endpoint rather than waiting for a retry that will not come.
Retires also halt permanently when the webhook is deleted or deactivated mid-retry. That produces a final delivery row with the error Webhook was deleted or deactivated; retries halted, so the log always ends in a terminal state instead of going silent.
Because redelivery is possible, handlers must be idempotent. Dedupe on the
X-Gork-Delivery header: it is deterministic per webhook, event, and attempt, so a repeated delivery of the same attempt carries the same id.Inspect deliveries
Every attempt — headers sent, status received, response body (truncated to 1000 characters), and error — is logged. Query the log to debug a silent endpoint:cURL
Response
GET /v1/webhooks/deliveries requires webhooks:read and accepts limit from 1 to 100 (default 50), newest first.
Debugging checklist
- Confirm the endpoint is subscribed to the event (
GET /v1/webhooks→subscribedEvents). - Check the deliveries log for
responseStatusanderror— a4xxmeans your side rejected it; a timeout means the handler took over 10 seconds. - Verify the URL is still correct and the webhook is active. Rotate the secret (
POST /v1/webhooks/{id}/rotate-secret) only if verification — not delivery — is failing.