Skip to content
FX-Port/Docs
GuidesAPI referenceChangelog
Get API keys
  • Introduction
  • Quickstart
  • Security
  • Authentication
  • Environments and Postman
  • Sandbox
  • Conventions and naming
  • Legacy names and twins
  • Errors
  • Rate limits and fair use
  • Streaming search results

Concepts

  • Overview
  • Pricing
  • Supplier continuity

Catalog and orders

  • Package catalog
  • Create an order
  • Top up

After the order

  • Usage
  • Bookings
  • Setup instructions
  • Use these docs with AI

eSIMs · Concepts

eSIMs API overview

Browse the package catalog, place orders, top up existing eSIMs and track usage across 190+ countries.

Sell travel data eSIMs across 190+ countries from a single API surface. FX-Port sources packages from its eSIM supplier network and prices them for your agency in your own currency: you never call a supplier directly. A package is a data plan for one destination (or one region); an order creates one eSIM from it; a topup adds a package to an eSIM that already exists.

For a summary of what the API covers, who it is for and how to get access, see the eSIM API for travel companies.

Coverage and pricing grow automatically. FX-Port continuously onboards more eSIM suppliers, and each supplier independently expands its own network of mobile operators over time — both add new countries, package sizes, and better rates/connectivity to the catalog. Your integration picks up new packages with no code changes — always read package_id from the catalog response rather than hard-coding it.

How an integration works

  1. 1

    Read the catalog

    GET /esims/packages?country=france returns the packages for a destination with prices in your currency. Keep the package_id of the package the traveler chooses.

  2. 2

    Create the order

    POST /esims/orders with that package_id and the traveler's email and phone creates one eSIM. Keep booking_id and the ICCID (data.iccid) from the response.

  3. 3

    Give the traveler the eSIM

    Show sim.qrcode_url or the qrcode text, or let the traveler open the sharing.link. Setup instructions returns the same data again later, with installation steps.

  4. 4

    Follow the usage

    GET /esims/usage/{iccid} returns the data left and the expiry.

  5. 5

    Top up when the traveler runs out

    GET /esims/topup-packages/{iccid} lists what can be added; POST /esims/topups adds it.

eSIM concepts

Read these before integrating.

eSIM pricingWhat each price field means and how to compute what is debited from your balance.Supplier continuityWhy a topup can occasionally be unavailable, and how FX-Port protects your balance.

Endpoints

MethodPathPermissionRate limit groupDescription
GET/api/v1/esims/packagesReadDefaultList the package catalog, filtered by country and type
GET/api/v1/esims/compatible-devicesReadDefaultList devices known to support eSIM
POST/api/v1/esims/ordersRead+WriteBookingCreate a new eSIM order
GET/api/v1/esims/topup-packages/{iccid}ReadDefaultList the packages that can top up one eSIM
POST/api/v1/esims/topupsRead+WriteBookingTop up an existing eSIM
GET/api/v1/esims/usage/{iccid}ReadDefaultUsage of one eSIM
GET/api/v1/esims/usage/bulkReadDefaultUsage of several eSIMs
GET/api/v1/esims/bookingsReadDefaultList the agency's eSIM orders (topups are not listed here)
GET/api/v1/esims/bookings/{iccid}/topup-historyReadDefaultTopups of one eSIM
GET/api/v1/esims/bookings/{booking_id}/verifyReadDefaultCheck that a booking is yours
GET/api/v1/esims/bookings/{booking_id}/setup-instructionsReadDefaultSetup data (QR code, APN, steps) of an order
GET/api/v1/esims/instructions/{iccid}ReadDefaultInstallation instructions for an ICCID

Only order creation and topup creation change anything: on live they debit your agency balance and provision the eSIM. Every other endpoint only reads. The full parameters, schemas and examples of every endpoint are in the API reference.

GET /esims/bookings/{booking_id}/setup-url is deprecated and must not be used: it is replaced by setup-instructions, which returns the same data as structured JSON. It no longer returns any supplier data: it answers with the install links of the order only (see the setup link).

Rate limits

Every API key may send 1,200 requests per minute to the booking group (creating an order and creating a topup) and 6,000 requests per minute to the default group (every other eSIM endpoint: the catalog, devices, topup packages, usage, bookings, instructions). The counters are per key and per minute. A request over the limit is answered 429 with the code rate_limit_exceeded: see Rate limits and fair use. Too many orders or topups of one key or agency running at the same time can be answered 429 concurrency_limit_exceeded: retry after the seconds in Retry-After. Separately, the supplier limits how often usage can be read: see eSIM usage.

Sandbox behaviour

A sandbox key (fxp_test_...) works against the supplier's test system, so every endpoint above can be tried end to end:

BehaviourDetail
An order creates a test eSIMThe supplier's sandbox returns a real test eSIM with a dummy activation code (LPA:1$lpa.airalo.com$DUMMY-...). It cannot be installed on a phone.
Nothing is debitedOrders and topups carry balanceDebited, transactionCreated and payoutCreated (twins: balance_debited, transaction_created, payout_created), all false. They are also on the error bodies of both endpoints.
Topup balanceA topup answers balance previous: 0.0 and current: 0.0: the sandbox has no balance.
UsageA new eSIM shows its full allowance and ACTIVE; usage does not change after a topup.
BookingsSandbox orders and topups appear only to sandbox keys: orders in bookings, topups in the topup history, and both in the account history and the booking detail.
Live-only checksThe balance check (402 insufficient_balance), the 60-second duplicate check and the balance lock (503 balance_lock_timeout) only run on live.

Traveler contact details

email and phone are required on order and topup creation — not optional. What happens to them:

  • email: on an order, FX-Port asks the supplier to email the QR code and a sharing link to this address as soon as the eSIM is created, so the traveler can install it without you relaying the QR code. On a topup the email is kept on the booking only; it is not sent to the supplier.
  • phone, first_name, last_name: kept on the booking and returned by the booking endpoints. They are not sent to the supplier.

Only pass the traveler's own contact details — never billing, pricing, or account information. first_name and last_name are optional and are not restricted to ASCII: accents and non-Latin scripts are accepted as they are (only the length is checked).

Conventions of the eSIM endpoints

  • Bodies have success. Every answer carries success (a call that fails also carries the usual error body, see below), except the answer of verify.
  • Creations answer 200, not 201, and have no Location header.
  • JSON in, JSON out. Send Content-Type: application/json on orders and topups (the media type is read in any case). A form-encoded body is also read, but a JSON body without the JSON content type is read as an empty form and refused with missing_field.
  • Wrapped payloads. Topup packages, usage and instructions wrap their payload one level deeper (data.data); each entry of bulk usage does it again (data.data.data). The reference shows each shape.
  • Units and times. Data is in megabytes. Times that come from the supplier (created_at of an order or eSIM, expired_at of usage) are YYYY-MM-DD HH:MM:SS in UTC without a zone; times stored by FX-Port (bookings) are ISO 8601 with a zone.
  • No trailing slash. /api/v1/esims/packages/ is redirected with an empty body: call the path without the slash.
  • Amounts are in the currency of your agency (currency), never in the supplier's.
  • Spellings that are read. An ICCID may be written in groups of spaces or hyphens (8944 4654 0000 0123 456); locale takes any spelling of a locale (zh-Hans, pt_BR, fr_FR.UTF-8, an Accept-Language value) and country a country name (United States); an empty page, limit, force or all (?page=) means not sent. A value that is really wrong keeps its stable code (invalid_iccid, invalid_locale, invalid_country ...).
  • Names. Several answers keep a legacy camelCase or short key next to its snake_case twin (code and order_id, id and package_id, balanceDebited and balance_debited, pagination.pages and total_pages ...). Both carry the same value; use the snake_case one in new code. ?naming=snake returns every key in snake_case. See Conventions and naming.

Error responses

Every error has a stable code in errors[0].code: branch on it, not on the message. See Errors for the shape and every shared code.

HTTPTypical codeCause
400missing_field, invalid_package_id, invalid_iccid, invalid_email, invalid_phone, invalid_type, invalid_jsonA required field is missing or has the wrong format
401authentication_required, invalid_api_keyMissing or invalid API key
402insufficient_balanceAgency balance lower than the amount to debit (live)
403read_write_permission_required, agency_not_activeThe key has read permission only, or the agency is not active
404not_found, iccid_not_found, booking_not_foundThe package, the eSIM or the booking does not exist for your agency
409duplicate_requestThe same order or topup is already being processed or was just confirmed
422validation_errorA query parameter has the wrong type or range (for example limit=500)
429rate_limit_exceeded, concurrency_limit_exceededToo many requests per minute, or too many orders or topups of your key or agency being processed at the same time. Retry after the seconds in Retry-After
500internal_error, booking_record_failed, balance_debit_failed, supplier_response_invalidAn error on our side; the last three come after the supplier created the eSIM
503service_unavailable, balance_lock_timeout, duplicate_check_unavailable, service_busyThe supplier connection, a lock or the service is temporarily unavailable; retry in a few seconds

When the supplier refuses an order or a topup, the response is a supplier_error with the supplier's own HTTP status (for example 422 or 429), nothing is debited, and a failed booking is saved for support. Usage, topup packages, topups and instructions answer 404 iccid_not_found for an ICCID that is not an eSIM of your agency; setup instructions answer 404 booking_not_found for a booking that is not yours.

Loading answers. Right after a restart the catalog and the device list may not be loaded yet: GET /esims/packages and GET /esims/compatible-devices then answer 202 with "success": false and an empty data, and the device list can answer 503 while its fetcher starts. This is not an error of your request: wait a few seconds and send it again.

Questions?

Email the FX-Port developer team at [email protected] for integration help, feature requests, or to report an API error.

PreviousCancel a hotel bookingNext eSIM pricing

On this page

  • How an integration works
  • eSIM concepts
  • Endpoints
  • Rate limits
  • Sandbox behaviour
  • Traveler contact details
  • Conventions of the eSIM endpoints
  • Error responses
  • Questions?

© 2026 FX-Port

TermsPrivacy[email protected]