# CheckAvail

`POST /api/search/checkAvail`

Re-validates a single rate package immediately before booking, confirming that the room is still sellable and that the price has not moved since HotelRates returned it.

This call is the mandatory pre-booking validation step. Skipping it exposes the booking to three failure modes:
- room inventory being consumed between the search and the booking attempt
- price movement that changes what the traveller was quoted
- outright booking failure because the rate package is no longer sellable

**When to call it**
Call it after HotelRates, once the user has picked one specific rate package.

**Inputs required**
- `ratePkgId` (request body): the rate package identifier taken from the HotelRates response
- `Session-Id` (request header): identifies the session for the booking flow

**What comes back**
- the confirmed availability status
- the final price
- the refreshed rate package detail
- fallback candidates for smart booking (R2 candidates)

**Error behaviour**
- a price or inventory move is returned in-band: the room comes back
  AVAILABLE with the refreshed rate package and `code` 0, carrying a
  `statusRemark` such as "price updated by supplier revalidation"

- a rate that has gone entirely comes back UNAVAILABLE with `code` 0 —
  CheckAvail never substitutes a bare error code for the re-priced package

- the ARI-changed business `code` 100001111 is raised by Book, not here:
  it fires only when the rate moves between this call and the commit,
  where there is no longer a re-priced package to hand back


**Position in the booking flow**
1. HotelRates returns the sellable room options
2. the user picks one rate package
3. CheckAvail re-validates that pick (this endpoint)
4. booking proceeds if availability was confirmed
5. a moved price or reduced inventory is reflected in the refreshed
   package this call returns


**Typical uses**
- confirming availability ahead of booking
- final price check before taking payment
- preparing the smart-booking fallback
- detecting inventory movement

## Request headers

| Header | Required | Description |
| --- | --- | --- |
| `Client-Request-Timestamp` | No | Unix timestamp recorded by the client at the moment it began sending the request. |
| `Currency` | No | Currency the rates should be returned in, expressed as an ISO 4217 code (https://en.wikipedia.org/wiki/ISO_4217). |
| `IP` | No | Client IP address. Both IPv4 and IPv6 are accepted. |
| `Language` | No | IETF BCP 47 language tag (https://masonreview.com/posts/ietf-bcp-47-language-tags/), for example "en" or "en-US". Defaults to "en-US". |
| `Market` | No | Point-of-sale market for this call, as an ISO 3166-1 alpha-2 country code. Required only when your account carries a market restriction: an allow-list cannot admit a market you have not stated, so such an account refuses calls that omit it. |
| `Request-Id` | No | Identifies this individual request. Values must not repeat across requests. |
| `Session-Id` | Yes | Session identifier. The client is expected to supply it on the request, and it is mandatory throughout the booking flow. |
| `Test` | No | Test flags, supplied as key-value pairs, for example "hotel=HC1&scenario=priceChange". When the server does not recognise the value, the request behaves exactly as though no "Test" header had been sent. |
| `Timeout-Milliseconds` | No | Client-specified timeout; the server makes a best effort to respond within it. |
| `Trace-Id` | No | Correlates a group of related requests for tracing. |
| `User-Ref` | No | Your own identifier for the person on whose behalf this call is made. Required only once named users have been authorised on your account, after which every call must identify one and is authorised against that user's scopes as well as the key's. |
| `Authorization` | Yes | Bearer credential, prefixed with "Bearer ". Obtained from the Ticket response. The Ticket endpoint itself does not require it. |

## Request body

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `ratePkgId` | string | Yes | Unique identifier of this RatePkg. |


### Example request

```json
{
  "ratePkgId": "rp_8f3c1a7e6b2d40f9a51c"
}
```

## Response

Successful calls return the standard envelope. `code` is `0` on success — check it rather than the HTTP status alone, because some business failures are delivered with HTTP 200.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `code` | integer | No |  |
| `msg` | string | No |  |
| `data` | hotel.search.protocol.CheckAvailResp | No |  |
|    `data.status` | enum | No | Availability outcome for the room. The source also states this field conveys other unavailability causes such as a credit-warning status, although only two enum values are defined. Allowed: `1`, `2`. |
|    `data.roomRatePkg` | object | No | Detailed rate package information, present when available. |
|       `data.roomRatePkg.ratePkgId` | string | Yes | Key input for the checkAvail and book APIs. |
|       `data.roomRatePkg.refundableMode` | enum | Yes |  Allowed: `full`, `partial`, `no`. |
|       `data.roomRatePkg.refundableUntil` | string | No | Instant up to which the stated refundableMode applies. |
|       `data.roomRatePkg.cancelFees[]` | array<hotel.supplier.domain.ComputedCancelPolicyItem> | No |  |
|          `data.roomRatePkg.cancelFees[].until` | string | No | Deadline for cancelling under this policy step. |
|          `data.roomRatePkg.cancelFees[].fee` | Money | No | Cancellation charge; a value of 0 means cancellation is free. |
|       `data.roomRatePkg.originalRoomNaming` | object | No | Room naming fields exactly as received from the supplier. |
|          `data.roomRatePkg.originalRoomNaming.id` | string | No | Unique identifier, i.e. the room code. |
|          `data.roomRatePkg.originalRoomNaming.name` | string | No | Room name as supplied by the supplier. |
|          `data.roomRatePkg.originalRoomNaming.supplier` | integer | No | Supplier id. |
|       `data.roomRatePkg.rate` | object | Yes | Price of a single room across all nights. |
|          `data.roomRatePkg.rate.commissionableRate` | object | No | Basis for commission calculation. |
|          `data.roomRatePkg.rate.netRate` | object | Yes |  |
|          `data.roomRatePkg.rate.grossRate` | object | No |  |
|          `data.roomRatePkg.rate.respectGrossRate` | boolean | No | When true, the client must honour GrossRate. Defaults to false. |
|       `data.roomRatePkg.totalRate` | object | Yes | Total price covering all rooms and all nights. |
|          `data.roomRatePkg.totalRate.commissionableRate` | object | No | Basis for commission calculation. |
|          `data.roomRatePkg.totalRate.netRate` | object | Yes |  |
|          `data.roomRatePkg.totalRate.grossRate` | object | No |  |
|          `data.roomRatePkg.totalRate.respectGrossRate` | boolean | No | When true, the client must honour GrossRate. Defaults to false. |
|       `data.roomRatePkg.rateComment` | string | No |  |
|       `data.roomRatePkg.includesPackaging` | boolean | No | Marks the product as a package, for example a flight plus hotel combination. |
|       `data.roomRatePkg.checkIn` | string | Yes | Check-in date. Defaults to the current date. |
|       `data.roomRatePkg.checkOut` | string | Yes | Check-out date. Defaults to seven days from the current date. |
|       `data.roomRatePkg.board` | object | No | Board information: the standard meal plan, following the liteapi standard. |
|          `data.roomRatePkg.board.boardId` | enum | Yes | Meal plan code, drawn from the standard enum. Allowed: `RO`, `BB`, `HB`, `FB`, `AI`, `TI`, `BI`, `LU`, `DI`, `BD`, `BL`, `LD`. |
|          `data.roomRatePkg.board.boardName` | object | No | Meal plan name, multilingual. |
|          `data.roomRatePkg.board.boardDesc` | object | No | Meal plan description, multilingual. |
|       `data.roomRatePkg.tax` | object | No | Taxes and fees. These are typically collected by the hotel on behalf of the government, are fixed costs, and are excluded from any markup applied during distribution, which is why they are itemised separately. |
|          `data.roomRatePkg.tax.total` | object | No |  |
|          `data.roomRatePkg.tax.items[]` | array<object> | No |  |
|    `data.exchangeRateSnapshot` | object | No | Exchange-rate snapshot captured at CheckAvail time and reused for Booking and for Cancellations/refunds (issue #73). Original source text — 汇率快照，在 CheckAvail 时捕获，用于 Booking 和 Cancellations/refunds 时复用（issue #73） |
|       `data.exchangeRateSnapshot.date` | string | No | Exchange-rate date. Original source text — 汇率日期 |
|       `data.exchangeRateSnapshot.usd` | object | No | Contains only the currencies actually needed, for example {"aed": 0.27, "usd": 1.0, "eur": 1.1}. Original source text — 只包含需要的币种，如 {"aed": 0.27, "usd": 1.0, "eur": 1.1} |


## Failure responses

| HTTP | Meaning |
| --- | --- |
| 400 | Bad Request |
| 401 | Unauthorized |
| 403 | Forbidden |
| 429 | Too Many Requests |

Every failure uses the `{ code, msg }` envelope. See [Error handling](../guides/error-handling) for the full business-code table.
