eSimfly Logo
DEVELOPER GUIDE · ARCHITECTURE TO PRODUCTION

eSIM API Integration Guide

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.

1. The four building blocks

Every eSIM API integration — whichever provider you choose — decomposes into the same four blocks. Scope your build against them:

Catalog

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.

Ordering & delivery

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.

Lifecycle

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.

Account & security

Signed requests, balance queries, webhook management, and rate limits. Boring until it isn't — most production incidents live here (see pitfalls below).

2. Authentication: signed requests, not bare keys

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.

// With the official SDK (npm install @esimfly/sdk) this entire block is one line:
//   const esimfly = new ESIMfly({ accessCode, secretKey });
// Shown in full so you know exactly what gets signed on every request.

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.

3. The integration path

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
import { ESIMfly } from '@esimfly/sdk';
const esimfly = new ESIMfly({
  accessCode: process.env.ESIMFLY_ACCESS_CODE,
  secretKey: process.env.ESIMFLY_SECRET_KEY,
});

// 1. What can I sell, and at what wholesale price?
const { packages } = await esimfly.packages.list({ search: 'Turkey', type: 'local' });

// 2. Buy one - returns the full installation payload
const order = await esimfly.orders.create({
  packageCode: packages[0].package_code,
  idempotencyKey: cart.id, // a retry can never charge twice
});
// order: { orderReference, newBalance, esims: [{ iccid, lpaString, qrCodeUrl,
//   directAppleInstallUrl, directAndroidInstallUrl, expired_time, ... }] }

The important architectural decision is sync vs async provisioning. Most eSIMfly providers provision synchronously — the order response already contains the eSIM. A few packages return pending_details and are ready a few minutes later — the SDK's orders.waitForEsim() polls until then. Design your order flow as "show the eSIM if it's in the response, otherwise show a 'preparing' state and finish when it's ready" and both cases are covered. What does deserve a webhook is everything after the sale: install, activation and low-data events arrive in real time once you subscribe.

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.

4. Choosing a provider: the evaluation checklist

Questions worth asking of any eSIM API vendor before you commit volume — with eSIMfly's answers for transparency:

Coverage — countries and networks

Not just how many countries, but which local networks per country and whether plans multi-network switch. eSIMfly: 200 countries, 450+ networks.

Share of synchronous provisioning

Every async carrier adds complexity to your checkout. eSIMfly: most packages synchronous; the few async ones are polled with waitForEsim(), and real-time webhooks cover install, status and low-data events after the sale.

Delivery payload completeness

You want QR code + Apple universal link + raw LPA string in one response — anything less degrades your install UX. eSIMfly: all three.

Lifecycle endpoints

Usage query, top-up catalog per ICCID, suspend/cancel, network events. Without usage data you can't build top-up revenue.

Auth model & rate limits

Signed requests (HMAC) beat static keys for an API that spends money. eSIMfly: HMAC-SHA256 (handled by the SDK), limits per API key — typically 100 req/minute and 1,000 req/hour — and a 5-minute timestamp window.

Docs with runnable code

If the docs don't include copy-paste examples in your language, integration time doubles. eSIMfly: an official Node.js SDK (@esimfly/sdk), Python and PHP examples, copy-paste prompts for AI coding assistants, plus an interactive playground.

5. Production pitfalls (learn them here, not in prod)

Clock skew silently breaks auth

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.

Losing the install payload

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.

Balance runs dry mid-flow

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.

Treating the catalog as static

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.

Polling where a webhook belongs

Usage-polling every eSIM every minute burns your per-key budget (typically 1,000 req/hour) fast at scale. Query usage when the user opens their eSIM, and subscribe to esim.usage.threshold and esim.status.changed so the API tells you when something changes.

eSIM API integration FAQ

What does an eSIM API integration involve?

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.

How long does it take to integrate an eSIM API?

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 with the official @esimfly/sdk). Production hardening (webhooks, balance monitoring, re-delivery of stored eSIMs, error handling) usually adds a few days.

How does eSIM API authentication usually work?

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.

Do I need webhooks, or can I just poll?

The purchase itself does not need webhooks: the order response already contains the QR code, and the few packages that provision asynchronously are simply polled until ready. Webhooks matter after the sale — eSIMfly pushes esim.installed, esim.status.changed and esim.usage.threshold (500/200/100/50 MB left) to your server, so you never poll usage across your fleet. Good rule: launch with the synchronous flow, subscribe to webhooks before you scale.

What should I compare when choosing an eSIM API provider?

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.

How do I get access to the eSIMfly API?

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 set per API key (typically 100 requests/minute, 1,000/hour). Wholesale tiers depend on volume — contact sales for rates.

Start integrating

Full endpoint reference, Python and PHP examples, and an interactive playground in the documentation — or start from the API overview and get your keys.