# Quote a held booking

> Get the current price and payment status of a held order before paying.

Endpoint: `POST /api/v1/flights/get_order_quote`

Source: https://fx-port.com/docs/flights/get-order-quote

Get the current quote of an order: its price, its status and whether it can still be paid. The step is **optional**: call it when you want to preview or refresh the price of a held order before you pay.

**Permission:** Read. **Rate group:** booking (1,200 requests per minute per key).

## Identifying the order

Send **one** of these; the first one present wins, in this order. Another one that holds a different value is dropped, and an `ignored_field` warning names it.

| Field | Description |
|---|---|
| `order_id` | The supplier's order id: `booking.reference` of the booking response. **Preferred.** |
| `booking_id` | The PNR of the booking. |
| `pnr` | The airline record locator. |
| `supplier_id` | Not needed: the supplier is read from the booking. |

The order must be a booking of **your agency** in the environment of your key. An unknown order, an order of another agency and the FX-Port UUID (which is not accepted here) all answer the same `404 not_found`, before any supplier is asked.


> [!WARNING]
> **PNRs are not unique.** The same PNR can exist at another supplier or airline, so a lookup by PNR can be ambiguous. Use `order_id` whenever you can.


Legacy names: `orderId`, `bookingId`, `supplierId` still work and are answered with a `deprecated_field` warning.

## Request example


**Request**

```bash
curl https://api.fx-port.com/api/v1/flights/get_order_quote \
  -H "Authorization: Bearer fxp_test_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "order_id": "eJzTd9ePNA9wdA0FAAs8AmE"
}'
```


## Response example

The held Amadeus Algeria order from [Book a flight](https://fx-port.com/docs/flights/book.md#response-example-hold), before it is paid. An Amadeus order is answered from the stored booking, without calling the supplier.

~~~json
{
  "environment": "sandbox",
  "success": true,
  "requestId": "469d8803",
  "orderId": "eJzTd9ePNA9wdA0FAAs8AmE",
  "processingTime": 0.134,
  "orderQuote": {
    "orderId": "eJzTd9ePNA9wdA0FAAs8AmE",
    "bookingReference": "Y7PAEU",
    "status": "awaiting_payment",
    "pricing": {
      "supplierCurrency": "DZD",
      "agencyCurrency": "DZD",
      "basePrice": 3160.0,
      "taxesAndFees": 1765.44,
      "agencyCommission": 4.93,
      "finalPrice": 4930.37,
      "b2bPrice": 4925.44,
      "additionalServices": [],
      "totalAmount": 4925.44
    },
    "paymentStatus": {
      "awaitingPayment": true,
      "paymentRequiredBy": null,
      "priceGuaranteeExpiresAt": null,
      "priceGuaranteed": true,
      "canPay": true
    },
    "liveMode": false
  },
  "supplier": { "id": "amadeus_aqc_dz_1", "technology": "amadeus_aqc", "name": "Amadeus Algeria" },
  "agency": { "currency": "DZD" },
  "meta": { "priceGuaranteed": true, "paymentDeadline": null, "canPay": true }
}
~~~

## Field meanings

| Field | Meaning |
|---|---|
| `orderId` | The supplier's order id (twin: `order_id`). |
| `orderQuote.bookingReference` | The PNR (twin: `orderQuote.pnr`). |
| `orderQuote.status` | `awaiting_payment` for a held order; `confirmed` or `cancelled` otherwise. |
| `orderQuote.pricing` | The price block of [Flight pricing](https://fx-port.com/docs/flights/pricing.md). **`b2bPrice` and `totalAmount` are the same number: what will be debited from your balance.** |
| `orderQuote.paymentStatus` | `awaitingPayment`, `paymentRequiredBy` (the deadline, when the supplier gives one), `priceGuaranteeExpiresAt`, `priceGuaranteed`, `canPay`. |
| `orderQuote.liveMode` | `false` in the sandbox, `true` on live. |
| `supplier`, `agency` | The supplier of the order, and your agency's id and currency. |
| `meta` | `priceGuaranteed`, `paymentDeadline`, `canPay`. |
| `exchangeRate` | Only when the currencies differ. On a **Duffel** order it is an object `{ "rate", "marginPercent", "fromCurrency", "toCurrency" }`, not a number. |

A **Duffel** order is answered by the supplier, live: the quote adds `orderQuote.pricing.taxAmount` and `originalTaxAmount`, the re-priced amounts can differ from what was charged at booking (21,434.22 against 21,505.29 in our test), and an order that is already paid has `canPay: false` and `priceGuaranteed: false`.

An order of an ACD booking has `orderQuote.pricing.acd`; see [Flight pricing](https://fx-port.com/docs/flights/pricing.md#the-acd-block-amadeus-algeria).


> [!WARNING]
> **`canPay` is not a guarantee.** Payment can still fail because the PNR expired or was cancelled, the deadline passed, or the airline released the reservation. The answer of [`pay_order`](https://fx-port.com/docs/flights/pay-order.md) is the only truth: handle a payment failure even when `canPay` was `true` a moment ago.


## Errors

An order that is not a booking of your agency is a `404` with the text `Booking not found for order_id: <id>` and the code `not_found`. Unknown orders and orders of other agencies are answered **identically**:

~~~json
{
  "environment": "sandbox",
  "detail": "Booking not found for order_id: ZZZZZZ",
  "success": false,
  "errors": [
    {
      "code": "not_found",
      "type": "not_found",
      "title": "Not found",
      "message": "Booking not found for order_id: ZZZZZZ",
      "field": null,
      "details": {},
      "documentation_url": "https://fx-port.com/docs/errors#not_found"
    }
  ],
  "meta": { "request_id": "req_8f3a61c2d9e4", "status": 404 },
  "request_id": "req_8f3a61c2d9e4"
}
~~~

When the supplier refuses the quote for an order that FX-Port knows (a Duffel order that is gone at the supplier, for example), the answer is **not** a `404`: it is `200` with `success: false` and the supplier's own error. Real shape of 2026-11-01:

~~~json
{
  "environment": "sandbox",
  "success": false,
  "requestId": "0582790e",
  "orderId": "ZZZZZZ",
  "processingTime": 0.085,
  "error": {
    "message": "The resource you are trying to access does not exist.",
    "code": "not_found",
    "type": "invalid_request_error",
    "details": [{ "title": "Not found", "type": "invalid_request_error", "message": "The resource you are trying to access does not exist.", "code": "not_found" }]
  },
  "supplier": { "id": "duffel_1", "technology": "duffel", "name": "Duffel" },
  "meta": {}
}
~~~

Always read `success`. `errors[0].type` is `supplier_error` (or `not_found`) for these answers.

| Status | Code | When |
|---|---|---|
| `200` | `not_found`, other supplier codes | `success: false`: the supplier refused the quote. |
| `400` | `bad_request` | None of `order_id`, `booking_id` and `pnr` was sent: `Missing required parameter: order_id (or booking_id / pnr)`. |
| `400` | `invalid_booking_id` | The id is not a valid token: letters, digits and `- _ . : = ~`, up to 128 characters. |
| `400` | `invalid_json`, `invalid_body` | The body is not a JSON object. |
| `404` | `not_found` | The order is not a booking of your agency in this environment. |

## Related

- [Pay a held booking](https://fx-port.com/docs/flights/pay-order.md) and [Cancel a held booking](https://fx-port.com/docs/flights/cancel-order.md).
- [Book a flight](https://fx-port.com/docs/flights/book.md) and [Booking flows](https://fx-port.com/docs/flights/booking-flows.md).
