Enquiries Channel manager Bookings Your website Booking engine Pricing
v2026-09

Replay events

Fetch events after a sequence cursor. This is how you catch up on anything your endpoint missed, without asking anyone to resend it.

GET https://api.doorloom.com/api/integrations/v1/events

Query parameters

Query parameters

Field Type Required Description
after_sequence integer Optional Return events with a sequence greater than this. Defaults to 0, i.e. from the beginning of what is retained.
limit integer Optional 1 to 200. Defaults to 100.
property_id integer Optional Only events for this Doorloom property.
types array Optional Only these event types. Repeat the parameter: types[]=rates.changed&types[]=availability.changed.
include_superseded boolean Optional Include events that were retired because a newer event covered them. Off by default, and normally you want it off.
Request bash
curl -G https://api.doorloom.com/api/integrations/v1/events \
  -H "Authorization: Bearer $DOORLOOM_API_KEY" \
  --data-urlencode "after_sequence=1042" \
  --data-urlencode "limit=200"

Response

Response 200 json
{
    "success": true,
    "message": "OK",
    "data": [
        {
            "sequence": 1043,
            "status": "delivered",
            "delivered_at": "2026-10-01T15:04:12+05:30",
            "event": {
                "id": "01J6Y0R2M4P7Q9S1T3V5W7X9Y1",
                "type": "rates.changed",
                "version": "2026-09",
                "sequence": 1043,
                "occurred_at": "2026-10-01T15:04:11+05:30",
                "integration": {
                    "id": 12,
                    "slug": "acme-pms"
                },
                "property": {
                    "doorloom_id": 902,
                    "external_id": "VILLA-9",
                    "master_property_id": 902
                },
                "window": {
                    "from": "2026-10-12",
                    "to": "2026-10-14"
                },
                "data": [
                    "…"
                ]
            }
        }
    ],
    "cursor": {
        "after_sequence": 1042,
        "next_after_sequence": 1043,
        "has_more": false,
        "latest_sequence": 1047,
        "retention_days": 30
    }
}
Field Type Description
data[].sequence integer The event's sequence.
data[].status string pending, delivering, delivered, failed, dead or superseded. Delivery state, for diagnosis — it does not change how you should apply the event.
data[].delivered_at string|null ISO-8601, when it was accepted by your endpoint. Null if it never was.
data[].event object The exact envelope that was or would have been POSTed, byte for byte.
cursor.after_sequence integer The cursor you asked with, echoed.
cursor.next_after_sequence integer Pass this as after_sequence on your next call.
cursor.has_more boolean True while more events exist past this page.
cursor.latest_sequence integer The newest sequence that exists for your integration. Compare with your cursor to measure how far behind you are.
cursor.retention_days integer How long events are kept. Currently 30.

cursor sits beside data, not inside it

Like pagination elsewhere, it is a top-level key.

Paging through

Catching up python
cursor = load_cursor()          # your stored high-water mark

while True:
    r = get("/events", params={"after_sequence": cursor, "limit": 200})

    for row in r["data"]:
        handle(row["event"])     # same code path as your webhook handler

    cursor = r["cursor"]["next_after_sequence"]
    save_cursor(cursor)

    if not r["cursor"]["has_more"]:
        break

Feed the events through the same handler your webhook endpoint uses, including the apply-if-newer rule. Replayed events you have already applied are then dropped for free, so overlapping replays are harmless.

Superseded events

An event that was still undelivered when a newer event fully covered its window is retired as superseded and omitted here by default. That is what you want: the newer event holds the same truth and more.

include_superseded=1 shows them, which is occasionally useful when reconstructing what happened during an outage. Do not apply them — they are older state.

Retention

Events are kept for 30 days

If your cursor is older than that, replay cannot give you a complete picture and you must not pretend it did. Take snapshots instead, or request a full sync.

Compare cursor.latest_sequence with your own high-water mark to see the size of the gap before you start.

There is no acknowledge, and no single-event resend

Doorloom does not track what you have processed — you keep your own cursor. And there is no endpoint to re-request one specific event, because a redelivery is always issued as a new event with a new sequence. To recover, page forward from your cursor.

Errors

Errors

Status Code Meaning
422 VALIDATION_FAILED The request body failed validation. errors is Laravel's field bag: an object keyed by field path, each holding an array of messages.
401 UNAUTHENTICATED No API key, or a key that is not valid. Rotating your API key invalidates the previous one immediately.
429 RATE_LIMITED You exceeded one of the rate limits. The standard Retry-After and X-RateLimit-* headers are set on the response.

Something unclear or wrong on this page? Write to [email protected] and tell us which page — we would rather fix the doc than answer the ticket twice.