Skip to main content

Deliveries and retries

A delivery is one event sent to one webhook. This page describes what a delivery request looks like, when it counts as successful, how failed deliveries are retried and what happens when an endpoint keeps failing.

The request​

POST /beepclock/webhooks HTTP/1.1
Host: integration.example.com
Content-Type: application/json; charset=utf-8
User-Agent: BeepClock-Webhooks/1.0
X-BeepClock-Webhook-Id: c5d8a2e7-4b19-4f63-8a0d-3e7b9c1f6a52
X-BeepClock-Event: timeEntry.created
X-BeepClock-Delivery: 8f2c6a1d-4e7b-5c93-a0d5-1b8e3f6c9a24
X-BeepClock-Attempt: 1
X-BeepClock-Signature: t=1791788292,v1=5d1f…c2a8

{"id":"8f2c6a1d-4e7b-5c93-a0d5-1b8e3f6c9a24","event":"timeEntry.created",…}

The body is the event envelope as compact JSON.

Headers​

HeaderDescription
X-BeepClock-Webhook-IdIdentifier of the webhook the delivery belongs to.
X-BeepClock-EventEvent type, for example timeEntry.created. See the event reference.
X-BeepClock-DeliveryIdentifier of the delivery, the idempotency key. Equal to the id field of the envelope.
X-BeepClock-AttemptAttempt number, starting at 1.
X-BeepClock-SignatureHMAC signature. See Verify signatures.

Custom headers configured for the webhook, for example Authorization, are added to every request, including test events. Their names cannot start with X-BeepClock- and cannot replace transport headers such as Content-Type, Host or User-Agent. Their values may contain only printable ASCII characters.

Transport​

PropertyRule
MethodPOST
URLhttps only, absolute, at most 2048 characters, without user:password@.
Target hostMust be publicly reachable. Loopback, private, link-local, carrier-grade NAT, documentation, multicast and reserved addresses, in IPv4 and IPv6, are blocked. The check runs when the URL is saved and again on every connection, after DNS resolution.
Timeout10 seconds.
RedirectsNot followed. A 3xx response counts as a failure.
SuccessAny 2xx status code. Everything else, including timeouts and connection or TLS errors, is a failure.
Response bodyIgnored.

Retry schedule​

When an attempt fails, BeepClock retries the delivery on a fixed schedule:

AttemptDelay after the previous attempt
1immediately
21 minute
35 minutes
430 minutes
52 hours
68 hours
724 hours

A delivery has at most 7 automatic attempts, spread over about 35 hours. After the last failed attempt the delivery is marked as failed. You can still resend it once the endpoint is fixed.

Automatic pausing​

BeepClock pauses a webhook automatically when:

  • the endpoint responds with 410 Gone. The delivery is not retried and the webhook is paused immediately. Return 410 only when the endpoint is permanently retired.
  • 20 deliveries in a row have failed. A delivery counts once, after all its attempts have failed, and any successful delivery resets the counter.

When a webhook is paused automatically, BeepClock emails the users of the account with the reason and a link to the webhook. The webhook list shows the reason in its status.

While a webhook is paused, automatically or with Pause sending:

  • deliveries that are waiting for a retry are not sent. They are marked as failed with the error Webhook is disabled or deleted.;
  • events that occur while the webhook is paused are not delivered later. After Resume sending, only new events are sent.

Delivery log​

The webhook page shows every delivery from the last 30 days, newest first, and can be filtered by status. Select a delivery to see:

  • each attempt with its HTTP status code, duration and error;
  • the exact payload that was sent;
  • when the next attempt is scheduled, if the delivery is still pending.

Resending a delivery​

Resend delivery in the delivery details sends the delivery again with the same delivery ID and the same body. The attempt number continues from the previous attempts: a delivery that succeeded on attempt 1 is resent as attempt 2.

Resending is available when the webhook is active and the delivery is no longer pending. A delivery that has been pending for more than an hour after its scheduled attempt, for example after an interrupted send, can also be resent.

If a resent attempt fails, the automatic retry schedule continues from that attempt number; from attempt 7 on there are no further automatic retries. A resent delivery counts towards automatic pausing like any other delivery.

Test events​

Send test event immediately sends a signed webhook.test event with the current secret and custom headers, and shows the response. A test event:

  • has a new random delivery ID each time and X-BeepClock-Attempt: 1;
  • is sent once and never retried;
  • is not added to the delivery log and does not count towards automatic pausing;
  • can be sent while the webhook is paused, to check the endpoint before resuming.

Idempotency and ordering​

Delivery is at least once: the same event can reach your endpoint more than once, for example when your 2xx response is lost on the way back.

  • The delivery ID (X-BeepClock-Delivery, equal to the envelope id) is deterministic for each pair of webhook and source event. Automatic retries and manual resends carry the same ID and the same body; only X-BeepClock-Attempt, t and the signature change.
  • Store the IDs you have processed and treat a repeated delivery as harmless.
  • The order of arrival is not guaranteed. A retry can deliver an older event after a newer one. Use occurredAt to order events about the same object.