Booking history
Booking summaries across all products, newest first.
GET/api/v1/history
GET /
Permission: Read
Booking summaries across one or all products (flights, hotels, eSIMs and transfers), newest first, limited to the
environment of your key. eSIM orders and topups are listed (type tells them apart).
Query parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
product | string | all | all, flights, hotels, esims or transfers. Case does not matter and the singular names (flight, hotel, esim, transfer) are read as the plural. Anything else is 400 invalid_product |
status | string | none | Keep bookings with exactly this status, for example confirmed. Case does not matter; spaces and hyphens are read as underscores (On Hold is on_hold); letters, digits and _, at most 32 characters. pending is accepted as another name of awaiting_payment. A status nothing has returns an empty list |
date_from | string | none | Inclusive start, on the creation time of the booking. Any ISO 8601 spelling is read: a date (2026-07-01 or 20260701, 00:00:00 UTC) or a datetime with 1 to 9 fraction digits and an offset written Z, +01:00 or +0100 (in a URL write the + as %2B). Without an offset a datetime is UTC |
date_to | string | none | Inclusive end, in the same spellings. A bare date means the end of that day (23:59:59.999999 UTC). Not before date_from |
page | integer | 1 | The page, starting at 1 (at most 10,000). An empty value means not sent |
limit | integer | 20 | Entries per page, 1 to 100 (not 200). A larger value is refused with 422 validation_error; an empty value means not sent |
Legacy names (still work; the response carries a deprecated_field warning; date_from and date_to win when both are sent):
| Legacy | Use instead |
|---|---|
from, from_date | date_from |
to, to_date | date_to |
Never send agency_id: an API key that does is refused with 400 agency_id_not_allowed.
Pagination
pagination is { page, limit, total, total_pages, hasMore, has_more }. total is the real number of bookings
that match (all products together). The pages are served from the 200 newest bookings of each product, so
with product=all at most 800 bookings can be reached by paging: follow has_more (hasMore is the same value), and
use date_from and date_to to read an older period.
Request examples
# The latest eSIM bookings
curl --get \
--url https://api.fx-port.com/api/v1/history \
--header 'Authorization: Bearer fxp_test_YOUR_KEY' \
--data-urlencode 'product=esims' \
--data-urlencode 'limit=2'
# Confirmed flights of a period
curl --get \
--url https://api.fx-port.com/api/v1/history \
--header 'Authorization: Bearer fxp_test_YOUR_KEY' \
--data-urlencode 'product=flights' \
--data-urlencode 'status=confirmed' \
--data-urlencode 'date_from=2026-11-01' \
--data-urlencode 'date_to=2026-11-30'const params = new URLSearchParams({ product: "flights", status: "confirmed", date_from: "2026-11-01", limit: "100" });
const response = await fetch(`https://api.fx-port.com/api/v1/history?${params}`, {
headers: { Authorization: "Bearer fxp_test_YOUR_KEY" },
});
const { data: bookings, pagination } = await response.json();
// keep the internal id as your key; bookingId is a display reference
const ids = bookings.map((booking) => booking.id);import requests
response = requests.get(
"https://api.fx-port.com/api/v1/history",
params={"product": "esims", "limit": 50, "date_from": "2026-11-01"},
headers={"Authorization": "Bearer fxp_test_YOUR_KEY"},
timeout=30,
)
body = response.json()Response example
An eSIM order, as the API returns it (a sandbox answer of the request above):
{
"environment": "sandbox",
"success": true,
"data": [
{
"product": "esims",
"id": "639417b4-b103-4ece-bd5d-850315322278",
"bookingId": "FX-1793546602916",
"booking_id": "FX-1793546602916",
"status": "confirmed",
"environment": "sandbox",
"agencyId": "0b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d",
"agency_id": "0b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d",
"agentId": null,
"agent_id": null,
"currency": "DZD",
"totalPrice": 468.84,
"total_price": 468.84,
"netPrice": 418.6,
"b2b_price": 418.6,
"agencyCommission": 50.24,
"agency_commission": 50.24,
"providerName": "Airalo",
"provider_name": "Airalo",
"supplierId": "airalo",
"supplier_id": "airalo",
"createdAt": "2026-11-01T15:23:22.961228+00:00",
"created_at": "2026-11-01T15:23:22.961228+00:00",
"updatedAt": "2026-11-01T15:23:22.961228+00:00",
"updated_at": "2026-11-01T15:23:22.961228+00:00",
"orderId": "20261101-106852",
"order_id": "20261101-106852",
"type": "esim",
"packageName": "1 GB - 7 days • France",
"package_name": "1 GB - 7 days • France",
"iccid": "8900000540463077957",
"customerEmail": "[email protected]",
"customer_email": "[email protected]",
"customer_first_name": "John",
"customer_last_name": "Smith",
"customer_phone": "+15555550123"
}
],
"pagination": { "page": 1, "limit": 2, "total": 80, "total_pages": 40, "hasMore": true, "has_more": true },
"meta": {
"agencyId": "0b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d",
"agency_id": "0b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d",
"environment": "sandbox",
"product": "esims"
}
}The entries of the other products have the same first fifteen keys and their own keys after updatedAt. They are shown
without their snake_case twins to keep them short:
{
"product": "flights",
"id": "8723790a-0417-46bb-8247-07254b214a4c",
"bookingId": "Y7INFJ",
"status": "awaiting_payment",
"environment": "sandbox",
"agencyId": "0b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d",
"agentId": null,
"currency": "DZD",
"totalPrice": 32593.93,
"netPrice": 32561.36,
"agencyCommission": 32.57,
"providerName": "Amadeus Algeria",
"supplierId": "amadeus_aqc_dz_1",
"createdAt": "2026-11-01T14:31:20.248661+00:00",
"updatedAt": "2026-11-01T14:31:22.611902+00:00",
"departureAirport": "ALG",
"arrivalAirport": "CDG",
"departureDate": "2026-12-15T07:15:00",
"arrivalDate": "2026-12-15T09:45:00",
"ticketNumber": null,
"requireAcd": false,
"voucherUrl": "https://files.example.com/flight-bookings/Y7INFJ-JOHN-SMITH.pdf",
"voucherUrlWithPrice": "https://files.example.com/flight-bookings/Y7INFJ-JOHN-SMITH.pdf",
"voucherUrlNoPrice": "https://files.example.com/flight-bookings/Y7INFJ-JOHN-SMITH-no-price.pdf"
}{
"product": "hotels",
"id": "34a08cf3-dff6-45c6-bdae-882061aa78f5",
"bookingId": "HMVXX4ZQ3",
"status": "refunded",
"environment": "sandbox",
"agencyId": "0b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d",
"agentId": null,
"currency": "DZD",
"totalPrice": 1484.97,
"netPrice": 1482.0,
"agencyCommission": 2.97,
"providerName": "ETG - RateHawk",
"supplierId": "ratehawk",
"createdAt": "2026-11-01T14:22:00.924125+00:00",
"updatedAt": "2026-11-01T14:22:32.992144+00:00",
"hotelId": "test_hotel_do_not_book",
"hotelName": "Test Hotel (Do Not Book) test",
"checkinDate": "2026-12-01",
"checkoutDate": "2026-12-04",
"bookingMode": "standard",
"voucherUrl": "https://files.example.com/hotel-bookings/HMVXX4ZQ3-Jane-Smith.pdf",
"voucherUrlWithPrice": "https://files.example.com/hotel-bookings/HMVXX4ZQ3-Jane-Smith.pdf",
"voucherUrlNoPrice": "https://files.example.com/hotel-bookings/HMVXX4ZQ3-Jane-Smith-no-price.pdf"
}{
"product": "transfers",
"id": "4745c761-0737-421a-aaab-c90f9c0aca8f",
"bookingId": "VIA-1782555657-QCF",
"status": "refunded",
"environment": "sandbox",
"agencyId": "0b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d",
"agentId": "5d6e7f80-91a2-4b3c-8d4e-5f6071829304",
"currency": "DZD",
"totalPrice": 15124.38,
"netPrice": 15002.38,
"agencyCommission": 122.0,
"providerName": "AirportTransfer.com",
"supplierId": null,
"createdAt": "2026-06-27T10:20:59.188372+00:00",
"updatedAt": "2026-06-27T10:29:28.684+00:00",
"arrivalDate": "2026-08-14T16:00:00+00:00",
"flightNumber": "593",
"voucherUrl": null,
"receiptUrl": "https://files.example.com/transfer-bookings/VIA-1782555657-QCF.pdf"
}Summary fields
Every product
| Field (twin) | Description |
|---|---|
product | flights, hotels, esims or transfers |
id | The internal id of the booking (UUID). Stable and unique: use it as your key |
bookingId (booking_id) | The public reference: the airline record locator of a flight (not unique across suppliers), the hotel booking id, FX- followed by a number for an eSIM, or the transfer reference |
status | The state of the booking (see below) |
environment | sandbox or live |
agencyId (agency_id) | Your agency UUID |
agentId (agent_id) | The user of your agency who created the booking, or null when it was created through an API key without a user |
currency | Your agency currency: the currency of every amount |
totalPrice (total_price) | What the traveler pays, with your commission |
agencyCommission (agency_commission) | Your commission as an amount. 0 when there is none |
netPrice (b2b_price) | The amount debited from your balance: totalPrice minus agencyCommission |
providerName (provider_name) | The supplier that fulfilled the booking |
supplierId (supplier_id) | The supplier id stored on the booking (see the note below) |
createdAt (created_at), updatedAt (updated_at) | ISO 8601, UTC |
Flights: departureAirport, arrivalAirport (IATA), departureDate, arrivalDate (local, without a zone), ticketNumber
(null until issued), requireAcd (require_acd), voucherUrl and voucherUrlWithPrice (the confirmation PDF with prices) and
voucherUrlNoPrice (without prices, to give to the traveler). The voucher links are null while the PDF is generated.
Hotels: hotelId, hotelName (can be null on a failed booking), checkinDate, checkoutDate (YYYY-MM-DD), bookingMode, and
the same three voucher links.
eSIMs: orderId (order_id, the supplier's order code), type (esim or topup), packageName (package_name), iccid,
customerEmail (customer_email), customer_first_name, customer_last_name, customer_phone.
Transfers: arrivalDate, flightNumber, voucherUrl (the supplier voucher: null until a driver is assigned) and receiptUrl
(FX-Port's receipt PDF, once the booking is confirmed).
Status values
| Status | Products | Meaning |
|---|---|---|
confirmed | All | The booking is confirmed |
awaiting_payment | Flights | A held booking that is not paid yet. pending is accepted as another name in the filter |
cancelled | Flights | The booking was cancelled |
failed | Flights, eSIMs | The supplier refused the booking |
refunded | Flights, hotels, transfers | The booking was refunded |
partial_refund | Flights | Part of the booking was refunded |
These are the values seen today; a product can use others, and a filter on a status nothing has answers an empty list.
Errors
| HTTP | code | Cause |
|---|---|---|
400 | invalid_product | product is not one of the allowed values (details.allowed lists them) |
400 | invalid_status | status is not a plain status name (letters, digits, _, spaces or hyphens, at most 32 characters) |
400 | invalid_date, invalid_date_range | A date is not valid, or date_from is after date_to |
400 | agency_id_not_allowed | An API key sent agency_id |
401 | authentication_required, invalid_api_key | Missing or invalid API key |
422 | validation_error | page is below 1 or above 10,000, or limit is above 100 |
429 | rate_limit_exceeded | Over 6,000 requests per minute for this key |
503 | service_overloaded | The service is shedding load for a moment (its database pool is full). Nothing was read: retry after the seconds in Retry-After (2 to 5) |