---
title: "Remove Stay Room"
method: POST
path: "/trips/{trip_id}/itinerary/stays/{stay_id}/rooms/remove"
tags: ["itinerary"]
---

# Remove Stay Room

`POST /trips/{trip_id}/itinerary/stays/{stay_id}/rooms/remove`

## Request

- Base URL: `https://stardrift.ai` (the document declares no server; this is the origin it was published from)
- URL: `https://stardrift.ai/trips/{trip_id}/itinerary/stays/{stay_id}/rooms/remove`
- Auth: none declared

Take a chosen room off a stay.

409 on a room that was actually bought: it is a record, not a selection, and
dropping it would strand a live reservation with nothing on the trip
pointing at it. Cancelling the booking is what takes a room out of play.

## Path parameters

- `trip_id` string, required
- `stay_id` string, required

## Headers

- `x-client-id` string, nullable

## Request body

- RemoveStayRoomRequest
  - `room_id` string, required

## Response `200`

Successful Response

- StayRoomResponse
  - `itinerary` object, required
  - `rooms` StayRoom[], required
    - `id` string, required
    - `source` 'liteapi'
    - `hotel_id` string, required
    - `mapped_room_id` integer, nullable
    - `canonical_room_id` string, nullable
    - `room_name` string, required
    - `occupancies` RoomOccupancy[]
      - `adults` integer, required
      - `children` integer[]
    - `board_type` string, nullable
    - `prefer_refundable` boolean, nullable
    - `chosen_rate` SeenRate: A price we OBSERVED for a room, and when. Never a held price. LiteAPI publishes no TTL on an offer — expiry surfaces only as error 4040 at prebook — so the honest shape is an observation with a timestamp rather than a quote that pretends to still be live. `offer_id` lives HERE rather than on `StayRoom` deliberately: an offer id is part of *a price seen at a time*, not part of *which room this is*. Pairing them means a stale rate is self-describing, and a surface can date the number instead of presenting it as current. Also the seed for price-change notification on a saved room: two `SeenRate`s for one `StayRoom` are a price movement.
      - `offer_id` string, required
      - `all_in_total` number, required
      - `price_per_night` number, nullable
      - `currency` string
      - `board_type` string, nullable
      - `board_name` string, nullable
      - `refundable` boolean
      - `cancel_until` string, nullable
      - `seen_at` string, date-time, required
    - `latest_seen_rate` SeenRate: A price we OBSERVED for a room, and when. Never a held price. LiteAPI publishes no TTL on an offer — expiry surfaces only as error 4040 at prebook — so the honest shape is an observation with a timestamp rather than a quote that pretends to still be live. `offer_id` lives HERE rather than on `StayRoom` deliberately: an offer id is part of *a price seen at a time*, not part of *which room this is*. Pairing them means a stale rate is self-describing, and a surface can date the number instead of presenting it as current. Also the seed for price-change notification on a saved room: two `SeenRate`s for one `StayRoom` are a price movement.
      - `offer_id` string, required
      - `all_in_total` number, required
      - `price_per_night` number, nullable
      - `currency` string
      - `board_type` string, nullable
      - `board_name` string, nullable
      - `refundable` boolean
      - `cancel_until` string, nullable
      - `seen_at` string, date-time, required
    - `booking_id` string, uuid, nullable

## 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/be9ed1e6c38a?raw)
