Skip to main content
Every other tutorial here ends when money moves. This one does not: an eSIM is only sold once a person has installed a profile on a handset, which happens after the debit, on someone else’s schedule, on a device you cannot see. So persist your intent before you call. Store your externalReference, the plan slug, the paying account, the customer it is for, and the state you last saw — and treat everything after the order as something you resume rather than something you complete in one request.

1. Mirror the catalog

Two reads, top down, both paged and read-only.
Do not read the catalog on the customer’s keystroke. Mirror it on a schedule — hourly is ample — and serve your own copy, storing the slug against your product record. Two fields decide what you can offer later, so keep them: Re-read the plan before you quote if your copy is older than an hour. A plan withdrawn from the network between your mirror and your order is 404 esim_package_unavailable, and the customer is already at a confirmation screen by then.

2. Quote, and show the figure you will charge

The catalog is USD. Your account may not be. Quote unless the paying account is USD, and put payable on the confirmation screen — never the USD price.
A quote is bound to one plan, one quantity, and one account, and backs exactly one order. It lasts about two minutes, so quote after the customer has chosen and immediately before you charge — not while they are still browsing. If it lapses, quote again and show the new figure rather than charging it silently. The quote window covers the failure modes; they all answer 409 esim_fx_quote_required and they all end the same way.

3. Create the order

The money leaves now; the eSIM arrives later. Expect provisioning with an empty profileIds and design for it — a “preparing” state the customer can walk away from, not a blocking spinner.
externalReference is the idempotency key. Retrying with the same one returns the original order whatever its status, including a failed one. A genuine second attempt after a failure needs a fresh reference and a fresh quote.
Pass customerId when you know who the eSIM is for. It does not change who is billed — your account is debited either way — but it is what lets you list a customer’s eSIMs later, and what a support agent will search on.

4. Wait for fulfilment

Take the webhook, and keep polling as the recovery path rather than the design:
  • esim.order.completed carries the order, profileIds included. That is your signal to fetch install details.
  • esim.order.failed means the network refused. The money is on its way back; you have nothing to claim.
  • Polling the order every few seconds while status is provisioning is the fallback when a webhook is missed.
Give up on the request, never on the order. An order still provisioning after your poll budget is not stuck: Sakawave asks the network on a widening backoff for roughly two hours, then fails and refunds by itself.

When you bought more than one

quantity above 1 produces one order and up to that many eSIMs, and the network can fill part of an order. Read profileIds as the truth about how many you actually got:

5. Hand it to the handset

One call, three forms of the same credential.
Offer the universal link first, the QR second, the manual details last — and remember a phone cannot scan a QR shown on its own screen. Installation and device support is the page to read before you design this screen; it is where integrations lose customers. Ask before the eSIM exists and you get 409 esim_profile_not_ready. That is a timing answer, not a failure: the profile is still pending.
The activation code installs a working SIM. Treat it as a credential — show it to the person the eSIM is for, keep it out of logs and analytics, and never put it in an email you also send elsewhere.

6. Run the eSIM for the rest of its life

Cancel and revoke are not two words for the same thing. Cancel returns the money because nobody used the eSIM; revoke returns nothing because the network has already been paid for the data. Revoking asks for {"confirm": true} for exactly that reason.

Top up instead of selling a second eSIM

A top-up extends the profile already on the phone — same ICCID, nothing to reinstall. It must cover the same destination, and the plan must itself support being a top-up:
A plan from another destination is 409 esim_topup_region_mismatch; a plan that cannot extend anything is 409 esim_package_not_topupable.
Sell the top-up on esim.usage.low — under about 100 MB left — rather than waiting for the allowance to run out. A depleted eSIM is refused with 409 esim_profile_not_topupable, so the offer has to reach the customer while data is still flowing.

Reaching the handset

If the plan reports supportsPlatformSms, you can push one 160-character message to the eSIM — ten per hour per eSIM, and 429 esim_message_rate_limited past that. Accepted means the provider took it, not that anyone read it: an eSIM that was never installed swallows it silently. The message log is what support reads back. It is a lifeline for a traveller with no other connectivity, not a notification channel. Use your own push and email for everything else.

7. Reconcile

Orders carry both figures, and they answer different questions:
paid is what left the account, in the account’s currency — the only figure a bank statement will agree with. price is the USD list price, for reconciling against the catalog. Refunds have already happened; they are entries to record, not exceptions to chase. Then reconcile the transaction alongside everything else.

What goes wrong, and what to do

Next