Cribond · Developers
Cribond Channel API
Connect a channel manager or PMS (Talkguest, Hostaway, Smoobu, Guesty…) to Cribond, the Portuguese holiday-rental marketplace, and manage Cribond listings exactly like listings on your other channels: push availability, nightly rates and stay restrictions in; receive reservations out, in real time.
https://api.cribond.com/functions/v1/channel-api/v1Version
2026-09-23 (sent back in the Cribond-Api-Version header) · Format JSON, UTF-8 · Currency EUR · Dates YYYY-MM-DD, local to the property (Europe/Lisbon)
1. Authentication
Every request carries a per-host API key: Authorization: Bearer cbk_…. The host creates the key in Cribond (Integrações) and gives it to you. A key only reaches the listings of the host who created it; the host can rotate or revoke it at any time (you then get 401). One key per host account covers all of that host's listings — including the ones they do not own but manage for other hosts as a co-host with full access, which is how a property manager runs several owners' places with a single key.
curl https://api.cribond.com/functions/v1/channel-api/v1/me \
-H "Authorization: Bearer cbk_xxxxxxxx_…"
2. How it maps to Cribond
- A Cribond listing is one bookable unit (entire place). Map each of your units/rooms to one listing.
- Once you push a calendar for a listing (or map it), the listing becomes channel-managed: Cribond prices each night exactly at your rate — no per-guest surcharges — and applies your restrictions. Nights you never priced fall back to the listing's own base/weekend price.
- Cribond collects the guest's payment (card, MB Way, etc.) and pays the host out. Reservations you receive are already paid and confirmed; there is no request/approval step.
- Closing nights is atomic with Cribond's booking check: a night you close can never be booked afterwards, even concurrently.
3. Listings & mapping
| Call | What it does |
|---|---|
GET/me | The connection this key belongs to. |
GET/listings | The host's listings: id, external_id, title, status, base_price, weekend_price, min_nights, max_nights, max_guests, managed. |
GET/listings/{id} | One listing ({id} = Cribond id or slug). |
PUT/listings/{id}/mapping | {"external_id": "your-unit-id"} — link a listing to your unit. Unique per connection. |
DELETE/listings/{id}/mapping | Stop managing a listing. Your closures and rates on it are removed; it returns to the host's own settings. |
PATCH/listings/{id} | Defaults: base_price, weekend_price, min_nights (1–30), max_nights (1–90), max_guests (1–50). |
4. Availability, rates & restrictions (ARI)
PUT/listings/{id}/calendar
Send ranges; to is inclusive (a night is identified by its date). A field you omit keeps its stored value; a field sent as null is cleared. Idempotent — resend freely. Up to 500 ranges and 20,000 nights per call, up to 760 days ahead; past nights are ignored.
PUT /listings/be255e3e-…/calendar
{
"updates": [
{ "from": "2026-10-01", "to": "2026-10-31", "price": 95, "min_nights": 2 },
{ "from": "2026-10-10", "to": "2026-10-12", "closed": true },
{ "date": "2026-10-17", "closed_to_arrival": true },
{ "from": "2026-11-01", "to": "2026-11-05", "available": false }
]
}
→ 200 { "listing_id": "be255e3e-…", "nights_updated": 36 }
| Field | Type | Meaning |
|---|---|---|
price | number | null | Nightly price in EUR for the whole unit — exactly what the guest pays for the stay (Cribond charges guests no fee; the host pays a 5% commission). |
min_nights / max_nights | 1–365 | null | Stay length rule, applied on the arrival date. |
closed (or available: false) | boolean | Night cannot be sold. |
closed_to_arrival | boolean | No check-in on this date. |
closed_to_departure | boolean | No check-out on this date. |
GET/listings/{id}/calendar?from=&to=
Read back every night (default: next 365 days): price, price_source (channel | listing_default), restrictions, available, and unavailable_reason — reservation (a Cribond booking), hold (a guest is paying right now; released within minutes if they abandon), host (blocked by the host in Cribond) or ical (another calendar the host imported). Use it to reconcile.
5. Reservations (pull)
A change feed with a monotonic cursor — nothing is ever skipped, even for changes made in the same millisecond.
GET/reservations?after=0&limit=100 | Reservations created or changed after the cursor, oldest first. Keep next_after and pass it back; loop while has_more. Optional listing_id. |
GET/reservations/{id} | One reservation, current state. |
{
"id": "55086fee-…", "code": "CB-55086FEE",
"status": "confirmed", // or "cancelled"
"stay_status": "upcoming", // "checked_in" | "checked_out"
"listing": { "id": "be255e3e-…", "external_id": "TG-123", "slug": "…", "title": "…" },
"arrival": "2026-10-20", "departure": "2026-10-23", "nights": 3,
"guests": { "total": 2 },
"guest": { "name": "Ana Silva", "email": "ana@…", "phone": "+351…" },
"guest_identity": null,
"currency": "EUR",
"amounts": {
"accommodation": 285.00, // stay price after host-funded discounts
"discount": 0,
"host_payout": 270.75, // what the host receives (stay − commission)
"guest_service_fee": 0, // the guest pays no Cribond fee
"host_commission": 14.25, // Cribond's 5%, paid by the host (payments included)
"security_deposit": 0, // refundable, held by Cribond
"total_paid_by_guest": 285.00,
"tourist_tax_collected": false
},
"payment": { "collected_by": "cribond", "status": "paid", "host_paid_out_at": null },
"cancellation": null, // or { cancelled_at, cancelled_by, reason, refund_amount }
"confirmed_at": "…", "created_at": "…", "sequence": 812
}
Poll every 1–5 minutes as a safety net even when you use webhooks.
6. Webhooks (push)
Register an HTTPS endpoint with PUT/webhook {"url": "https://…"} (DELETE to remove, POST/webhook/test to receive a ping). Cribond POSTs within seconds of every change:
reservation.created | A reservation was paid and confirmed — close those nights on your other channels. |
reservation.modified | Dates or party size changed. |
reservation.cancelled | Cancelled — reopen the nights. |
POST https://your-endpoint
Cribond-Signature: t=1790083940,v1=5f1c… // HMAC-SHA256
Cribond-Event-Id: evt_1042
Cribond-Event-Type: reservation.created
{ "id": "evt_1042", "type": "reservation.created", "created_at": "…",
"api_version": "2026-09-23", "data": { "reservation": { … } } }
Verify every delivery: compute HMAC-SHA256(webhook_secret, t + "." + raw_body) in hex and compare with v1 (constant-time); reject timestamps older than 5 minutes. The webhook_secret (whsec_…) is given to the host with the API key.
// Node.js
const [t, v1] = header.split(",").map(p => p.split("=")[1]);
const expected = crypto.createHmac("sha256", secret).update(t + "." + rawBody).digest("hex");
const ok = crypto.timingSafeEqual(Buffer.from(v1), Buffer.from(expected)) && Date.now()/1000 - t < 300;
Answer 2xx within 10 seconds. Anything else is retried after 1, 2, 5, 15, 30 min, 1, 2, 4, 8 and 12 h, then marked failed (the host can resend from Cribond). Deliveries can arrive more than once — de-duplicate on id. The payload always carries the reservation's current state, so a late created for a stay already cancelled says "status": "cancelled".
7. Errors & limits
{ "error": { "code": "invalid_date", "message": "updates[0]: from/to must be YYYY-MM-DD." } }
401 | unauthorized — missing, wrong or revoked key. |
404 | not_found — unknown endpoint, or a listing/reservation that is not this host's. |
409 | Conflict, e.g. external_id_taken. |
422 | Validation (invalid_date, invalid_price, invalid_restriction, …). |
429 | More than 6,000 calls/hour for one connection. Honour Retry-After; batch ranges instead of one call per night. |
5xx | Retry with exponential backoff. All writes are idempotent. |
8. Guests, invoicing & SEF/AIMA
- Reservations carry the guest's name, email and phone. Cribond does not collect identity documents: SIBA/AIMA guest registration stays with your online check-in, exactly as for reservations from your other channels.
guest_identityis reserved for when that changes. - Invoicing: Cribond invoices the host for its commission (
amounts.host_commission) and the guest for nothing. The accommodation is the host's supply — invoice it from your certified billing module usingamounts.accommodation.amounts.host_payoutis what reaches the host's bank account. - Tourist tax is not collected by Cribond (
tourist_tax_collected: false); charge it at check-in as for other direct/OTA channels that do not collect it.
9. Recommended integration flow
- Host creates a key in Cribond → pastes it into your product.
GET /listings→ the host picks which unit is which →PUT /listings/{id}/mapping.- Full sync:
PUT /listings/{id}/calendarwith the next 12–24 months (prices, restrictions, closures — including nights booked on other channels). PUT /webhook, thenGET /reservations?after=0once to import history; storenext_after.- From then on: push every ARI change as it happens (deltas are fine); react to webhooks; poll
/reservationsevery few minutes as a safety net.
10. Partnership & support
Building a Cribond connection for your platform? We give you a sandbox host account and help test before you go live: support@cribond.com. Hosts whose channel manager does not support Cribond yet can sync calendars over iCal in the meantime.