StayBindDevelopers
Connect a custom OTA

Receive bookings

Post your OTA's reservations to a StayBind channel webhook. New, modified, and cancelled deliveries keep the ledger in sync, idempotently and with self-healing retries.

Whenever your OTA creates, changes, or cancels a reservation, POST it to your StayBind channel webhook. StayBind verifies it, normalizes it through mapReservation, and reflects it into the ledger, which then blocks (or releases) those dates on every other channel.

Endpoint

POST https://api.staybind.com/webhooks/channel/{connectionId}
Content-Type: application/json
x-signature: <your connection's webhookSecret>

{connectionId} identifies your connection (and through it, the org and your credentials). The x-signature header carries the shared secret assigned to your connection; StayBind verifies it against the stored webhookSecret before ingesting. (For compatibility, x-channex-webhook-secret is also accepted.) A failed verification is rejected and logged as a security event.

Body

Send either a single raw reservation object or an array of them. The shape is yours, as long as the configured mapReservation understands it. Out of the box, StayBind's default mapper reads this shape:

Single reservation
{
  "id": "R-1001",
  "status": "new",
  "roomTypeId": "deluxe",
  "checkIn": "2026-02-20",
  "checkOut": "2026-02-22",
  "channel": "my-ota",
  "totalMinor": 1500000,
  "guest": { "name": "Aarav Sharma", "email": "aarav@example.com", "phone": "+919812345678", "adults": 2, "children": 0 }
}
Or a batch
[ { "id": "R-1001", "...": "..." }, { "id": "R-1002", "...": "..." } ]

See Map reservations for the field-by-field meaning and how to send a different shape.

Statuses: new, modified, cancelled

Set status on each reservation. This is what makes changes and cancellations work, not just new bookings:

statusWhat StayBind does
newcreate the booking and block the dates (trips the double-booking guard on a real clash)
modifiedfind the existing booking by its stable id and update it, re-blocking the new range and releasing the old
cancelledfind the booking and release its dates back to the ledger, freeing them on every channel

For modified and cancelled to target the right booking, your payload must carry a stable booking id that is constant across revisions (mapped to providerBookingId), distinct from the per-delivery id (providerResId). See idempotency.

Response

The webhook always answers HTTP 200, even on a downstream error, so your retries never storm and a transient failure self-heals via the reconcile pull. The body tells you what happened:

{ "ok": true, "ingested": 1, "acked": 1, "conflicts": [] }
FieldMeaning
okthe request was processed (it may still report conflicts)
ingestedhow many reservations were written to the ledger
ackedhow many deliveries were acknowledged (so they won't be re-pulled)
conflictsreal overbookings that could not be reflected, a human is alerted to relocate/refund

If ok is false (an unexpected error), do not panic and do not hammer: the same reservation will be picked up by the next reconcile pull from your GET /reservations endpoint. At-least-once delivery plus idempotency means nothing is lost.

Reliability summary

Verify — StayBind checks x-signature against your webhookSecret.
Dedupe — each reservation is ingested once, keyed by its per-delivery id. Re-sends are no-ops.
Always 200 — so your client doesn't retry-storm; the reconcile pull heals anything missed.

Next: Map reservations, the field-by-field mapping and how a connection is configured.

On this page