Skip to main content
POST
Create a booking only after a successful Prebook a Room response. This endpoint is idempotent and requires an Idempotency-Key header for every request. The booking request assigns named guests to the exact room instances returned by prebook. It does not use static catalogue room IDs, supplier room names, or array position as identity.

Cancellation-based review

The request body and idempotency rules are unchanged. Bookings within the accepted offer’s free-cancellation window return PROCESSING and queue supplier booking immediately, without portal approval. Non-refundable bookings, offers whose free window has ended, and unclear cancellation terms return AWAITING_REVIEW. Neither status is a confirmed reservation or a supplier hold. For AWAITING_REVIEW, show “Awaiting verification — room and price are not reserved”. An organization owner/admin reviews the saved hotel, supplier rooms, guests, price and cancellation terms in the portal, then chooses Approve and book. REVIEW_BOOKING is a portal action; customer API keys cannot approve requests. Free cancellation is checked again before supplier submission. If it ends while the request is queued, the booking moves to AWAITING_REVIEW and requires approval. data.review_expires_at is the current supplier quote deadline. Manual requests remain AWAITING_REVIEW after quote expiry; do not cancel or refund based on this timestamp. The reviewer can obtain a fresh quote in the portal and approve its current price and terms under the same booking reference. The original agent price stays unchanged; the reviewer accepts any supplier cost difference. Approval and supplier submission must occur before the fresh quote expires. Rejection produces FAILED / BOOKING_REVIEW_REJECTED. Already-terminal requests cannot be refreshed. Expiry during direct free-cancellation submission can still produce FAILED / BOOKING_REVIEW_EXPIRED before any reservation is submitted.

Request Example

Request Fields

The rooms array can be sent in any order. Unifystays matches each entry by room_allocation_id and restores the supplier’s trusted room order server-side.

Building the Room Assignments

For every room in the prebook response:
  1. Copy its room_allocation_id into one booking room object.
  2. Read the room’s occupancy.adults and occupancy.child_ages.
  3. Attach exactly that number of adult and child guest objects.
  4. Repeat until every prebook allocation appears once.
For example, an occupancy of {"adults": 1, "child_ages": [8]} requires one guest with guest_type: "ADULT" and one guest with guest_type: "CHILD". The child’s age was already captured in the shopping and prebook context; the booking guest object supplies the child’s identity. Never send the nested unifystays_room.room_id in this request. A room with mapping_status: "UNMAPPED" is booked through its room_allocation_id in exactly the same way as a mapped room.

Idempotency Rules

Generate one unique key for one customer booking attempt. Persist it before the request. On a network timeout or unreadable response, retry with the same key and identical request body.
Never generate another key for an uncertain retry. A new key represents a new attempt and can result in a second reservation. Generate a new idempotency key only when the customer intentionally starts a new booking attempt, for example after returning to room options and completing a new prebook.

Build the Booking Body

  • Send prebooking_id and accepted_offer_id from the same prebook response.
  • Send every room allocation returned by prebook exactly once. Array order is not significant.
  • Use each prebook room_allocation_id to attach the correct guests to that quoted room slot.
  • Render the prebook offer’s booking_requirements dynamically. Use label, value_type, allowed_values, and constraints to build and validate the form.
  • Copy each applicable requirement_id exactly into the guest’s answers. Never construct IDs from code, and do not send answers that were not declared by the accepted prebook offer.
  • Apply LEAD_GUEST, ALL_GUESTS, ADULT, CHILD, INFANT, and optional room_allocation_ids scopes when deciding which guest must answer.
  • Do not send agency billing, arrival, or special-request sections. Agency tax details belong to organization/provider settings, not individual bookings.
The API rejects duplicate, unknown, or missing allocation IDs. It also rejects guest counts that do not match the occupancy saved during prebook. On either error, fix the request body only if you still have a valid prebooking ID; otherwise restart from room options.

Response Example

Track the Outcome

The response contains a stable booking_id and unified status. Use Get Booking Status as the source of truth after the request returns. Use is_terminal to stop status polling, but always check action_required and available_actions. An ON_HOLD response can be terminal for the hold creation operation while still requiring CONFIRM_HOLD as the next business action.
Booking contains guest personal data. Send it only from your trusted backend and avoid writing unprotected guest information to client-side logs.
The OpenAPI section below documents all booking fields, guest structures, document fields, response statuses, and errors.

Authorizations

x-api-key
string
header
required

Environment-specific API key created in the Unifystays portal

Headers

X-Unifystays-End-User-IP
string

Public IP of the traveler completing checkout. Required for RateHawk when the API request does not originate directly from that traveler.

Example:

"8.8.8.8"

Idempotency-Key
string
required

Unique key per booking attempt from client. Reusing the same key with same payload returns the same booking object.

Example:

"order-2987349823-booking-1"

X-Unifystays-Contract-Version
enum<string>
default:1

Hotel API contract version. Missing defaults to v1.

Available options:
1

Body

application/json
prebooking_id
string
required

Prebooking token from prebook response (data.prebooking_id).

Example:

"pbq7.bjNQb1Y5R2hRWEg.k6jQ3nW4cF1nL4MWvN7A9Q"

accepted_offer_id
string
required

Exact prebook offer being accepted.

rooms
object[]
required

Guest assignments keyed by room_allocation_id. Array order is not significant.

booking_mode
enum<string>
default:INSTANT

Booking mode. HOLD is accepted only when the prebook lifecycle explicitly lists HOLD; currently only certified TripJack offers can do this.

Available options:
INSTANT,
HOLD

Response

contract_version
string
required
Example:

"1"

success
boolean
required
Example:

true

message
string
required
Example:

"Booking request accepted and is being processed."

data
object
required