Bookings & checkout
Place a booking directly, or run a pay-first checkout that commits the calendar only when payment is captured. Fetch and cancel bookings.
There are two ways to turn a quote into a booking, and they differ in when the calendar is committed:
createBookingholds the dates immediately (defaults toconfirmed). Use it when you've already taken payment, or for free/hold-style bookings.createCheckoutopens the booking as a non-blocking enquiry and returns a payment URL. The calendar is committed only when the payment is captured. Use it for a self-serve, pay-first funnel.
createBooking
Place a booking. A confirmed booking writes the ledger hold and fans availability out to every other channel.
Input
Prop
Type
curl -X POST https://api.staybind.com/public/trpc/createBooking \
-H "x-api-key: $STAYBIND_API_KEY" \
-H "content-type: application/json" \
-d '{
"propertyId": "prop_haveli",
"unitId": "unit_courtyard",
"guest": { "name": "Aarav Sharma", "phone": "+919812345678" },
"checkIn": "2026-02-20",
"checkOut": "2026-02-22"
}'{ "result": { "data": { "id": "bk_2Xq…", "status": "confirmed", "unitId": "unit_courtyard" } } }If those nights were taken between your availability check and this call, the response is CONFLICT (409). The guest record is matched or created by phone, so repeat guests are deduplicated automatically.
Idempotency
createBooking is not idempotent on its own, calling it twice creates two
bookings (the second fails with CONFLICT if the first held the dates). Guard
against double-submits on your side, and treat a 409 as "already taken,"
re-query availability before retrying.
createCheckout
Open a pay-first booking. StayBind prices the stay, opens it as a non-blocking enquiry (the calendar is not held yet), creates a payment link, and returns the URL to send the guest to.
Input is the same shape as createBooking minus status/channel/totalAmountMinor (the channel is always direct and the amount is the server quote):
Prop
Type
curl -X POST https://api.staybind.com/public/trpc/createCheckout \
-H "x-api-key: $STAYBIND_API_KEY" \
-H "content-type: application/json" \
-d '{
"propertyId": "prop_haveli",
"unitId": "unit_courtyard",
"guest": { "name": "Aarav Sharma", "phone": "+919812345678" },
"checkIn": "2026-02-20",
"checkOut": "2026-02-22"
}'{
"result": {
"data": {
"bookingId": "bk_2Xq…",
"paymentId": "pay_9aZ…",
"paymentUrl": "https://rzp.io/i/abc123",
"amountMinor": 1500000,
"currency": "INR"
}
}
}Redirect the guest to paymentUrl. When they pay, StayBind's payment-capture webhook confirms the booking and writes the ledger hold, or, in the rare case the nights were taken meanwhile, resolves the clash to a single winner via the double-booking guard. Because the calendar is committed by money, two people can safely reach checkout for the same night; only the one who pays first gets it.
Errors specific to checkout:
BAD_REQUEST"This stay isn't priced for online booking yet." — the quote is0(no sellable rate).BAD_REQUEST"This property can't take online payments yet." — the operator hasn't connected a payment account.
How do I know it was paid?
Confirmation happens server-side via the payment-capture webhook. Poll
getBooking for status: "confirmed", or build your post-payment status page
around the bookingId you got back. The guest's payment itself settles to the
operator (the operator is merchant of record); StayBind never pools guest
funds.
getBooking
Fetch a single booking by id. Input { "id": "bk_…" }.
curl -G https://api.staybind.com/public/trpc/getBooking \
-H "x-api-key: $STAYBIND_API_KEY" \
--data-urlencode 'input={"id":"bk_2Xq…"}'Returns the booking (status, unit, dates, guest, amounts). NOT_FOUND if the id isn't in this org.
cancelBooking
Cancel a booking and release its dates back to the ledger (which re-opens them on every other channel). Input { "id": "bk_…" }, a mutation:
curl -X POST https://api.staybind.com/public/trpc/cancelBooking \
-H "x-api-key: $STAYBIND_API_KEY" \
-H "content-type: application/json" \
-d '{"id":"bk_2Xq…"}'Next: Guest KYC.