Skip to main content
If your server returns a non-2xx status, times out, or is unreachable, CallingBox retries the delivery with exponential backoff over roughly two days. You can also replay any delivery manually from the dashboard or API.

Retry schedule

AttemptDelay after previous attempt
1Immediate (at most ~2s after the triggering event).
2+1 minute
3+5 minutes
4+30 minutes
5+2 hours
6+5 hours
7+10 hours
8+24 hours
Each delay has ±20% jitter applied so failing endpoints don’t get retried in lock-step. After 8 attempts the delivery moves to status: "exhausted" and stops retrying. It stays queryable from GET /v1/webhook_deliveries and can be replayed manually.

What counts as a success

A delivery is considered successful when your server returns any 2xx status. Everything else (3xx, 4xx, 5xx, or network error) is a retry.
Return 200 OK immediately and move work onto a background queue on your side. Anything slower than 10 seconds times out and retries.

Idempotency

CallingBox sends the same CallingBox-Event-Id on every retry of a given event, including manual replays. Use it as the primary key in an idempotency table so repeated deliveries are safe.
const eventId = req.headers["callingbox-event-id"] as string;
if (await db.seen(eventId)) return res.sendStatus(200);
await process(event);
await db.markSeen(eventId);
res.sendStatus(200);

Auto-disable after repeated failures

If a single endpoint accrues 10 consecutive exhausted deliveries, CallingBox flips the endpoint to status: "disabled" with disabled_reason: "too_many_failures" to stop burning credits on a broken target. The successful delivery counter resets on any 2xx response. Re-enable from the dashboard or via:
curl -X PATCH https://api.callingbox.io/v1/webhook_endpoints/{id} \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"status": "enabled"}'
Re-enabling zeroes out the failure counter.

Manual replay

List recent deliveries:
curl "https://api.callingbox.io/v1/webhook_deliveries?status=exhausted&limit=20" \
  -H "Authorization: Bearer YOUR_API_KEY"
Replay one:
curl -X POST https://api.callingbox.io/v1/webhook_deliveries/{id}/redeliver \
  -H "Authorization: Bearer YOUR_API_KEY"
This resets the delivery to pending and enqueues it for the next worker tick. Since the event id is preserved, your consumer’s idempotency check will dedupe against the original attempt.

Inspecting failures

Each delivery row records:
  • attempt_count — total automatic attempts.
  • manual_retry_count — times you’ve clicked Resend.
  • last_response_status — HTTP status code of the most recent attempt.
  • last_error — the specific error (HTTP 502, connection reset by peer, url resolved to a private or reserved address, etc).
See the webhook delivery object for the full schema.