Skip to content
FX-Port/Docs
GuidesAPI referenceChangelog
Get API keys
  • Overview
  • Error object

Catalog

  • PackagesGET
  • Compatible devicesGET

Orders and top-ups

  • Create an orderPOST
  • Top-up packagesGET
  • Top upPOST

After the order

  • UsageGET
  • Usage of several eSIMsGET
  • BookingsGET
  • Top-up historyGET
  • Check ownershipGET
  • Setup dataGET
  • Installation instructionsGET

Objects

  • eSIM package
  • eSIM booking

eSIMs · Orders and top-ups

Create an eSIM order

Create one eSIM, debit your agency balance (live only) and return the eSIM with its activation data.

POST/api/v1/esims/orders

Requires an API key with Read+Write permission: a Read key is refused with read_write_permission_required.

Prices are computed on the server. quantity and every price field of the body are ignored (the response lists them in warnings), and every order creates exactly one eSIM: call the endpoint once per eSIM. The names of the traveler are optional and are not restricted to ASCII.

Send Content-Type: application/json (in any case). A form-encoded body also works, but a JSON body sent without the JSON content type is read as an empty form and answered with missing_field.

There is no idempotency key. While an order for a package is being processed, another order for the same package is refused with duplicate_request; on live so is an order for a package when the most recent confirmed order of your agency is for that same package and is less than 60 seconds old, whoever the traveler is. If a call times out, look for the booking with GET /esims/bookings?search=<traveler email> before you send the order again.

If the supplier refuses the order the response has the supplier's status, nothing is debited and a failed booking is saved. In the sandbox the supplier creates a real test eSIM with a dummy activation code, no balance is debited, and the response (including its error bodies) carries balanceDebited, transactionCreated and payoutCreated, all false, with a snake_case twin each.

curl https://api.fx-port.com/api/v1/esims/orders \
  -H "Authorization: Bearer fxp_test_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "package_id": "france-in-7days-1gb",
  "first_name": "John",
  "last_name": "Smith",
  "email": "[email protected]",
  "phone": "+15555550123",
  "description": "Order for John Smith"
}'
Response200
{
  "environment": "sandbox",
  "success": true,
  "data": {
    "order": {
      "code": "20261101-106852",
      "order_id": "20261101-106852",
      "package_id": "france-in-7days-1gb",
      "type": "sim",
      "description": "Order for John Smith",
      "esim_type": "local",
      "created_at": "2026-11-01 15:23:22",
      "package": "KPN France Data only-1 GB - 7 days",
      "data": "1 GB",
      "validity": 7,
      "price": 468.84,
      "currency": "DZD",
      "total_price": 468.84,
      "retail_price": 468.84,
      "agency_currency": "DZD",
      "supplier_currency": "USD",
      "exchange_rate": 250,
      "voice": null,
      "text": null,
      "coverage": ""
    },
    "sim": {
      "iccid": "8900000540463077957",
      "created_at": "2026-11-01 15:23:22",
      "lpa": "lpa.airalo.com",
      "imsis": null,
      "qrcode": "LPA:1$lpa.airalo.com$DUMMY-2610301358-iKFxr-44741",
      "qrcode_url": "https://sandbox.airalo.com/qr?expires=1879860202&id=473564&signature=...",
      "direct_apple_installation_url": "https://esimsetup.apple.com/esim_qrcode_provisioning?carddata=LPA:1$lpa.airalo.com$DUMMY-2610301358-iKFxr-44741",
      "apn_type": "automatic",
      "apn_value": "N/A",
      "apn": {
        "ios": {
          "apn_type": "automatic",
          "apn_value": "N/A"
        },
        "android": {
          "apn_type": "automatic",
          "apn_value": "N/A"
        }
      },
      "is_roaming": true,
      "confirmation_code": null,
      "msisdn": null,
      "sharing": {
        "access_code": 8803,
        "link": "https://esims.cloud/v8hy7-usgkq6wg"
      }
    },
    "iccid": "8900000540463077957"
  },
  "booking_id": "FX-1793546602916",
  "message": "eSIM order placed successfully",
  "balanceDebited": false,
  "balance_debited": false,
  "transactionCreated": false,
  "transaction_created": false,
  "payoutCreated": false,
  "payout_created": false
}

Request

Body

Required, JSON.

package_idstringrequired

The id of a package from the catalog (its package_id).

At most 128 characters.

emailstringrequired

The traveler's email address. FX-Port asks the supplier to send the QR code and a sharing link to it.

At most 254 characters.

phonestringrequired

The traveler's phone number: at least 3 digits. Kept on the booking: it is not sent to the supplier.

At most 32 characters.

first_namestring

The traveler's first name. Any characters are accepted. Kept on the booking only.

At most 100 characters.

last_namestring

The traveler's last name. Any characters are accepted. Kept on the booking only.

At most 100 characters.

descriptionstring

A note for your own records. It is sent to the supplier with the order and returned as order.description.

At most 500 characters.

agent_idstring (uuid)

The id of the user of your agency who places the order. Optional: it appears on the booking as agent_id. A user of another agency is refused.

user_idstring (uuid)deprecated

Legacy name, still accepted. Use agent_id instead.

Previous name of agent_id.

customer_emailstringdeprecated

Legacy name, still accepted. Use email instead.

The name the booking rows use for email. Still accepted.

customer_phonestringdeprecated

Legacy name, still accepted. Use phone instead.

The name the booking rows use for phone. Still accepted.

customer_first_namestringdeprecated

Legacy name, still accepted. Use first_name instead.

The name the booking rows use for first_name. Still accepted.

customer_last_namestringdeprecated

Legacy name, still accepted. Use last_name instead.

The name the booking rows use for last_name. Still accepted.

Response

200The order was placed. The response has status 200, not 201.

successboolean

true when the order was placed.

dataobject

The order and its eSIM. sim is null when the supplier has not returned the eSIM yet: ask for the setup instructions later.

ShowHide 3 attributes
orderobject

The order, with the amounts in your agency currency.

ShowHide 20 attributes
codestringdeprecated

Legacy name, still accepted. Use order_id instead.

The supplier's order code, for example 20261101-106852. Booking rows call it order_id. The older name of order_id: same value, use order_id.

order_idstring

The supplier's order code, for example 20261101-106852. Booking rows call it order_id. The snake_case twin of code, with the same value: use this name.

package_idstring

The package that was ordered.

typestring

Always sim.

descriptionstringnullable

The description you sent.

esim_typestring

Kind of eSIM plan, for example local.

created_atstring

When the supplier created the order: YYYY-MM-DD HH:MM:SS, UTC, without a zone.

packagestring

Name of the package: operator, data allowance and validity.

datastring

Data allowance as text, for example 1 GB.

validityinteger

Validity in days.

pricenumber

What the traveler pays, in your agency currency. Equal to total_price here (in the catalog, price is a different amount: see the pricing guide).

currencystring

Currency of the amounts: the settlement currency of your agency.

total_pricenumber

The price to charge the traveler, in your agency currency. Your commission is total_price minus the amount debited from your balance.

retail_pricenumber

The price to charge the traveler, in your agency currency. Your commission is total_price minus the amount debited from your balance. Another name of total_price, with the same value.

agency_currencystring

Same as currency.

supplier_currencystring

Currency the supplier prices the package in.

exchange_ratenumber

Rate used to convert supplier_currency to your agency currency.

voiceintegernullable

Voice minutes included, or null.

textintegernullable

SMS included, or null.

coveragestring

Coverage text taken from the installation instructions. Can be an empty string.

simobjectnullable

The eSIM that was created. Treat the activation data as a secret of the traveler.

ShowHide 14 attributes
iccidstring

The ICCID of the eSIM. Keep it: usage, topups and instructions are asked by ICCID.

created_atstringnullable

When the supplier created the eSIM: YYYY-MM-DD HH:MM:SS, UTC, without a zone.

lpastringnullable

Host of the SM-DP+ server (the LPA address).

imsisstringnullable

IMSI of the profile, when the supplier returns it.

qrcodestringnullable

The activation string the QR code encodes: LPA:1$<host>$<activation code>. Sensitive: show it only to the traveler.

qrcode_urlstringnullable

Link to the QR code image.

direct_apple_installation_urlstringnullable

Link that starts the installation on an iPhone.

apn_typestringnullable

automatic or manual.

apn_valuestringnullable

The APN to enter on a manual setup, or N/A.

apnobjectnullable

APN settings per operating system.

ShowHide 2 attributes
iosobject

Access point name (APN) settings for one operating system.

ShowHide 2 attributes
apn_typestring

automatic when the device configures the access point name by itself, manual when the traveler has to enter it.

apn_valuestringnullable

The access point name to enter on a manual setup; null or N/A when none is needed.

androidobject

Access point name (APN) settings for one operating system.

ShowHide 2 attributes
apn_typestring

automatic when the device configures the access point name by itself, manual when the traveler has to enter it.

apn_valuestringnullable

The access point name to enter on a manual setup; null or N/A when none is needed.

is_roamingbooleannullable

Whether the eSIM works through roaming.

confirmation_codestringnullable

Confirmation code to enter at installation, when the operator requires one.

msisdnstringnullable

Phone number of the eSIM, for the rare plans that include one.

sharingobjectnullable

A shareable installation page for the eSIM.

ShowHide 2 attributes
access_codenumber

Code the traveler enters on the sharing page.

linkstring

Page where the traveler can open the eSIM details and QR code.

iccidstring

The ICCID of the eSIM: the same value as sim.iccid. When the supplier has not returned the eSIM yet it is the placeholder PENDING- followed by the order code.

booking_idstring

The FX-Port booking reference, FX- followed by a number. Keep it: it is the key of the booking in every other endpoint.

messagestring

A confirmation sentence.

balanceDebitedbooleandeprecated

Legacy name, still accepted. Use balance_debited instead.

Sandbox only, always false: no balance was debited. The older name of balance_debited: same value, use balance_debited.

balance_debitedboolean

Sandbox only, always false: no balance was debited. The snake_case twin of balanceDebited, with the same value: use this name.

transactionCreatedbooleandeprecated

Legacy name, still accepted. Use transaction_created instead.

Sandbox only, always false: no balance transaction was created. The older name of transaction_created: same value, use transaction_created.

transaction_createdboolean

Sandbox only, always false: no balance transaction was created. The snake_case twin of transactionCreated, with the same value: use this name.

payoutCreatedbooleandeprecated

Legacy name, still accepted. Use payout_created instead.

Sandbox only, always false: no supplier payout was created. The older name of payout_created: same value, use payout_created.

payout_createdboolean

Sandbox only, always false: no supplier payout was created. The snake_case twin of payoutCreated, with the same value: use this name.

Errors

StatusCodeExample message
400missing_fieldpackage_id is required
400invalid_emailemail is not a valid email address
400missing_fieldphone is required
400invalid_agent_idagent_id is not a user of your agency.
402insufficient_balanceAgency balance is insufficient. Available: 300.0 DZD, Required: 418.6 DZD.
403read_write_permission_requiredThis endpoint requires an API key with read_write permission.
404not_foundPackage no-such-package-1gb not found in cache. Packages may still be loading — retry in a moment.
409duplicate_requestAn identical order is already being processed. Please wait before retrying.
429rate_limit_exceededToo many requests hit the API too quickly. Please retry your request after the time specified in the `ratelimit-reset` header.
429concurrency_limit_exceededToo many requests of this kind are already running for this API key; wait for one to finish and retry.
503service_unavailableAiralo token unavailable
503balance_lock_timeoutAnother operation on this balance is in progress. Please retry in a few seconds.

The shape of the error body depends on the endpoint. See Errors for every shape and code.

Related guides

  • Create an eSIM order
  • eSIM pricing
PreviousList eSIM compatible devicesNext List topup packages of an eSIM

© 2026 FX-Port

TermsPrivacy[email protected]