Retries and failures

Answer 2xx within 10 seconds. A delivery is tried up to 7 times over about 33 hours, and an endpoint that fails for 72 hours is disabled until you enable it again.

What counts as delivered

An attempt succeeds when your endpoint answers any 2xx status within 10 seconds, with 5 seconds to connect. Any other status, a timeout, a failed connection, a TLS error or a redirect is a failed attempt. Deliveries do not follow redirects, so register the final URL.

Answer first and work later: store the event, queue what it starts and return 204. Work that takes longer than 10 seconds makes a delivered event look failed, and it comes again.

The retry schedule

A failed attempt is tried again after a wait that grows each time. Each wait counts from the attempt before it.

AttemptWhen
1Right after the event is recorded.
21 minute after attempt 1.
35 minutes after attempt 2.
430 minutes after attempt 3.
52 hours after attempt 4.
66 hours after attempt 5.
724 hours after attempt 6.

When attempt 7 fails, about 33 hours after the event, the delivery is failed. The event stays in GET /events for 90 days, so you can still read it from the feed.

See your deliveries

GET /webhook_endpoints/{webhook_endpoint_id}/deliveries lists the deliveries to one endpoint, newest first. Filter by status: pending while attempts remain, succeeded or failed once they end.

curl "https://api.submitator.com/v1/webhook_endpoints/we_4Xk9Lm2Qt7Wr3Nb8Vz5HcT/deliveries?status=pending" \
  -H "Authorization: Bearer $SUBMITATOR_API_KEY"
Response 200
{
  "object": "list",
  "data": [
    {
      "object": "webhook_delivery",
      "id": "wd_3Cr8Kx2Wq7Lt4Vb9Nz1HmP",
      "livemode": false,
      "endpoint": "we_4Xk9Lm2Qt7Wr3Nb8Vz5HcT",
      "event": "evt_6Lr3Kx8Wq2Nt7Vb1Rz5MpA",
      "event_type": "listing.action_required",
      "status": "pending",
      "attempts": 5,
      "next_attempt_at": "2026-10-08T17:49:31Z",
      "last_attempt": {
        "attempted_at": "2026-10-08T11:49:31Z",
        "http_status": null,
        "duration_ms": 10000,
        "error": "timeout"
      },
      "created_at": "2026-10-08T09:13:30Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}

last_attempt.error says why an attempt failed without a 2xx: timeout, connection_failed, tls_failed, redirect or blocked_address, when the host is not public. It is null when your endpoint answered, and http_status then holds the status it sent.

The endpoint itself sums up the last 7 days in delivery_summary: attempts, successes, and the time and status of the last attempt.

Send a delivery again

POST /webhook_deliveries/{webhook_delivery_id}/retry sends a delivery again now, whatever its status. Use it once you have fixed your endpoint, for the deliveries that failed meanwhile.

curl -X POST https://api.submitator.com/v1/webhook_deliveries/wd_3Cr8Kx2Wq7Lt4Vb9Nz1HmP/retry \
  -H "Authorization: Bearer $SUBMITATOR_API_KEY"

The endpoint must be enabled: a retry to a disabled endpoint returns 422 validation_failed.

When an endpoint is disabled

An endpoint with no successful delivery for 72 hours and at least 10 failed events is disabled: enabled becomes false and disabled_reason becomes failing. We email you when it happens.

A disabled endpoint gets no deliveries, but events go on being recorded in GET /events. Fix the endpoint, enable it again, and read the feed from your last cursor to catch up on what it missed.

curl -X PATCH https://api.submitator.com/v1/webhook_endpoints/we_4Xk9Lm2Qt7Wr3Nb8Vz5HcT \
  -H "Authorization: Bearer $SUBMITATOR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"enabled": true}'
Response 200 (some fields left out)
{
  "object": "webhook_endpoint",
  "id": "we_4Xk9Lm2Qt7Wr3Nb8Vz5HcT",
  "url": "https://hooks.northlight.test/listings",
  "enabled": true,
  "disabled_reason": null
}

You can disable an endpoint yourself with enabled false: disabled_reason is then requested. Deleting an endpoint drops the deliveries still waiting for it, and its events stay in the feed.

What does not count

Deliveries to your endpoints do not count toward your rate limit. Your calls to read deliveries, retry them or change an endpoint do.

What can go wrong

CodeStatusFix
endpoint_url_invalid422The URL is not a public https URL, or holds a user name or password.
validation_failed422A retry to a disabled endpoint, or an events value that is not a type or a group. errors says which.
quota_exceeded422Before your first purchase, test mode allows 3 webhook endpoints. Delete one first.
not_found404The endpoint or delivery belongs to the other mode, or was deleted.

Next steps