eSIM bookings
List the eSIM orders of your agency, read the topups of an eSIM and check that a booking is yours.
Three read-only endpoints cover the eSIM orders of your agency: the list of orders, the topups of one eSIM, and a check that a booking reference is yours. Orders and topups are stored as bookings of the same shape; the list shows orders only, and the topups of an eSIM are read with the topup history.
List bookings
GET /
Permission: Read
A paginated list of the eSIM orders of your agency in this environment, newest first. A sandbox key lists
sandbox orders and a live key lists live orders. Topups are not in this list: read them with the
topup history of the eSIM, or in the account history,
which lists orders and topups together. A failed attempt is listed too, with the status failed.
curl --request GET \
--url 'https://api.fx-port.com/api/v1/esims/bookings?page=1&limit=50&[email protected]' \
--header 'Authorization: Bearer fxp_test_YOUR_KEY'const params = new URLSearchParams({ page: "1", limit: "50", search: "[email protected]" });
const response = await fetch(`https://api.fx-port.com/api/v1/esims/bookings?${params}`, {
headers: { Authorization: "Bearer fxp_test_YOUR_KEY" },
});
const { data: bookings, pagination } = await response.json();import requests
response = requests.get(
"https://api.fx-port.com/api/v1/esims/bookings",
params={"page": 1, "limit": 50, "search": "[email protected]"},
headers={"Authorization": "Bearer fxp_test_YOUR_KEY"},
timeout=30,
)
body = response.json()| Query parameter | Description |
|---|---|
search | Part of a booking id, the traveler's first or last name, the email, the package name or the ICCID. It does not match the supplier order code or the phone number. At most 100 characters |
page | The page, starting at 1 (at most 10,000) |
limit | Bookings per page, 1 to 200 (default 50). A larger value is refused with 422 validation_error |
all | true returns the largest pages: 200 bookings, see below |
An empty page, limit or all (?page=) means not sent and takes the default.
search is safe with any text. Characters other than letters, digits and @ . - _ + ' : / are treated as
spaces, so brackets, commas, quotes or wildcards cannot break the search. A term longer than 100 characters, or one
with control characters, is refused with 400 invalid_search; a term with nothing searchable in it answers an
empty page. pagination.total counts the orders that match, search included.
all=true does not return every booking in one answer: an API key gets pages of at most 200 bookings
(limit defaults to 200). The response carries a coerced_value warning. Follow pagination.has_more and
page to read the rest.
Response example
{
"environment": "sandbox",
"success": true,
"data": [
{
"id": "639417b4-b103-4ece-bd5d-850315322278",
"booking_id": "FX-1793546602916",
"order_id": "20261101-106852",
"status": "confirmed",
"currency": "DZD",
"total_price": 468.84,
"agency_commission": 50.24,
"type": "esim",
"package_name": "1 GB - 7 days • France",
"iccid": "8900000540463077957",
"customer_email": "[email protected]",
"customer_first_name": "John",
"customer_last_name": "Smith",
"customer_phone": "+15555550123",
"provider_name": "Airalo",
"supplier_id": "airalo",
"created_at": "2026-11-01T15:23:22.961228+00:00",
"updated_at": "2026-11-01T15:23:22.961228+00:00",
"environment": "sandbox"
}
],
"pagination": { "total": 61, "page": 1, "limit": 1, "pages": 61, "total_pages": 61, "has_more": true }
}Booking fields
| Field | Meaning |
|---|---|
id | Internal id of the booking row (UUID): the id the account history returns |
booking_id | The FX-Port reference, FX- followed by a number. Use it in setup instructions and in the booking detail |
order_id | The supplier's order code (code in the order response) |
status | confirmed, or failed when the supplier refused the order (the ICCID of such a row starts with PENDING-) |
type | esim for an order, topup for a topup |
currency, total_price | Your agency currency and the price charged to the traveler |
agency_commission | Your commission as an amount. The amount debited from your balance is total_price minus this amount (see eSIM pricing) |
package_name | Package name, with the destination for an order |
iccid | The ICCID of the eSIM. A topup row carries the ICCID that was topped up |
customer_email, customer_first_name, customer_last_name, customer_phone | The traveler details you sent when ordering |
provider_name, supplier_id | The supplier that fulfilled the booking. Here airalo: the supplier list calls the same supplier airalo_1 |
created_at, updated_at | ISO 8601 with a zone (UTC) |
environment | sandbox or live |
Only agency-facing fields are returned: the supplier's cost and FX-Port's internal margins are never part of a booking.
Pagination
| Field | Meaning |
|---|---|
total | Number of orders that match (search included) |
page, limit | The page returned and the page size used |
pages | Number of pages, 0 when there is no order. total_pages carries the same value |
has_more | true when another page follows |
Topup history for an ICCID
GET /
Permission: Read
The topups of one eSIM, newest first, with the same booking shape as above and type: "topup". There is no
pagination. The list is empty (status 200) when the eSIM has no topup or is not an eSIM of your agency.
curl --request GET \
--url https://api.fx-port.com/api/v1/esims/bookings/8900000540463077957/topup-history \
--header 'Authorization: Bearer fxp_test_YOUR_KEY'{
"environment": "sandbox",
"success": true,
"data": [
{
"id": "bd6ff7d7-392f-4d56-8dea-4f0f3dff0af9",
"booking_id": "FX-1793546625391",
"order_id": "20261101-106853",
"status": "confirmed",
"currency": "DZD",
"total_price": 468.84,
"agency_commission": 50.24,
"type": "topup",
"package_name": "1 GB - 7 days",
"iccid": "8900000540463077957",
"customer_email": "[email protected]",
"customer_first_name": "John",
"customer_last_name": "Smith",
"customer_phone": "+15555550123",
"provider_name": "Airalo",
"supplier_id": "airalo",
"created_at": "2026-11-01T15:23:45.424526+00:00",
"updated_at": "2026-11-01T15:23:45.424526+00:00",
"environment": "sandbox"
}
]
}The ICCID is 18 to 22 digits (groups of spaces or hyphens are read as the digits), or the PENDING-... placeholder of an
order whose eSIM the supplier has not returned yet (letters, digits and -, at most 64 characters); anything else is
refused with 400 invalid_iccid.
Check that a booking is yours
GET /
Permission: Read
Tells whether an eSIM booking belongs to your agency, before you build a link or a screen around a booking_id.
The reference is the booking_id of an eSIM order or topup (FX- followed by a number, not the internal UUID), at most 100 characters of letters,
digits and ._:=+~- (400 invalid_booking_id otherwise).
curl --request GET \
--url https://api.fx-port.com/api/v1/esims/bookings/FX-1793546602916/verify \
--header 'Authorization: Bearer fxp_test_YOUR_KEY'{
"environment": "sandbox",
"isOwner": true,
"is_owner": true,
"userAgencyId": "0b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d",
"bookingAgencyId": "0b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d"
}| Field | Meaning |
|---|---|
isOwner | true when the booking is an eSIM booking of your agency in this environment. is_owner carries the same value |
userAgencyId, bookingAgencyId | Present only when isOwner is true; both are your own agency id |
A booking of another agency and a booking that does not exist are answered the same way, {"isOwner": false}
with status 200, so the call cannot be used to discover which references exist. This answer has no success key.
Errors
| HTTP | code | Cause |
|---|---|---|
400 | invalid_search | search is longer than 100 characters or has control characters |
400 | invalid_iccid | The ICCID of the topup history is not valid |
400 | invalid_booking_id | The booking reference of verify is not valid |
401 | authentication_required, invalid_api_key | Missing or invalid API key |
422 | validation_error | page or limit is not an integer in its range (for example limit=201) |
429 | rate_limit_exceeded | Over 6,000 requests per minute for this key |