---
title: "Prebook"
method: POST
path: "/hotel-bookings/prebook"
tags: ["hotel-bookings"]
---

# Prebook

`POST /hotel-bookings/prebook`

Hold an offer and report what it will actually cost.

Failure modes worth handling in the UI, by `error.kind`:
  * `offer_unavailable` — the commonest one (4 of 18 fresh offers measured).
    This offer cannot be sold; the room is gone, not the hotel.
  * `offer_expired` — re-search and re-prebook.

## Request body

- PrebookRequest
  - `offer_id` string, required
  - `hotel_id` string, required
  - `quoted_all_in_total` number, required
  - `currency` string
  - `hotel_name` string, nullable
  - `trip_id` string, uuid, nullable
  - `conversation_id` string, uuid, nullable
  - `booking_intent_id` string, nullable
  - `use_payment_sdk` boolean

## Response `200`

Successful Response

- PrebookResponse
  - `booking_id` string, uuid, required
  - `prebook_id` string, required
  - `status` string, required
  - `hotel_id` string, required
  - `checkin` string, date, required
  - `checkout` string, date, required
  - `price` MoneyBreakdown, required — Never render `total` on its own. `all_in_total` is the price.
    - `total` number, required
    - `excluded_fees` number, required
    - `all_in_total` number, required
    - `currency` string, required
  - `drift` DriftReport, required — What changed between what we showed and what LiteAPI will honour. `requires_acknowledgement` is the gate: while it is true and nobody has confirmed, `/book` refuses. Note `price_drift_pct` and `provider_price_difference_pct` are DIFFERENT numbers — LiteAPI computes theirs on `retailRate.total`, so an excluded fee can move the user's price while their flag reads zero.
    - `requires_acknowledgement` boolean, required
    - `price_drift_pct` number, nullable, required
    - `provider_price_difference_pct` number, nullable, required
    - `cancellation_changed` boolean, nullable, required
    - `board_changed` boolean, nullable, required
    - `quoted_all_in_total` number, nullable, required
  - `rooms_priced` integer, required
  - `refundable_tag` string, nullable, required
  - `cancellation_policy` object, nullable, required
  - `rooms` object[], required
  - `payment` PaymentHandoff, required — Everything the Payment Element needs. `secret_key` is a Stripe PaymentIntent client secret (`pi_…`) issued by Nuitee. It IS persisted, on `HotelBooking.liteapi_payment_secret`, and read back by the owner-gated `GET /{id}` — see that field on `BookingOut`. There is no server-side alternative: the Stripe account is Nuitee's, so we hold no key, and a resume that cannot re-mount the same intent can neither pay nor re-prebook without stranding the transaction.
    - `payment_types` string[], required
    - `transaction_id` string, nullable
    - `secret_key` string, nullable
  - `sandbox` boolean, required

## Other responses

- `422` — Validation Error

---

[API](https://skmtc.dev/stardrift/apis/fastapi.md) · [All operations](https://skmtc.dev/stardrift/apis/fastapi/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/stardrift/fastapi/revisions/00746572572a/schema)
