Enquiries Channel manager Bookings Your website Booking engine Pricing Log in Sign up
v2026-09

Quickstart

Four steps, in the order that finds problems earliest: prove your key works, get your properties into Doorloom, prove you can verify a webhook, then write a booking.

You need an API key and a webhook secret from Doorloom before starting. See Authentication.

The onboarding sequence

End to end, an integration comes alive in this order. Each step is expanded below or on its own page.

  1. Doorloom activates your integration against one brand and hands you an API key and a webhook secret.
  2. You call GET /me to prove the key and read your sequence cursor.
  3. You create or map properties. Listings that live in your system go in through POST /properties (or the bulk form); listings the host already made in the Doorloom app are in your coverage or are mapped by staff.
  4. You store the ids — Doorloom's doorloom_id against your external_id, and inventory_id against your unit ids.
  5. Units are created or mapped in the same create call, or by staff for app-created listings.
  6. You load initial state: a created property sends you its own snapshot; for everything else, GET /properties then the per-property snapshots.
  7. Webhooks keep the two systems in sync, and PUT /properties/{id} carries your side's listing changes back.
  8. You create bookings.

1. Prove your key works

Request bash
curl https://doorloom.com/api/integrations/v1/me \
  -H "Authorization: Bearer $DOORLOOM_API_KEY"

A 200 means you are talking to the right environment with a live key. Note two things in the response: data.webhook.last_sequence, which is the cursor you will need to stay in sync, and data.covered_properties, which tells you how many properties this integration can already see.

2. Create or map your properties

If the listing lives in your system first, create it. One call makes the property, its units, its opening rates and your id mapping, and covers it for your integration:

Request bash
curl -X POST https://doorloom.com/api/integrations/v1/properties \
  -H "Authorization: Bearer $DOORLOOM_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 2c5d0b7e-1f7a-4c1b-9b3e-3e7d9a4f6c21" \
  -d '{
    "external_id": "VILLA-9",
    "name": "Amber Villa, Alibaug",
    "property_type": "villa",
    "description": "Sea-facing villa with a private pool.",
    "address": { "address_line_1": "12 Kihim Beach Road", "city": "Alibaug", "state": "Maharashtra", "pin_code": "402201" },
    "space": { "bedrooms": 3, "washrooms": 3 },
    "occupancy": { "max_guests": 8 },
    "pricing": { "weekday": { "base_price": 12000 }, "weekend": { "base_price": 15000 } },
    "units": [ { "name": "Room A", "external_id": "ROOM-A" }, { "name": "Room B", "external_id": "ROOM-B" } ]
  }'

The 201 carries data.doorloom_id and every unit's inventory_id next to the ids you sent. Store that mapping now; everything after this point refers to properties and units by one id or the other. A portfolio goes in through POST /properties/bulk, 25 at a time.

If the host already created the listing in the Doorloom app, do not create a copy. List what you cover:

Request bash
curl https://doorloom.com/api/integrations/v1/properties \
  -H "Authorization: Bearer $DOORLOOM_API_KEY"

Each property comes back with its doorloom_id, its external_id if staff mapped one, and its units. Store those ids the same way. If a listing you expect is missing, ask Doorloom to add it to your coverage.

A created property sends its own initial state

Within seconds of the 201 you receive the property's full snapshot through your webhook — property, inventory, availability, rates and restrictions across your horizon. You do not need to call the snapshot endpoints for it. For properties that were already in your coverage, pull the snapshots once instead.

3. Receive and verify a webhook

Give Doorloom an HTTPS URL that answers POST. Then ask staff to send a test ping to it, or make any calendar change in the Doorloom app to trigger a real event — creating a property in step 2 already sent you several.

Your endpoint has exactly three obligations, and the first two matter more than they look:

  1. Verify the signature before trusting a byte of the payload.
  2. Answer 2xx within 10 seconds. Acknowledge first, process afterwards.
  3. Apply only if newer — the sequence rule, below.
A minimal handler python
# POST /hooks/doorloom
def webhook(request):
    raw = request.get_data()             # RAW bytes, not a re-encoded dict
    header = request.headers.get("X-Doorloom-Signature", "")

    if not verify(os.environ["DOORLOOM_WEBHOOK_SECRET"], raw, header):
        return Response(status=401)

    event = json.loads(raw)

    # Hand off and return immediately. Anything slow happens off-request.
    queue_for_processing(event)
    return Response(status=204)

The verify() function is on the signature page, in Python and JavaScript. Copy it rather than writing your own — the two mistakes people make (hashing re-serialised JSON, and accepting only the first v1=) both produce something that works right up until it does not.

Do not process inside the request

Doorloom waits 10 seconds. If you exceed that, the delivery is a timeout, which is a retryable failure — and because delivery is strictly in order, nothing else reaches you until that event succeeds. A slow handler does not just delay itself, it stops your whole feed.

4. Implement the sequence rule

Every event carries a sequence, and every payload is the full current state for its scope, never a delta. So the entire correctness requirement is one line:

The rule

Per property and per event type, apply an event only if its sequence is higher than the last one you applied for that property and type. Otherwise ignore it.

That makes duplicates, retries and out-of-order arrivals harmless without any other bookkeeping. Ordering and idempotency explains why it is sufficient.

5. Create a booking

Request bash
curl -X POST https://doorloom.com/api/integrations/v1/bookings \
  -H "Authorization: Bearer $DOORLOOM_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 6f1c2f2a-6b3a-4a1e-9d2f-8a7c5e3b1d40" \
  -d '{
    "external_booking_id": "PMS-100234",
    "property": { "external_id": "VILLA-9" },
    "units": [ { "external_unit_id": "ROOM-A", "adults": 2, "children": 1, "meal_plan": "CP" } ],
    "check_in": "2026-10-12",
    "check_out": "2026-10-14",
    "guest": { "name": "Asha Rao", "phone_code": "+91", "mobile": "9876543210" },
    "pricing": { "total": 16000, "currency": "INR" },
    "status": "confirmed"
  }'

A 201 returns the booking. Two other outcomes are normal and neither is a bug:

  • 200 with data.duplicate: true — you already created a booking with this external_booking_id. Treat it as success.
  • 409 UNAVAILABLE — nothing was free for the whole stay. errors.availability carries the per-night picture so you can correct your calendar in the same breath.

Send an Idempotency-Key on every create

Booking creates and property creates both require one: 8 to 128 characters, and a UUID per attempt is ideal. Retrying with the same key and body replays the original response instead of creating a second record — including replaying a refusal, so a retry after a 409 cannot race into a double booking or a duplicate property.

6. Handle the echo

Moments later you will receive a booking.changed webhook for the booking you just made, with origin: "partner". That is your own write coming back as confirmation. You can ignore it, or use it to mark the write as durably landed. Property writes echo the same way, as property.changed (and rates.changed or inventory.changed when you touched those).

When the host edits that booking in the Doorloom app, you get the same event with origin: "doorloom". That one you must apply.

Before you go live

  1. Signatures verified, bad ones rejected with a 401.
  2. The sequence rule implemented per property and type, with your cursor persisted.
  3. 2xx inside 10 seconds; processing is asynchronous.
  4. Every property you sell mapped: created through the API or listed by GET /properties, with doorloom_id and inventory_id stored against your own ids.
  5. On start-up and after any outage, call GET /events?after_sequence=. If your cursor is older than 30 days, take snapshots instead.
  6. Idempotency-Key on every create, booking or property; 200 duplicate and 409 PROPERTY_EXTERNAL_ID_EXISTS for an id you already sent treated as "already done".
  7. 409 UNAVAILABLE feeds your calendar from errors.availability.
  8. Money parsed as numbers, timestamps parsed with their offset.

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.