POST /api/v1/hotels/book_hotel
Finalize a pre-booked hotel offer with guest details. Requires Read+Write permission.
Finalize the booking for a rate you already locked with pre_book. The
backend recovers price, hotel, and dates from the cached pre-book offer — you only need to send
partner_order_id, the guests per room, and contact details.
Permission: Read+Write
Always call pre_book first. Booking without a matching cached pre-book offer returns
409 cached_offer_required (live) — sandbox is more lenient for local testing, but the request
shape is identical either way.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
partner_order_id | string | Yes | From pre_book |
rooms | array | Yes | One object per room, matching the room order used in get_rates — see Guests & rooms |
rooms[].guests | array | Yes | { first_name, last_name } per guest staying in that room |
user | object | Yes | { email, phone } — booking contact, receives the confirmation |
language | string | No | Default "en" |
send_email | boolean | No | false to suppress the confirmation email. Default true. |
Request example
curl --request POST \
--url https://api.fx-port.com/api/v1/hotels/book_hotel \
--header 'Authorization: Bearer fxp_test_YOUR_KEY' \
--header 'Content-Type: application/json' \
--data '{
"partner_order_id": "HMTLZLWGQ",
"language": "en",
"rooms": [
{
"guests": [
{ "first_name": "Amine", "last_name": "Benali" },
{ "first_name": "Sara", "last_name": "Benali" }
]
}
],
"user": {
"email": "[email protected]",
"phone": "+213555000001"
},
"send_email": false
}'Multi-room example
{
"partner_order_id": "HMTLZLWGQ",
"language": "en",
"rooms": [
{ "guests": [{ "first_name": "Amine", "last_name": "Benali" }, { "first_name": "Sara", "last_name": "Benali" }] },
{ "guests": [{ "first_name": "Karim", "last_name": "Haddad" }] }
],
"user": { "email": "[email protected]", "phone": "+213555000001" }
}Name encoding: first_name / last_name must be plain Latin (ASCII) letters only — no
accents/diacritics, no non-Latin scripts. See Guests & rooms.
Response example
{
"environment": "sandbox",
"success": true,
"status": "pending",
"bookingId": "HMTLZLWGQ",
"partnerOrderId": "HMTLZLWGQ",
"hotelId": "test_hotel",
"checkinDate": "2026-11-15",
"checkoutDate": "2026-11-18",
"pricing": {
"totalPrice": 43812.75,
"agencyCommission": 87.30,
"currency": "DZD",
"supplierCurrency": "EUR",
"originalPrice": 291.00
},
"postProcessing": {
"bookingDbId": "24fec1e5-a09f-48ec-8050-1adaab0a8de1",
"webhookSent": false,
"bucketLink": null
},
"processingTime": 2.986,
"balanceDebited": false,
"transactionCreated": false,
"payoutCreated": false
}The response returns status: "pending" immediately. Confirmation finishes in the
background (supplier confirmation + voucher PDF generation) and typically completes within a few
seconds. Poll GET /api/v1/bookings/{id}?product=hotels with bookingId
until status becomes confirmed (or failed).
Field reference
| Field | Description |
|---|---|
bookingId / partnerOrderId | Same value — use this to poll get-booking, fetch the voucher, or later cancel |
status | pending right after this call; becomes confirmed or failed in the background |
pricing.totalPrice | Final amount charged, matching what pre_book returned |
postProcessing.bucketLink | null until the voucher PDF finishes generating — poll get-booking |
balanceDebited / transactionCreated / payoutCreated | Always false in sandbox — no financial side effects occur. In live, these reflect the real ledger state. |
Next step
Poll GET /api/v1/bookings/{id}?product=hotels until confirmed, then fetch
the voucher.
POST /api/v1/hotels/pre_book
Lock in the price of a chosen rate and get a partnerOrderId + booking form ahead of book_hotel. Requires Read+Write permission.
Get hotel booking
Retrieve full hotel booking details, including pricing breakdown and the voucher PDF link, through the shared account booking endpoint.