Everything an engineering team needs to plan and ship an eSIM integration: the four building blocks every eSIM API shares, how signed authentication works, the sync-vs-webhook provisioning split, what to evaluate before picking a provider, and the pitfalls that only show up in production.
Every eSIM API integration — whichever provider you choose — decomposes into the same four blocks. Scope your build against them:
The packages you can sell, with your wholesale prices. Cache it — but refresh periodically, because carrier rates change. Filter by country to build destination pages.
One authenticated POST turns a package code into a provisioned eSIM, debited from your account balance. The response carries the full install payload: QR code image, Apple one-tap universal link, and the raw LPA string.
Usage queries ("80% used — top up?"), top-up packages and orders, status, suspend/cancel, and network events. This block turns a one-shot storefront into a product with retention.
Signed requests, balance queries, webhook management, and rate limits. Boring until it isn't — most production incidents live here (see pitfalls below).
An eSIM order spends real money from your balance, so serious APIs sign every request instead of trusting a static key header. The eSIMfly scheme is HMAC-SHA256: four headers — access code, unique request ID, millisecond timestamp, and a signature over timestamp + requestId + accessCode + requestBody. Requests older than 5 minutes are rejected, which kills replay attacks.
const BASE_URL = 'https://esimfly.net';
const ACCESS_CODE = process.env.ESIMFLY_ACCESS_CODE; // esf_...
const SECRET_KEY = process.env.ESIMFLY_SECRET_KEY; // sk_...
function hmacHeaders(requestBody = '') {
const timestamp = Date.now().toString();
const requestId = uuidv4();
// signData = Timestamp + RequestID + AccessCode + RequestBody
const signData = timestamp + requestId + ACCESS_CODE + requestBody;
const signature = crypto
.createHmac('sha256', SECRET_KEY)
.update(signData)
.digest('hex')
.toUpperCase();
return {
'RT-AccessCode': ACCESS_CODE,
'RT-RequestID': requestId,
'RT-Timestamp': timestamp,
'RT-Signature': signature,
'Content-Type': 'application/json'
};
}Credentials come from Business Dashboard → Settings → API Keys. Keep the secret key server-side only — never ship it in a mobile app or browser bundle.
The minimal happy path is two calls — catalog, then order. A prototype that sells a real eSIM and displays its QR code is a one-day build:
// The minimal happy path — two calls from catalog to installed eSIM
// 1. What can I sell, and at what wholesale price?
const catalog = await fetch(
BASE_URL + '/api/v1/business/esims/packages?country=TR',
{ headers: hmacHeaders() }
).then(r => r.json());
// 2. Buy one — returns the full installation payload
const order = await fetch(BASE_URL + '/api/v1/business/esims/order', {
method: 'POST',
headers: hmacHeaders(body),
body // { packageCode, quantity: 1 }
}).then(r => r.json());
// order.data: { orderReference, iccid, qrCodeUrl,
// lpaString, appleInstallUrl, newBalance, ... }The important architectural decision is sync vs async provisioning. Most eSIMfly providers provision synchronously — the order response already contains the eSIM. A minority (KDDI Japan, for example) return pending_details and deliver the eSIM via a signed webhook a few minutes later. Design your order flow as "show the eSIM if it's in the response, otherwise show a 'preparing' state and finish from the webhook" and both cases are covered.
For the full working build — catalog UI, ordering, QR delivery — follow the Node.js storefront tutorial (~30 min) and then top-ups, usage tracking & webhooks.
Questions worth asking of any eSIM API vendor before you commit volume — with eSIMfly's answers for transparency:
Not just how many countries, but which local networks per country and whether plans multi-network switch. eSIMfly: 200 countries, 450+ networks.
Every async carrier adds webhook complexity to your flow. eSIMfly: most providers synchronous; async ones (e.g. KDDI) delivered via signed webhook.
You want QR code + Apple universal link + raw LPA string in one response — anything less degrades your install UX. eSIMfly: all three.
Usage query, top-up catalog per ICCID, suspend/cancel, network events. Without usage data you can't build top-up revenue.
Signed requests (HMAC) beat static keys for an API that spends money. eSIMfly: HMAC-SHA256, 1,000 req/hour, 5-minute timestamp window.
If the docs don't include copy-paste examples in your language, integration time doubles. eSIMfly: Node.js, Python and PHP examples plus an interactive playground.
Signed timestamps older than 5 minutes are rejected. A server with a drifting clock produces intermittent 401s that look like random failures. Run NTP; alert on auth-failure rate.
Users delete emails and switch phones. Persist orderReference, ICCID, QR and LPA string on your side so you can re-deliver the eSIM later — re-ordering costs money, re-displaying is free.
Orders debit your prepaid balance and fail cleanly when it's insufficient — which is still a failed customer checkout. Watch the newBalance field on every order and alert well before empty.
Wholesale prices move with carrier rates. A stale cached catalog means selling at yesterday's cost. Cache, but refresh on a schedule and before large campaigns.
Usage-polling every eSIM every minute burns your 1,000 req/hour budget fast at scale. Poll on user-open, schedule background checks sparsely, and let webhooks carry async events.
Four building blocks: a package catalog (what you can sell, with wholesale prices), an ordering endpoint (turns a package code into a provisioned eSIM), delivery UX (QR code, one-tap install links, and the raw LPA string), and lifecycle management (usage queries, top-ups, suspend/cancel, webhooks). A minimal storefront needs only the first three and can be built in a day; lifecycle features make it a real product.
A working prototype — authenticate, pull the catalog, create an order, show the QR code — is typically a one-day build (the eSIMfly Node.js tutorial does it in ~30 minutes without an SDK). Production hardening (webhooks, balance monitoring, re-delivery of stored eSIMs, error handling) usually adds a few days.
Serious eSIM APIs use signed requests rather than a bare API key. eSIMfly uses HMAC-SHA256: each request carries an access code, a unique request ID, a timestamp, and a signature computed over timestamp + request ID + access code + body with your secret key. Requests older than 5 minutes are rejected, which blocks replay attacks.
Most eSIMfly providers provision synchronously — the order response already contains the QR code, so no webhook is needed for the core flow. Webhooks matter for the minority of carriers that provision asynchronously (KDDI Japan takes a few minutes) and for avoiding usage-polling loops at scale. Good rule: launch with the synchronous flow, add webhooks before you scale.
Coverage (countries AND which local networks), wholesale pricing model and top-up support, what share of orders provision synchronously, delivery payload completeness (QR + Apple universal link + raw LPA), auth security, rate limits, usage/lifecycle endpoints, and whether documentation includes runnable examples. Test the sandbox with your real use case before committing volume.
Create an eSIMfly business account, then generate API credentials (access code + secret key) from Business Dashboard → Settings → API Keys. Coverage spans 200 countries across 450+ networks, with rate limits of 1,000 requests/hour. Wholesale tiers depend on volume — contact sales for rates.
Full endpoint reference, Python and PHP examples, and an interactive playground in the documentation — or start from the API overview and get your keys.