Keep in sync
Keep your copy of a hotel's bookings right, using webhooks for speed and a daily check for certainty.
If you keep your own copy of bookings (for a guest app, a channel manager, a CRM or accounting), you need it to match ChatBeds. Bookings change from everywhere: the front desk, WhatsApp, the hotel's booking page and other partners. Use webhooks to hear about changes within seconds, and a daily check to catch anything a webhook missed.
Scopes you need: reservations:read (needed for webhooks too).
1. Take webhooks
Set your webhook address (see Webhooks) and handle the three events:
async function handle(event) {
if (await seen(event.id)) return; // a repeat delivery
const incoming = event.data.reservation;
const mine = await db.reservations.get(incoming.id);
// Deliveries can arrive out of order: keep the newest.
if (mine && mine.updated_at >= incoming.updated_at) return markSeen(event.id);
await db.reservations.upsert(incoming); // created, modified and cancelled alike
await markSeen(event.id);
}The webhook carries the whole booking, so you rarely need to call back. Check status, not just the event name: a no-show comes as reservation.cancelled with status: "no_show".
Answer fast
Verify the signature, put the event on a queue, and answer 204 at once. Do the database work from the queue.
2. Check daily
Webhooks are retried for about two days, but if your server was down longer, or a bug dropped events, your copy drifts. Once a day, for each hotel, compare the coming days against ChatBeds.
reservation.search finds bookings by exact arrival or departure date. Walk the dates you care about:
from datetime import date, timedelta
def nightly_check(api, property_id: str, days: int = 30) -> None:
today = date.today()
for n in range(days):
day = (today + timedelta(days=n)).isoformat()
theirs = api.get(f"/properties/{property_id}/reservations",
params={"arrival": day, "limit": 100})["reservations"]
for r in theirs:
mine = db.reservations.get(r["id"])
if mine is None or mine["updated_at"] < r["updated_at"]:
db.reservations.upsert(r)
# Anything you hold for that arrival day that ChatBeds doesn't: fetch it by id.
for missing in db.reservations.arriving(property_id, day, exclude=[r["id"] for r in theirs]):
db.reservations.upsert(api.get(f"/reservations/{missing['id']}")["reservation"])Thirty days is 30 calls per hotel, well inside the rate limit. Spread hotels across the night rather than starting them all at once.
One page per day
limit is at most 100. If a day returns exactly 100, narrow it with status (one call per status) so nothing is cut off.
3. Your own bookings
For bookings you made, you already have ChatBeds' id from the create call. Keep it next to your own ID, and search by external_ref if you ever lose it.
When a hotel disconnects
When a hotel disconnects your app, your tokens stop working (401 on calls, invalid_grant on refresh) and webhooks stop. Mark the connection as ended, keep or delete the data under your privacy terms, and stop the nightly check for that hotel.
Building something?
Build a booking channel
Sell a ChatBeds hotel's rooms in your own product, from showing prices to booking, changing and cancelling, without ever selling a room twice.
Take payments
Two ways to handle money on a ChatBeds booking. Record a payment you took yourself, or send the guest a card payment link on the hotel's own Stripe.