Quickstart
Four calls: get a token, find a package, order it, read the eSIM. Everything below runs against sandbox, so nothing here spends real money.
Before you start
Section titled “Before you start”In the partner portal, open API Integration and create a sandbox key
with the scopes catalog:read, orders:write and esims:read.
Copy the client_secret now — it is shown once and stored only as a hash.
1. Get a token
Section titled “1. Get a token”curl -X POST https://partner-api.esimfo.com/oauth/token \ -H 'Content-Type: application/json' \ -d '{ "grant_type": "client_credentials", "client_id": "esf_test_ci_4f9c2a1b8e7d6c5a4b3f2e1d0c9b8a7f", "client_secret": "esf_test_cs_xN2pQ7vR...redacted" }'{ "access_token": "esf_test_at_9K3mR7pQ2wX5nB8vC1zL4jH6tY0dF...", "token_type": "Bearer", "expires_in": 3600, "scope": "catalog:read orders:write esims:read"}The token lasts an hour. Cache it — do not fetch one per request.
2. Find a package
Section titled “2. Find a package”This example uses a flat package list. To build a storefront organized by
catalog, use List catalogs with packages and take the
order’s package_id from data[].packages[].id.
curl 'https://partner-api.esimfo.com/v1/catalog/packages?country=TR&limit=5' \ -H 'Authorization: Bearer esf_test_at_...'{ "data": [ { "id": "pkg_tr_3gb_30d", "name": "Turkey 3 GB — 30 days", "service_type": "DATA", "data_policy": "FIXED", "data_amount_mb": 3072, "validity_days": 30, "countries": ["TR"], "currency": "EUR", "price": "4.20", "selling_price": "6.30" } ], "next_cursor": null, "has_more": false}price is what you pay us. selling_price is what you charge. Take the id.
3. Place the order
Section titled “3. Place the order”The Idempotency-Key is required. Generate a UUID and store it alongside
your own order record before you make the call — that is what makes a retry
safe.
curl -X POST https://partner-api.esimfo.com/v1/orders \ -H 'Authorization: Bearer esf_test_at_...' \ -H 'Idempotency-Key: 9f1c4e2a-7b3d-4a58-9c06-2e8f5d1b4a73' \ -H 'Content-Type: application/json' \ -d '{ "items": [{ "package_id": "pkg_tr_3gb_30d", "quantity": 1 }], "client_reference": "cart-4821" }'{ "id": "ord_4b21c9e7", "order_number": "ESF-2026-0004821", "status": "COMPLETED", "payment_mode": "BALANCE", "subtotal": "4.20", "commission_amount": "0.00", "total": "4.20", "currency": "EUR", "client_reference": "cart-4821", "created_at": "2026-08-22T09:14:03.512Z", "items": [ { "package_id": "pkg_tr_3gb_30d", "quantity": 1, "unit_price": "4.20", "line_total": "4.20" } ], "esims": [ { "id": "esm_9a3f1c", "iccid": "89852350326100409575", "lpa_code": "LPA:1$rsp.truphone.com$QR-G-5C-1LK-1V0FS", "qr_code_url": "https://cdn.esimfo.com/qr/esm_9a3f1c.png", "smdp_address": "rsp.truphone.com", "matching_id": "QR-G-5C-1LK-1V0FS", "status": "PROVISIONED", "data_total_mb": 3072, "data_used_mb": 0, "data_remaining_mb": null, "expires_at": null, "failure_reason": null } ]}Most orders come back COMPLETED with the eSIM already attached.
4. Deliver the eSIM
Section titled “4. Deliver the eSIM”Everything the traveller needs is on the eSIM object:
qr_code_url— show or email this. Scanning it installs the profile.lpa_code— the same thing as text, for manual installation. On iOS this is what “Enter Details Manually” expects.smdp_addressandmatching_id— the two halves of the LPA string, for devices that ask for them separately.
That is a working integration. From here:
- Read Idempotency properly before you handle real money.
- Wire up Webhooks so you are not polling.
- Work through Going live before your first real sale.
