Delivery and retries
What Doorloom does with your response code, what happens while you are down, and how you come back.
The request
Doorloom sends a POST with a JSON body to the webhook URL you registered.
Answer with any 2xx within 10 seconds. The response body is ignored entirely —
there is nothing you can put in it that Doorloom reads.
Content-Type: application/json
Accept: application/json
User-Agent: Doorloom-Webhooks/2026-09
X-Doorloom-Signature: t=1759312504,v1=5f2a9c…
X-Doorloom-Event-Id: 01J6Y0Q8ZK3N4V6M7P8R9S0T1U
X-Doorloom-Event-Type: availability.changed
X-Doorloom-Sequence: 1042
X-Doorloom-Delivery-Attempt: 1
X-Doorloom-Integration: acme-pms
There is no separate timestamp header. The timestamp lives inside
X-Doorloom-Signature as t=. See
Verifying signatures.
Acknowledge first, process later
What your status code means
| Field | Type | Description |
|---|---|---|
2xx
|
success | Marked delivered. Doorloom immediately sends the next event. |
408, 429, 5xx
|
retry | Treated as “you are having a bad moment”. Retried on the ladder below. Nothing later is sent until this event succeeds. A Retry-After on a 429 is honoured, clamped to between 60 and 300 seconds. |
timeout or connection error
|
retry | Same as above. |
any other 4xx
|
dead-letter | Treated as “this specific payload is unacceptable to you”. The event is dead-lettered, Doorloom staff are alerted, and delivery continues with the next event. |
410
|
gone | Treated as “this endpoint is retired”. Delivery pauses until a probe succeeds or staff resume it. |
Never answer 4xx for a problem that is really yours
400 means do not bother resending this, I
will never accept it, and Doorloom takes you at your word — that event is dropped from your
feed for good. If your database was merely down, answer 500. Returning
400 from a generic error handler is the single most damaging thing a partner
integration can do here, because the data loss is silent on your side.The retry ladder
A retryable failure is retried after, in seconds:
60, 300, 900, 1800, 3600, 7200, 7200, 7200, …
That is 1 minute, 5, 15, 30, 1 hour, 2 hours, then every 2 hours, up to 12 attempts in total — roughly 12 hours of trying. After the twelfth the event is marked dead and staff are alerted.
X-Doorloom-Delivery-Attempt tells you which attempt you are looking at, starting
at 1.
Head-of-line blocking is deliberate
While an event is being retried, no later event is delivered. Your feed stops at the failure and resumes from it.
This is intentional. It is what lets you rely on events arriving in sequence order, which is
what makes the apply-if-newer rule
sufficient on its own. The cost is that one persistently failing payload stalls everything behind
it — which is precisely why a 4xx dead-letters instead of blocking, and why answering
5xx to something you will never accept is a bad trade.
Auto-pause and recovery
If your endpoint fails five times consecutively and has not succeeded for
six hours, the integration is paused automatically and Doorloom staff are
alerted. A 410 pauses it immediately.
While paused:
- Events keep being recorded. Nothing is lost.
- The REST API keeps working. Paused only stops deliveries.
- Doorloom sends a ping every 30 minutes. The first one you answer with a 2xx resumes delivery.
- The backlog then drains in sequence order.
The backlog shrinks while you are down
A pause applied by staff by hand is never probed — it is resumed by staff.
Choosing which events you receive
Doorloom staff can restrict your integration to a subset of event types. By default you
receive all of them. GET /me reports
the current subscription as webhook.event_types.
ping is always sent,
regardless of subscription.
Redelivery
If an event dead-letters and you later fix the handler, Doorloom staff can redeliver it. A redelivery is always a new event — new id, new sequence, and payload rebuilt from the database as it is now, not as it was.
Doorloom never re-sends an old sequence number, because your apply-if-newer rule would
correctly discard it. This also means there is no partner-callable "resend event N": to catch up,
use GET /events with your cursor.