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

# Quotes

> Frozen prices for 30 minutes before booking

A **quote** is a price you obtain for a specific adventure + rate pack + date + room composition. It is **frozen for 30 minutes**, which means:

* The `net_amount` returned by `POST /quotes` is what you owe SafarAPI when you book.
* Even if the underlying rate pack price changes during those 30 minutes, your quote stays at the quoted price.
* After 30 minutes, the `quote_id` is rejected by `POST /bookings` with `409 partner.booking.quote.expired`.

This pattern guarantees a **stable price during your customer's checkout flow**.

## Lifecycle

```mermaid theme={"theme":"github-dark-dimmed"}
stateDiagram-v2
  [*] --> Fresh: POST /quotes
  Fresh --> Consumed: POST /bookings (within 30 min)
  Fresh --> Expired: 30 min elapse
  Expired --> [*]
  Consumed --> [*]
```

Quotes are single‑use: once `POST /bookings` succeeds with a `quote_id`, the same quote cannot be used twice.

## Pricing logic

The `net_amount` exposed in your quote is the **net amount due to SafarAPI** — that is, the public Safariat price minus any partner‑specific margin negotiated in your contract.

You are free to:

* Show your customer the gross price (your markup on top, your decision)
* Show your customer the net price (zero markup)
* Show your customer a discounted price (you absorbing some of the cost)

SafarAPI does **not enforce** any specific customer‑facing price — only the `net_amount` you remit at booking time.

## Breakdown

The `breakdown` array in the quote response shows you how the total is computed:

```json theme={"theme":"github-dark-dimmed"}
"breakdown": [
  { "label": "adults", "quantity": 2, "unit_amount": "1200.00", "subtotal": "2400.00" }
]
```

For Phase 2A, only the `adults` line is computed (`basePrice × totalAdults`). Child supplements and extra bed pricing land in a future release — the line list will simply grow without breaking changes.

## Anti‑fraud check

When you book with `POST /bookings`, SafarAPI validates that `payment_confirmation.paid_amount_net` strictly equals the quote's `net_amount`. If they differ — by even 1 centime — the booking is rejected with `422 payment.amount.mismatch`.

This is the cornerstone of the trust between SafarAPI and your bank: we trust your bank's payment confirmation **because** the amount cannot be tampered with after the quote.
