> ## Documentation Index
> Fetch the complete documentation index at: https://docs.seyaha.net/llms.txt
> Use this file to discover all available pages before exploring further.

# POST /availability

> Return bookable time slots for a product/option/date range. Seyaha calls this during sync and at checkout.

Seyaha calls `POST /availability` in two situations:

1. **During catalog sync** — for every product × option, with a **60-day lookahead window** from today
2. **At checkout** — real-time check before placing a hold, to verify the slot is still available and get a fresh `availabilityId`

***

## Request

```http theme={null}
POST /availability
Authorization: Bearer <auth_key>
Content-Type: application/json
```

### Request body

| Field            | Type   | Required | Description                                                                                  |
| ---------------- | ------ | -------- | -------------------------------------------------------------------------------------------- |
| `productId`      | string | **Yes**  | Your product `id` from `GET /products`                                                       |
| `optionId`       | string | **Yes**  | Your option `id` from `GET /products`                                                        |
| `localDateStart` | string | **Yes**  | Start of the requested window (`YYYY-MM-DD`)                                                 |
| `localDateEnd`   | string | **Yes**  | End of the requested window (`YYYY-MM-DD`). Seyaha requests up to 60 days ahead during sync. |
| `units`          | array  | **Yes**  | Guest counts. Seyaha always sends `[{ "id": "unit-adult", "quantity": N }]`                  |

```json theme={null}
{
  "productId": "product_abc",
  "optionId": "option_standard",
  "localDateStart": "2026-07-01",
  "localDateEnd": "2026-08-30",
  "units": [
    { "id": "unit-adult", "quantity": 1 }
  ]
}
```

***

## Response

Return an array of availability objects — one per bookable time slot.

```http theme={null}
200 OK
Content-Type: application/json
```

### Availability object

| Field                | Type    | Required | Description                                                                                                                                          |
| -------------------- | ------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`                 | string  | **Yes**  | Unique slot identifier. Seyaha caches this as `availability_id` and sends it back in `POST /bookings/reserve`. **Must be stable for the same slot.** |
| `localDateTimeStart` | string  | **Yes**  | ISO 8601 datetime with timezone offset, e.g. `"2026-07-15T10:00:00+03:00"`                                                                           |
| `localDateTimeEnd`   | string  | **Yes**  | ISO 8601 datetime with timezone offset                                                                                                               |
| `status`             | string  | **Yes**  | See status values below                                                                                                                              |
| `vacancies`          | integer | No       | Remaining bookable spots. Omit or null for `FREESALE`.                                                                                               |
| `capacity`           | integer | No       | Total slot capacity                                                                                                                                  |
| `unitPricing`        | array   | No       | Per-slot prices. Include when prices vary by date or time. If omitted, Seyaha uses the static `pricingFrom` from the option units.                   |

### Status values

| Value       | Seyaha behaviour                            |
| ----------- | ------------------------------------------- |
| `AVAILABLE` | Slot is bookable                            |
| `FREESALE`  | Slot is bookable, unlimited capacity        |
| `LIMITED`   | Slot is bookable, shown as low availability |
| `SOLD_OUT`  | Slot is shown but not bookable              |
| `CLOSED`    | Slot is hidden (`isActive: false`)          |

### Unit pricing object

| Field               | Type    | Required | Description                                                                                                             |
| ------------------- | ------- | -------- | ----------------------------------------------------------------------------------------------------------------------- |
| `unitId`            | string  | **Yes**  | Must match a unit `id` from the option                                                                                  |
| `unitType`          | string  | No       | Guest type: `ADULT`, `CHILD`, `INFANT`, `SENIOR`, `STUDENT`. Also accepted as `type` (Seyaha reads `unitType ?? type`). |
| `original`          | integer | **Yes**  | Price in smallest currency unit. Also accepted as `retail` or `price` — Seyaha reads `original ?? retail ?? price`.     |
| `currency`          | string  | **Yes**  | ISO 4217, e.g. `"SAR"`                                                                                                  |
| `currencyPrecision` | integer | No       | Decimal places, default 2                                                                                               |

***

## Full example

```json theme={null}
[
  {
    "id": "avail_2026-07-15-10",
    "localDateTimeStart": "2026-07-15T10:00:00+03:00",
    "localDateTimeEnd": "2026-07-15T16:00:00+03:00",
    "status": "AVAILABLE",
    "vacancies": 14,
    "capacity": 20,
    "unitPricing": [
      {
        "unitId": "unit-adult",
        "unitType": "ADULT",
        "original": 25000,
        "currency": "SAR",
        "currencyPrecision": 2
      },
      {
        "unitId": "unit-child",
        "unitType": "CHILD",
        "original": 15000,
        "currency": "SAR",
        "currencyPrecision": 2
      }
    ]
  },
  {
    "id": "avail_2026-07-15-18",
    "localDateTimeStart": "2026-07-15T18:00:00+03:00",
    "localDateTimeEnd": "2026-07-16T00:00:00+03:00",
    "status": "LIMITED",
    "vacancies": 2,
    "capacity": 20,
    "unitPricing": [
      {
        "unitId": "unit-adult",
        "unitType": "ADULT",
        "original": 30000,
        "currency": "SAR",
        "currencyPrecision": 2
      }
    ]
  }
]
```

If an option has no availability in the requested window, return an empty array:

```json theme={null}
[]
```

***

## Implementation notes

<Warning>
  `availability.id` is the most critical field in this response. Seyaha caches it as
  `availability_id` on the slot and sends it back in `POST /bookings/reserve`. If you
  change this ID for the same physical slot, Seyaha will call `POST /availability`
  again at checkout to resolve a fresh one — this adds latency to every checkout.
  Keep IDs stable.
</Warning>

<Note>
  Include `unitPricing` if prices vary by date, time, or demand (e.g. peak/off-peak).
  If all slots for an option have the same price, you can omit `unitPricing` entirely
  and Seyaha falls back to the static `pricingFrom` on the option's units.
</Note>

* Timeout: **20 seconds** — the longest Seyaha allows. Aim to respond within 15 seconds.
* During sync, Seyaha calls this for **every option of every product**. For 100 products × 3 options = 300 calls per sync. Use efficient database queries or a pre-computed availability table.
* Return `[]` for options with no availability — not a 404 or error.
