# Supplier selection

> Let FX-Port select suppliers automatically, or pass exact supplier ids for a special case.

Source: https://fx-port.com/docs/flights/search/suppliers

Most integrations send no supplier field at all. FX-Port keeps the list of enabled suppliers, selects those that can serve the route and the passenger mix, calls them in parallel, and returns each answer under its own `searchId` in `suppliers[]`. This page says how that selection works, what you can force, and what the sandbox offers.

## Suppliers in the sandbox

`GET /api/v1/suppliers` (Read) lists the enabled suppliers with their capabilities; see [Suppliers](https://fx-port.com/docs/suppliers.md). The sandbox has two flight suppliers:

| `supplier_id` | Name | Routes | Hold | Void | Flexible dates | Notes |
|---|---|---|---|---|---|---|
| `amadeus_aqc_dz_1` | Amadeus Algeria | Only routes that **touch Algeria** (`routes: ["DZ"]`) | Yes | Yes | Yes | Source of the ACD fares. Never returns carrier `BA`. |
| `duffel_1` | Duffel | Worldwide (`routes: ["*"]`) | No | No | No | Instant ticketing only. Offers expire 15 to 60 minutes after the search. |

Other suppliers exist in the code and are disabled; they do not appear in the list and cannot be selected. Never hard-code the catalogue: read `GET /suppliers`.


> [!WARNING]
> The suppliers' own **test systems** can be unstable: an Amadeus request can fail in the sandbox for a reason that does not exist on live. The failed supplier is listed in `failures[]` and the others still answer. See [Sandbox](https://fx-port.com/docs/sandbox.md).


## Automatic selection (recommended)


**Request**

```bash
curl https://api.fx-port.com/api/v1/get_flights \
  -H "Authorization: Bearer fxp_test_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "origin": "ALG",
  "destination": "CDG",
  "departure_date": "2026-12-15",
  "cabin_class": "economy",
  "passengers": {
    "adults": 1
  }
}'
```


Do not send `supplier_id` or `supplier_ids`. FX-Port handles the priority, the compatibility and the activation of new suppliers without a change on your side. If one supplier fails while another returns offers, you get the offers and the failure in `failures[]`.

The rules, verified on the sandbox on 2026-11-01:

| Route | Suppliers called |
|---|---|
| `ALG` to `CDG` (touches Algeria) | `amadeus_aqc_dz_1` and `duffel_1` |
| `LHR` to `CDG` | `duffel_1` only: Amadeus Algeria is eligible only when an airport of the route is in Algeria, or `from_cc` or `to_cc` is `DZ`, or `countries` contains `DZ` |
| `ALG` to `ORN` (domestic) | both, unless you send `from_cc: "DZ"` and `to_cc: "DZ"`: then Duffel is skipped |
| A passenger mix one supplier cannot serve | That supplier is skipped silently; `400 supplier_passenger_combination_unsupported` only when none is left. See [Flight passengers & ages](https://fx-port.com/docs/flights/passengers.md) |


> [!NOTE]
> **Country hints change the result.** For a search **from Algeria to a foreign country** FX-Port limits Duffel to the airlines `TO` and `BA` when the request carries `from_cc` and `to_cc`. `ALG` to `CDG` with `"from_cc": "DZ", "to_cc": "FR"` returned **one** Duffel offer (`filtersApplied.includedAirlines` was `["TO","BA"]`) against 92 without the hints. FX-Port's own website sends the hints; a server integration normally does not. Do not send `from_cc`, `to_cc` or `countries` unless you want this behaviour.


## Exact supplier ids (advanced)

Use them for tests or for a commercial rule of yours. A selection is **strict**: it never substitutes another supplier.

| Field | Type | Behaviour |
|---|---|---|
| `supplier_id` | string | One id, or several separated by commas (`"duffel_1,amadeus_aqc_dz_1"`). |
| `supplier_ids` | string[] | A set of ids (up to 10). Merged with `supplier_id` without duplicates. |
| `preferred_suppliers` | string[] | A **hint**: ids that cannot be used are ignored and the automatic selection applies. `["duffel_1"]` returned Duffel only. |
| `max_suppliers` | integer | Keep only the first N selected suppliers, in priority order (Amadeus Algeria before Duffel). `1` returned Amadeus Algeria only. `"1"` and `1.0` are read as 1 with a `coerced_value` warning; an empty text means no limit. |


**Request**

```bash
curl https://api.fx-port.com/api/v1/get_flights \
  -H "Authorization: Bearer fxp_test_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "origin": "ALG",
  "destination": "CDG",
  "departure_date": "2026-12-15",
  "cabin_class": "economy",
  "passengers": {
    "adults": 1
  },
  "supplier_ids": [
    "amadeus_aqc_dz_1",
    "duffel_1"
  ]
}'
```


Legacy names: `supplierId`, `supplierIds`, `preferredSuppliers`, `maxSuppliers` still work (see [Search flights](https://fx-port.com/docs/flights/search.md#legacy-names)).

An unknown or disabled id, or an id that cannot do flexible search on `flexible_search`, is answered with `400 invalid_supplier_selection`:

~~~json
{
  "environment": "sandbox",
  "detail": {
    "error": "invalid_supplier_selection",
    "message": "One or more requested suppliers cannot be used for this flight search.",
    "invalidSuppliers": ["nope_1"],
    "disabledSuppliers": [],
    "unsupportedFlexibleSuppliers": [],
    "availableSuppliers": ["amadeus_aqc_dz_1", "duffel_1"]
  }
}
~~~

A selection does not widen the supplier's reach: `"supplier_id": "amadeus_aqc_dz_1"` on `LHR` to `CDG` is a valid selection and answers `200` with a supplier entry that has `results.totalOffers: 0` and an empty `offers` list.

## Price and book never take a supplier

Only a search chooses suppliers. `price_flight` and `book_flight` find the supplier from the offer they are given (the `searchId` and the offer `id`), so the `supplier_id` you passed to the search is not needed again. The supplier of a booking is `supplier.id` in the response.

## Related

- [Suppliers](https://fx-port.com/docs/suppliers.md): the live list and the capabilities.
- [Search flights](https://fx-port.com/docs/flights/search.md), [Filters](https://fx-port.com/docs/flights/search/filters.md) and [Sandbox](https://fx-port.com/docs/sandbox.md).
