eSIM
Order an eSIM
Orders an eSIM and creates a new profile in a single operation.
Returns the eSIM details including the activation code (LPA string) for device installation, along with the newly created profile reference for future API calls.
To port an existing number onto the new eSIM, include the optional portIn block — an eSIM that waits for its port then stays pre-active (installable, but no service) until the port completes. See the Porting tag for the full workflow.
/esimsAuthorization
Authorization: Bearer {token} — an OAuth2 access token from the client-credentials flow. How authentication works
Headers
X-Idempotency-KeystringOptional idempotency key for mutating requests (POST, PATCH). If provided, duplicate requests with the same key within 48 hours will return the cached original response without duplicating side effects.
Behavior:
- Same key + same request body → returns cached response (prevents duplicate operations)
- Same key + different request body → returns 422 error
- Same key + in-flight request → returns 409 error with Retry-After header
- Keys expire after 48 hours
Request Body Matching: Request bodies are compared by their JSON content. Object key order, including in nested objects, and whitespace do not affect matching. This means:
{"a":1,"b":2}and{"b":2,"a":1}are treated as identical ✓- Whitespace differences are ignored ✓
- URL parameters and headers are NOT included in request body matching
Best Practices:
- Use UUIDs or client-generated unique strings
- Store keys on your side to support retries
- Don't reuse keys across different operations
Request body
application/json
externalProfileIdstringOptional client-provided external ID to associate with this eSIM. Must be unique per client.
esimVariantstringThe eSIM variant of the new eSIM (e.g. 'travel'), one of those GET /catalog/esim-variants lists. Defaults to the client's default eSIM variant.
portInobjectOptional port-in of an existing number onto the ordered eSIM. When present, the response contains a portIn object, and an eSIM that waits for its port stays pre-active until the port completes.
Show propertiesHide properties
msisdnstringrequiredThe number to port, in international format (E.164 without a leading +) — i.e. the country code, not the national 0 trunk prefix. Belgium: 324 + 8 digits, e.g. 32470123456; Netherlands: 316 + 8 digits, e.g. 31612345678.
detailsone of Belgium | NetherlandsrequiredDonor details of the number to port. Their shape depends on the country of the selected eSIM's variant: the Belgian or the Dutch shape. Unknown fields are rejected.
Show propertiesHide properties
BelgiumobjectDonor details of a Belgian number. A prepaid contract takes donorIccid and/or donorSimNumber; a postpaid contract any of donorIccid, donorSimNumber and donorAccountNumber; a business contract donorAccountNumber only.
Show propertiesHide properties
donorContractTypestringrequiredContract type of the number at the donor operator
prepaidpostpaidbusinessdonorIccidstringICCID of the donor SIM card, with a valid check digit. The preferred proof of a donor SIM: most donor operators accept it.
donorSimNumberstringThe number printed on the donor SIM card. Send it only when the donor SIM's ICCID is not available; donorIccid is accepted by more donor operators.
donorAccountNumberstringAccount/customer number at the donor operator
NetherlandsobjectDonor details of a Dutch number. A postpaid contract requires donorAccountNumber.
Show propertiesHide properties
donorContractTypestringrequiredContract type of the number at the donor operator
prepaidpostpaiddonorAccountNumberstringCustomer number at the donor operator
communicationLanguageCodestringExperimentalThe language to message the customer in, as a two-character lowercase ISO 639-1 code, stored on the created profile. Set it whenever you know the customer's language, en included: a profile without one is messaged in the client's default language, which can change. Change it later with PATCH /profiles/{profileReference}. Independent of numberRegistration.languageCode, which is registry data.
packagesarray of OrderPackageRequestExperimentalPackages ordered with the eSIM. Each is created pending as an order of the package itself would be, so a plan that cannot be ordered on this eSIM fails the whole order, and is loaded once the eSIM has network service, for example after its installation, its activation request or a port-in. Its validity counts from its activation; until then it has no expiresAt.
Show propertiesHide properties
planReferencestringrequiredPlan reference identifier (14-character opaque token)
externalTransactionIdstringOptional client-provided external transaction ID to associate with this package.
numberRegistrationobjectOptional subscriber facts to register the number in its country's number registry, required in markets whose regulator mandates it. Applies to the preloaded number, or to the ported number when portIn is present. A registration that cannot be captured fails the order: a country whose registry is not supported is a 422; a country that does not match the number, or subscriber details the registry cannot accept, are a 400 with field errors under numberRegistration.
Responses
201Profile created and eSIM successfully orderedapplication/jsonShow response bodyHide response body
dataobjectoptionalShow propertiesHide properties
profileReferencestringThe eSIM's profile reference for API access (16-digit numeric)
externalProfileIdstring | nullThe client's external profile ID if provided
esimReferencestringeSIM reference identifier (18-digit opaque token)
iccidstringThe SIM's ICCID (needed for device installation)
activationCodestring | nullLPA activation code for device installation; null for a physical SIM
pin1stringPIN1 for the eSIM profile, as personalised by the manufacturer. Required to unlock the profile when SIM PIN is enabled on the device.
puk1stringPUK1 for the eSIM profile. Resets PIN1 after it has been entered incorrectly three times.
pin2stringPIN2 for the eSIM profile, guarding SIM service settings.
puk2stringPUK2 for the eSIM profile. Resets PIN2.
esimVariantstring | nullThe eSIM's variant (e.g. 'travel'), or null if it has none.
statusstringProfile state on the device, as reported by the SM-DP+. A physical SIM has no download lifecycle and stays released; its service state is lifecycleStatus.
released: Ready for use; an eSIM profile in this state is available for download (QR code ready)downloaded: Profile has been downloaded to the deviceinstalled: Profile is installed on the eSIM chipenabled: Profile is active on the devicedisabled: Profile is installed but disabled on the devicedeleted: Profile has been removed from the devicefaulted: Profile failed to download or install on the device
releaseddownloadedinstalledenableddisableddeletedfaultedlifecycleStatusstringNetwork service state of the eSIM.
preactive: not live on the network yetactive: live on the networksuspended: temporarily without network service; can be reactivatedterminated: permanently without network servicefaulted,stale: network service could not be set up; contact support
preactiveactivesuspendedterminatedfaultedstalemsisdnsarray of objectPhone numbers (MSISDNs) attached to the eSIM. Only available for eSIM variants that include a phone number; empty for variants without one, and until a number is assigned.
Show propertiesHide properties
msisdnstringPhone number in E.164 format without the leading +
primarybooleanWhether this is the eSIM's primary phone number
createdAtstring · date-timeportInobjectoptionalPresent when the order included a portIn block.
Show propertiesHide properties
portInRequestReferencestringPublic opaque port-in request reference (8-char uppercase base36)
statusstringrequested: Accepted by Firsty; provider submission in progressapproved: The donor accepted the port;scheduledAtis when the number moves, once known, which can be days ahead. The port finishes atcompletedcancelling: Cancellation requested, awaiting provider confirmationcompleted: The donor released the number and it is assigned to this SIMrejected: Donor rejected the request (seereason); submit a corrected request. A rejection the customer can still correct may keep the requestrequesteduntil it is finalfailed: Port failed (seereason); submit a corrected requestcancelled: Cancellation confirmed; the eSIM stays pre-active for a corrected request or abandon
requestedapprovedcancellingcompletedrejectedfailedcancelledreasonobjectoptionalWhy the port-in was rejected or failed. Present when status is rejected or failed, and on a requested port-in the donor has rejected for a reason the customer can still correct
Show propertiesHide properties
codestringNormalized cause of the rejection or failure, the same for every porting provider. provider_failure covers every cause without a more specific code. The list of values is open-ended; new values may be added
msisdn_sim_mismatchmsisdn_account_mismatchdonor_contract_type_mismatchnumber_not_activenumber_not_portablenumber_porting_in_progressporting_window_unavailableprovider_failuremessagestring | nullHuman-readable detail of the cause for support; free-form, not intended to be parsed. Null when there is none
numberRegistrationobjectoptionalThe registration of the number the eSIM is on or porting to, in its country's number registry. The field is absent when that number has no registration.
Show propertiesHide properties
numberRegistrationReferencestringregistrystringThe registry the number was registered with.
msisdnstringThe registered number, in international format (E.164 without a leading +).
statusstringprocessing while the registration is on its way to the registry, completed once the registry accepted it, error when it was rejected (see reason).
processingcompletederrorreasonobject | nullRejection detail; null unless the registration ended in error
Show propertiesHide properties
codestringThe registry's own rejection code, or one of ours when the registration never reached it
messagestring | nullHuman-readable detail when available
packagesarray of objectoptionalExperimentalPresent when the order included packages, in the same order. Each package is pending until the eSIM has network service.
Show propertiesHide properties
packageReferencestringPackage reference identifier (23-character opaque token)
planReferencestringexternalTransactionIdstring | null404No available eSIM foundapplication/problem+jsonShow response bodyHide response body
typestring · uriURI reference to error documentation
titlestringShort, consistent error summary
statusintegerHTTP status code
detailstringHuman-readable explanation specific to this occurrence
codestringExtensible enum. Machine-readable error slug. This is the field clients should branch on. The URI in type documents the code. Handle an unknown code by its HTTP status.
bad_requestvalidation_failedunauthorizedpayment_requiredfeature_not_enabledforbiddenbalance_not_foundesim_not_foundnot_foundnumber_registration_not_foundport_in_not_foundprofile_not_foundscheduled_action_not_foundsubscription_not_foundsubscription_plan_not_foundwebhook_endpoint_not_foundbalance_not_availablebalance_update_pendingconcurrent_modificationconflictesim_change_pendingesim_not_activeesim_not_provisionedesim_suspendedesim_swap_cooldownesim_swap_pendingesim_terminatedinvalid_state_transitionlimit_reachedno_esim_availablenumber_registration_pendingport_in_pendingservices_change_pendingservices_not_availablebalance_not_supportedbalance_operation_not_supportedbalance_update_refusedclient_transaction_id_reusedesim_variant_not_allowedesim_variant_not_swappableidempotency_key_reusedinsufficient_balancenumber_not_availablenumber_registration_not_supportedport_in_cancel_refusedporting_not_supportedservices_change_refusedservices_not_changeableservices_not_supportedsim_refused_by_networkunprocessable_entitylockedrate_limit_exceededinternal_errorbad_gatewayservice_unavailable409A profile with this externalProfileId already existsapplication/problem+jsonShow response bodyHide response body
typestring · uriURI reference to error documentation
titlestringShort, consistent error summary
statusintegerHTTP status code
detailstringHuman-readable explanation specific to this occurrence
codestringExtensible enum. Machine-readable error slug. This is the field clients should branch on. The URI in type documents the code. Handle an unknown code by its HTTP status.
bad_requestvalidation_failedunauthorizedpayment_requiredfeature_not_enabledforbiddenbalance_not_foundesim_not_foundnot_foundnumber_registration_not_foundport_in_not_foundprofile_not_foundscheduled_action_not_foundsubscription_not_foundsubscription_plan_not_foundwebhook_endpoint_not_foundbalance_not_availablebalance_update_pendingconcurrent_modificationconflictesim_change_pendingesim_not_activeesim_not_provisionedesim_suspendedesim_swap_cooldownesim_swap_pendingesim_terminatedinvalid_state_transitionlimit_reachedno_esim_availablenumber_registration_pendingport_in_pendingservices_change_pendingservices_not_availablebalance_not_supportedbalance_operation_not_supportedbalance_update_refusedclient_transaction_id_reusedesim_variant_not_allowedesim_variant_not_swappableidempotency_key_reusedinsufficient_balancenumber_not_availablenumber_registration_not_supportedport_in_cancel_refusedporting_not_supportedservices_change_refusedservices_not_changeableservices_not_supportedsim_refused_by_networkunprocessable_entitylockedrate_limit_exceededinternal_errorbad_gatewayservice_unavailable422The request was well-formed but cannot be applied as given, for example an idempotency key reused with a different request body, or a physical SIM its network refuses for good (`code` `sim_refused_by_network`; the SIM stays assigned to the profile). The `detail` field identifies the cause.application/problem+jsonShow response bodyHide response body
typestring · uriURI reference to error documentation
titlestringShort, consistent error summary
statusintegerHTTP status code
detailstringHuman-readable explanation specific to this occurrence
codestringExtensible enum. Machine-readable error slug. This is the field clients should branch on. The URI in type documents the code. Handle an unknown code by its HTTP status.
bad_requestvalidation_failedunauthorizedpayment_requiredfeature_not_enabledforbiddenbalance_not_foundesim_not_foundnot_foundnumber_registration_not_foundport_in_not_foundprofile_not_foundscheduled_action_not_foundsubscription_not_foundsubscription_plan_not_foundwebhook_endpoint_not_foundbalance_not_availablebalance_update_pendingconcurrent_modificationconflictesim_change_pendingesim_not_activeesim_not_provisionedesim_suspendedesim_swap_cooldownesim_swap_pendingesim_terminatedinvalid_state_transitionlimit_reachedno_esim_availablenumber_registration_pendingport_in_pendingservices_change_pendingservices_not_availablebalance_not_supportedbalance_operation_not_supportedbalance_update_refusedclient_transaction_id_reusedesim_variant_not_allowedesim_variant_not_swappableidempotency_key_reusedinsufficient_balancenumber_not_availablenumber_registration_not_supportedport_in_cancel_refusedporting_not_supportedservices_change_refusedservices_not_changeableservices_not_supportedsim_refused_by_networkunprocessable_entitylockedrate_limit_exceededinternal_errorbad_gatewayservice_unavailable423A request with this idempotency key is still being processedapplication/problem+jsonShow response bodyHide response body
typestring · uriURI reference to error documentation
titlestringShort, consistent error summary
statusintegerHTTP status code
detailstringHuman-readable explanation specific to this occurrence
codestringExtensible enum. Machine-readable error slug. This is the field clients should branch on. The URI in type documents the code. Handle an unknown code by its HTTP status.
bad_requestvalidation_failedunauthorizedpayment_requiredfeature_not_enabledforbiddenbalance_not_foundesim_not_foundnot_foundnumber_registration_not_foundport_in_not_foundprofile_not_foundscheduled_action_not_foundsubscription_not_foundsubscription_plan_not_foundwebhook_endpoint_not_foundbalance_not_availablebalance_update_pendingconcurrent_modificationconflictesim_change_pendingesim_not_activeesim_not_provisionedesim_suspendedesim_swap_cooldownesim_swap_pendingesim_terminatedinvalid_state_transitionlimit_reachedno_esim_availablenumber_registration_pendingport_in_pendingservices_change_pendingservices_not_availablebalance_not_supportedbalance_operation_not_supportedbalance_update_refusedclient_transaction_id_reusedesim_variant_not_allowedesim_variant_not_swappableidempotency_key_reusedinsufficient_balancenumber_not_availablenumber_registration_not_supportedport_in_cancel_refusedporting_not_supportedservices_change_refusedservices_not_changeableservices_not_supportedsim_refused_by_networkunprocessable_entitylockedrate_limit_exceededinternal_errorbad_gatewayservice_unavailable400Bad request - invalid parameters401Unauthorized - missing or invalid API key403Forbidden - client does not have access to this resource429Rate limit exceeded. A `429` can also arrive without these headers or this body; handle it by its status code.500Internal server error