---
title: "Book"
method: POST
path: "/hotel-bookings/{booking_id}/book"
tags: ["hotel-bookings"]
---

# Book

`POST /hotel-bookings/{booking_id}/book`

Take the booking. Safe to call again after any failure.

A `409 book_indeterminate` does NOT mean the booking failed — it means we
could not establish whether it succeeded. The correct client response is to
call this endpoint again; the reference is fixed, so a retry resolves into
the existing booking rather than creating a second one.

## Path parameters

- `booking_id` string, uuid, required

## Request body

- BookRequest
  - `holder` HolderIn, required
    - `first_name` string, required
    - `last_name` string, required
    - `email` string, required
    - `phone` string, nullable
  - `guests` GuestIn[], required
    - `occupancy_number` integer, required
    - `first_name` string, required
    - `last_name` string, required
    - `email` string, required
    - `phone` string, nullable
    - `remarks` string, nullable
  - `transaction_id` string, nullable
  - `metadata` object, nullable

## Response `200`

Successful Response

- BookingOut — Everything a screen can know about a booking from its id alone. That constraint is not academic. Payment puts a **full-page Stripe redirect in the middle of checkout** (LiteAPI's own flow — guest details are collected on the `return_url` page, after the card is charged), so the confirm page starts from a fresh document holding one thing: the booking id smuggled through the redirect. Every piece of state it needs to decide what to render has to come back from `GET /hotel-bookings/{id}` or it cannot be recovered at all. Deliberately still absent: `liteapi_transaction_id`. `/book` falls back to the one persisted on the row, so no client ever needs to hold it.
  - `booking_id` string, uuid, required
  - `status` string, required
  - `provider_status` string, nullable, required
  - `provider_booking_id` string, nullable, required
  - `hotel_confirmation_code` string, nullable, required
  - `hotel_id` string, required
  - `hotel_name` string, nullable, required
  - `checkin` string, date, required
  - `checkout` string, date, required
  - `currency` string, required
  - `all_in_total` number, nullable, required
  - `booked_total` number, nullable, required
  - `cancellation_fee` number, nullable, required
  - `refund_amount` number, nullable, required
  - `refundable_tag` string, nullable, required
  - `cancellation_policy` object, nullable, required
  - `rooms_priced` integer, nullable, required
  - `trip_id` string, uuid, nullable, required
  - `stay_tool_call_id` string, nullable, required
  - `sandbox` boolean, required
  - `payment_status` string, nullable, required
  - `payment_model` string, nullable, required
  - `payment_secret` string, nullable, required
  - `prebook_id` string, nullable, required
  - `booking_intent_id` string, nullable, 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

## 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.dev/stardrift/apis/fastapi/revisions/01060c7defa6?raw)
