# Suppliers

> Discover every enabled supplier across all products, with capabilities and void deadlines.

Endpoint: `GET /api/v1/suppliers`

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

`GET /api/v1/suppliers`

**Permission:** Read. **Rate limit:** the default group, 6,000 requests per minute per key.

Returns the suppliers that are **enabled** for your key, grouped by product: flights, hotels and eSIMs. This endpoint
spans every product, not only flights. A product with no enabled supplier is left out, and so are disabled suppliers.


> [!NOTE]
> **Read the list, do not hard-code it.** The suppliers FX-Port connects to change over time, and so do their ids and
> descriptions. Your integration should read this list (and cache it for a while: see [Rate limits](https://fx-port.com/docs/rate-limits.md))
> and take the `id` it needs from it.


## Request


**cURL**

~~~bash
curl --request GET \
  --url https://api.fx-port.com/api/v1/suppliers \
  --header 'Authorization: Bearer fxp_test_YOUR_KEY'
~~~

**Node.js**

~~~js
const response = await fetch("https://api.fx-port.com/api/v1/suppliers", {
  headers: { Authorization: "Bearer fxp_test_YOUR_KEY" },
});
const { products } = await response.json();
const flights = products.find((entry) => entry.product === "flights")?.suppliers ?? [];
const canHold = flights.filter((supplier) => supplier.capabilities?.hold);
~~~

**Python**

~~~python
import requests

response = requests.get(
    "https://api.fx-port.com/api/v1/suppliers",
    headers={"Authorization": "Bearer fxp_test_YOUR_KEY"},
    timeout=30,
)
products = response.json()["products"]
~~~


## Response example

A sandbox answer. `description` is free text written by FX-Port: it is shortened to `...` here and can change.

~~~json
{
  "environment": "sandbox",
  "success": true,
  "products": [
    {
      "product": "flights",
      "suppliers": [
        {
          "id": "amadeus_aqc_dz_1",
          "name": "Amadeus Algeria",
          "technology": "amadeus_aqc",
          "routes": ["DZ"],
          "description": "...",
          "capabilities": { "hold": true, "void": true, "flexible_dates": true, "ancillaries": false },
          "voidDeadline": "2026-11-01T23:00:00Z",
          "void_deadline": "2026-11-01T23:00:00Z"
        },
        {
          "id": "duffel_1",
          "name": "Duffel",
          "technology": "duffel",
          "routes": ["*"],
          "description": "...",
          "capabilities": { "hold": false, "void": false, "flexible_dates": false, "ancillaries": true },
          "voidDeadline": "2026-11-02T00:00:00Z",
          "void_deadline": "2026-11-02T00:00:00Z"
        }
      ]
    },
    {
      "product": "hotels",
      "suppliers": [
        { "id": "worldota_1", "name": "RateHawk", "technology": "worldota", "description": "..." }
      ]
    },
    {
      "product": "esims",
      "suppliers": [
        { "id": "airalo_1", "name": "Airalo", "technology": "airalo", "description": "..." }
      ]
    }
  ],
  "meta": { "environment": "sandbox", "permissionRequired": "read", "permission_required": "read" }
}
~~~

## What the list contains

| Product | Supplier `id` | Name | `technology` |
|---|---|---|---|
| Flights | `amadeus_aqc_dz_1` | Amadeus Algeria | `amadeus_aqc` |
| Flights | `duffel_1` | Duffel | `duffel` |
| Hotels | `worldota_1` | RateHawk | `worldota` |
| eSIMs | `airalo_1` | Airalo | `airalo` |

These are the suppliers of the sandbox today. The eSIM block is listed when the eSIM supplier is configured. FX-Port
can enable more suppliers (and disable some): the list tells what your key can use right now.

## Field reference

### Every supplier

| Field | Type | Description |
|---|---|---|
| `id` | string | The supplier identifier. Send it as `supplier_id` where an endpoint takes one (for example in a flight search) |
| `name` | string | The name of the supplier |
| `technology` | string | How FX-Port connects to the supplier: `amadeus_aqc` (an Amadeus office with negotiated fares), `duffel`, `worldota` (hotels) or `airalo` (eSIMs) today. New values appear when connections are added: do not hard-code them |
| `description` | string | What the supplier is good for. Free text: do not parse it |

### Flight suppliers only

| Field | Type | Description |
|---|---|---|
| `routes` | string[] | The markets the supplier serves. A country code (for example `"DZ"`) means routes from and to that country; `"*"` means every market |
| `capabilities.hold` | boolean | The supplier can hold a booking to pay later |
| `capabilities.void` | boolean | The supplier can void an issued ticket on the day of issue |
| `capabilities.flexible_dates` | boolean | The supplier supports the flexible-dates search |
| `capabilities.ancillaries` | boolean | The supplier sells extras such as seats and bags |
| `voidDeadline` | string | The next void cut-off, in UTC: the next midnight in the supplier's time zone (see below). `void_deadline` carries the same value |

Hotel and eSIM suppliers have only `id`, `name`, `technology` and `description`.

### `meta`

| Field | Description |
|---|---|
| `environment` | The environment of your key: `sandbox` or `live` |
| `permissionRequired` | `read`: the permission the endpoint needs. `permission_required` carries the same value |

## Sandbox and live

The endpoint, the shape and the way to read it are the same in both environments, and the list is **not filtered by
the environment of your key**: `meta.environment` only tells which environment answered. What differs is what a
supplier's own test system can do: see [Sandbox](https://fx-port.com/docs/sandbox.md).

## Supplier ids in your bookings

The id in this list is the one to send to the API. The bookings of your account carry the id stored on the booking
(`supplierId` in the [booking history](https://fx-port.com/docs/account/history.md)), and that id is not always the same one:

| Supplier | Id in this list | `supplierId` on bookings |
|---|---|---|
| Amadeus Algeria | `amadeus_aqc_dz_1` | `amadeus_aqc_dz_1` |
| Duffel | `duffel_1` | `duffel_1` |
| RateHawk | `worldota_1` | `ratehawk` |
| Airalo | `airalo_1` | `airalo` |

Do not match bookings with this list on the id alone: use `providerName` or keep your own mapping.

## The `voidDeadline` field


> [!WARNING]
> `voidDeadline` is recalculated on every request: **do not keep it across days**. It is the next midnight in the
> supplier's operating time zone, expressed in UTC. It is present on the flight suppliers whatever `capabilities.void`
> says (a supplier with `void: false` still carries one), so read `capabilities.void` first. Void eligibility also varies
> by airline: check it immediately before you attempt a void.


## Errors

| HTTP | `code` | Cause |
|---|---|---|
| `401` | `authentication_required`, `invalid_api_key` | Missing or invalid API key |
| `429` | `rate_limit_exceeded` | Over 6,000 requests per minute for this key |
