---
title: "Create Hotel Purchase"
method: POST
path: "/hotel-purchases/"
tags: ["hotel-purchases"]
---

# Create Hotel Purchase

`POST /hotel-purchases/`

Start a hotel purchase with auth-capture payment flow.

Two modes:
- **Saved card** (payment_method_id provided): resolves Stripe customer,
  creates hotel purchase with off-session auth. Returns status "processing".
- **Inline pay** (no payment_method_id): resolves user email for Stripe customer
  creation, creates hotel purchase with unconfirmed PI. Returns client_secret
  for frontend card entry.

## Request body

- CreateHotelPurchaseRequest
  - `hotel_search_booking_session_id` string, uuid, nullable — Persisted hotel booking session that authoritatively owns replacement intent when provided.
  - `hotel_purchase_id` string, uuid, required — Client-generated UUID for idempotency
  - `quote_id` string, required — Quote ID from /prices endpoint
  - `hotel_negotiation_offer_id` string, uuid, nullable — Active hotel negotiation offer to redeem at its locked customer price.
  - `payment_method_id` string, nullable — Stripe payment method ID (pm_xxx). If absent, returns client_secret for inline card entry.
  - `payment_method_types` string[], nullable — How the deferred Stripe Elements group was configured, e.g. ['card'] (inline pay only). The PaymentIntent is created to match — Stripe rejects confirm on mismatch. Omitted = automatic payment methods.
  - `guest_rooms` ApiHotelPurchasesGuestRoom[], required — Guest details per room
    - `traveler_id` string, uuid, nullable — Saved traveler profile ID. Gateway resolves to name.
    - `first_name` string, nullable — Guest first name
    - `last_name` string, nullable — Guest last name
    - `email` string, nullable — Guest email
    - `adults` union — Named adult guests or count. ETG-ready format.
      - object[]
      - integer
    - `children` union — Named child guests or count.
      - object[]
      - integer
  - `validated_book_hash` string, nullable — Prebook-validated ETG hash from /hotel-purchases/prebook
  - `prebook_price_cents` integer, nullable — Prebooked supplier price in cents
  - `prebook_price_currency` string, nullable — Prebooked supplier price currency
  - `force_pay_now` boolean — If true, always use immediate charge (Path A) regardless of cancellation policy.
  - `conv_trip_id` string, uuid, nullable — Brain trip document UUID from conversation card
  - `replacement_for_booking_id` string, nullable — Existing hotel booking ID that this new booking is intended to replace.
  - `retail_total_amount` integer, nullable — Expedia retail total in minor units (cents). For savings display in confirmation email.
  - `retail_total_currency` string, nullable — Currency of retail_total_amount (e.g., 'USD')
  - `credit_amount_cents` integer, nullable — Axel credit to apply (cents). None/omitted=no credit, >0=apply this amount.

## Response `201`

Successful Response

- CreateHotelPurchaseResponse
  - `hotel_purchase_id` string, uuid, required
  - `status` string, required
  - `client_secret` string, nullable
  - `charge_mode` string
  - `credit_applied_cents` integer

## Other responses

- `422` — Validation Error

---

[API](https://skmtc.dev/helloaxel/apis/client-api-gateway.md) · [All operations](https://skmtc.dev/helloaxel/apis/client-api-gateway/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/helloaxel/client-api-gateway/revisions/d3c4c29fede7/schema)
