Integrating Simology’s eSIM into your app or site should be quick, safe and predictable. This guide shows you how to stand up a working flow end‑to‑end: pull a live catalogue, create a checkout, and handle activation webhooks to deliver eSIM credentials. You’ll get example endpoints, headers, sample payloads, sandbox tips, and robust error and retry strategies so you can go live with confidence.
We assume you’re building for travellers and want a clean, reliable purchase and activation journey. The same patterns apply whether you’re selling a single-country plan like Esim United States or regional bundles such as Esim Western Europe and Esim North America. If you’re still shaping your plan range, explore available markets on Destinations and see what resonates with your audience. When you’re ready to partner, head to the Partner Hub or our For Business page to get access.
What you’ll build
A minimal, production‑ready integration includes:
- Catalog: Fetch plans (SKU, coverage, allowance, validity, price) and display them.
- Checkout: Create an order/checkout session and direct the user to pay.
- Webhooks: Receive order status and eSIM activation credentials securely.
- Activation: Present LPA QR or SM‑DP+ + activation code in your UI.
- Post‑purchase: Poll or subscribe to status updates; offer top‑ups if supported.
Prerequisites
- A Simology partner account with API credentials: request access via the Partner Hub.
- Sandbox environment enabled (for test cards and simulated activations).
- Public HTTPS webhook endpoint (TLS 1.2+, supports POST, returns 2xx on success).
- Server ability to store secrets and verify signatures.
- Optional: SDK installed (Node.js or Python) or curl for initial testing.
Tip: While you prototype, use live product copy from Destinations. For regional content and FAQs, see Esim France, Esim Italy and Esim Spain.
Environments and authentication
Typical environment split:
- Sandbox base URL (example): https://sandbox-api.simology.io
- Production base URL (example): https://api.simology.io
Authentication:
- Use the HTTP header: Authorization: Bearer YOUR_API_KEY
- Send JSON: Content-Type: application/json
- Use idempotency for POSTs: Idempotency-Key: a-unique-uuid-per-intent
Pro tips: - Rotate keys regularly; keep them server-side only. - Scope keys to least privilege; separate sandbox and production keys. - Log the response header request_id (if provided) for faster support.
Step 1: Fetch the eSIM catalogue
Endpoint (example): - GET /v1/catalog?country=US - GET /v1/catalog?region=western-europe
Example request:
GET /v1/catalog?country=US HTTP/1.1
Host: sandbox-api.simology.io
Authorization: Bearer sk_sandbox_123
Accept: application/json
Example response:
{
"items": [
{
"sku": "US-5GB-30D",
"name": "United States 5 GB / 30 days",
"region": "US",
"coverage": ["US"],
"data_allowance_mb": 5120,
"validity_days": 30,
"price": { "amount": 14.99, "currency": "USD" },
"activation_method": "lpa",
"esim_type": "data",
"terms_url": "https://simology.io/esim-united-states",
"available": true
}
],
"updated_at": "2025-01-10T09:12:44Z"
}
Implementation notes: - Cache catalogue responses for several minutes; invalidate on webhook or daily refresh. - Use query params to filter by country/region to reduce payloads. - Map regional SKUs to your UX—e.g., “Western Europe” → Esim Western Europe.
Pro tips: - Localise currencies client-side only if your payment provider requires it; keep SKU and currency from the API authoritative. - Surface coverage and validity clearly; travellers value transparency.
Step 2: Create a checkout session (order)
Endpoint (example): - POST /v1/checkout/sessions
Example request:
{
"customer": {
"email": "alex@example.com",
"country": "GB"
},
"items": [
{ "sku": "US-5GB-30D", "quantity": 1 }
],
"success_url": "https://yourapp.example/checkout/success?session_id={SESSION_ID}",
"cancel_url": "https://yourapp.example/checkout/cancel",
"metadata": {
"user_id": "u_789",
"source": "ios-app"
}
}
Example response:
{
"id": "cs_abc123",
"payment_url": "https://pay.sandbox.simology.io/cs_abc123",
"status": "pending",
"expires_at": "2025-01-10T09:27:44Z"
}
- Redirect the user to payment_url.
- On success, Simology will send a webhook (see next step) such as checkout.completed or order.paid.
Error example:
{
"error": {
"code": "sku_unavailable",
"message": "Requested SKU is not available in the selected region.",
"request_id": "req_9x8y7z"
}
}
Pro tips: - Always include a unique Idempotency-Key on POSTs to prevent duplicate orders. - Do not fulfil on the browser redirect alone; wait for the signed webhook.
Step 3: Webhooks for checkout and activation
Expose a POST endpoint, e.g., https://yourapp.example/webhooks/simology
Expected events (names may vary by integration): - checkout.completed — customer returned from payment - order.paid — funds confirmed; fulfilment can begin - activation.ready — eSIM credentials ready for delivery - order.failed or payment.failed — handle gracefully
Security: - Simology signs webhook payloads. Expect a header like: - Simology-Signature: t=1736500000,v1=hex-hmac-sha256 - Verify HMAC using your webhook secret and the raw request body + timestamp t. - Reject if signature invalid or timestamp skew > 5 minutes.
Example webhook: order.paid
{
"type": "order.paid",
"id": "evt_123",
"created": "2025-01-10T09:20:02Z",
"data": {
"order_id": "ord_456",
"session_id": "cs_abc123",
"items": [
{ "sku": "US-5GB-30D", "quantity": 1, "unit_price": 14.99, "currency": "USD" }
],
"customer": { "email": "alex@example.com" }
}
}
Example webhook: activation.ready
{
"type": "activation.ready",
"id": "evt_789",
"created": "2025-01-10T09:21:10Z",
"data": {
"order_id": "ord_456",
"line": {
"iccid": "8988307000001234567",
"smdp_plus": "LPA:1$sm-dp-plus.simology.net$ACT-CODE-1234",
"qr_url": "https://sandbox-api.simology.io/v1/qr/ord_456.png",
"valid_from": "2025-01-10T09:21:10Z",
"expires_at": "2025-02-09T23:59:59Z"
}
}
}
Retries: - Respond 2xx on success within 5 seconds. - Non-2xx triggers automatic retries with exponential backoff (e.g., 1m, 5m, 30m, hourly up to 48h). - Webhooks are idempotent; use the event id to deduplicate.
Pro tips: - Store the full webhook event before processing; reprocess safely if needed. - Use a separate signing secret per environment; rotate on a schedule.
Step 4: Deliver and activate the eSIM
Once you receive activation.ready: - If you display QR in-app: render qr_url or generate your own QR from the LPA string (smdp_plus). Confirm the screen brightness/instructions for scanning. - If you deliver manually: present the SM‑DP+ address and activation code clearly.
UI checklist: - Show coverage and validity (mirror your catalogue details, e.g., Esim North America). - Provide concise device instructions (Settings > Mobile Data > Add eSIM). - Remind users to keep primary SIM for calls/SMS if needed, using data on eSIM. - Offer a link back to plan details (e.g., Esim United States) for FAQs.
Step 5: Post‑activation status and top‑ups
Common endpoints (examples): - GET /v1/orders/{order_id} — check latest status. - GET /v1/lines/{iccid} — inspect data used/remaining. - POST /v1/topups — add data to an existing line.
Example line status:
{
"iccid": "8988307000001234567",
"status": "active",
"data": {
"used_mb": 1200,
"remaining_mb": 3920
},
"valid_until": "2025-02-09T23:59:59Z"
}
Pro tips: - Cache status for 30–60 seconds to avoid rate limits. - If you surface data usage, include a timestamp and note that roaming networks can report with slight delay.
Errors, rate limits and observability
HTTP status patterns: - 400 validation_error — your request is malformed (missing field, invalid SKU). - 401/403 auth_error — bad or expired credentials, wrong environment key. - 404 not_found — order/line ID not recognised. - 409 conflict — duplicate idempotency key with different payload. - 429 rate_limited — back off using Retry-After header. - 5xx server_error — transient; retry with backoff and jitter.
Canonical error body:
{
"error": {
"code": "rate_limited",
"message": "Too many requests. Try again later.",
"request_id": "req_123",
"retry_after": 30
}
}
Best practices: - Always log request_id and error.code. - Implement circuit breakers for persistent 5xx. - Respect Retry-After on 429; apply exponential backoff with jitter. - Use unique Idempotency-Key per action (e.g., “create checkout for cart 123”). - Monitor webhook delivery success rate and age of last processed event.
SDK quick start
While you can integrate with raw HTTP, SDKs speed up auth, idempotency and webhook verification. The shapes below reflect the examples above; adapt to your language and tooling.
Node.js (example):
import { Simology } from "@simology/sdk";
const sim = new Simology({ apiKey: process.env.SIMOLOGY_API_KEY, baseUrl: "https://sandbox-api.simology.io" });
const catalog = await sim.catalog.list({ country: "US" });
const session = await sim.checkout.create({
customer: { email: "alex@example.com", country: "GB" },
items: [{ sku: "US-5GB-30D", quantity: 1 }],
success_url: "https://yourapp.example/success?session_id={SESSION_ID}",
cancel_url: "https://yourapp.example/cancel"
});
Webhook verification (pseudo):
app.post("/webhooks/simology", express.raw({ type: "application/json" }), (req, res) => {
const signature = req.header("Simology-Signature");
const event = sim.webhooks.verify(req.body, signature, process.env.SIMOLOGY_WEBHOOK_SECRET);
// process event.type ...
res.sendStatus(200);
});
Python (example):
from simology import Simology
sim = Simology(api_key=os.getenv("SIMOLOGY_API_KEY"), base_url="https://sandbox-api.simology.io")
catalog = sim.catalog.list(country="US")
Tip: Keep the webhook route using raw body to preserve signature integrity.
Security and privacy essentials
- Store only what you need (e.g., order_id, sku, iccid). Avoid storing full QR images if the LPA string is sufficient.
- Encrypt secrets at rest; restrict access via IAM.
- Validate webhook payload against expected schema before acting.
- Do not render raw error messages to end users; translate to helpful guidance.
Go‑live checklist
- Sandbox to production switch with environment flags.
- API key rotation plan and secret storage verified.
- Idempotency implemented on all POST operations.
- Webhook endpoint verified with signature checks and 2xx acks.
- Observability: logs capture request_id, event.id, order_id, iccid.
- Rate limit handling and backoff tested.
- Happy path and failure path user messaging in place.
- Regional catalogue mapped to your content (e.g., Esim France, Esim Italy).
FAQ
- How do sandbox and production differ? Sandbox uses test payment and simulated activation events. Payload shapes mirror production, but no real provisioning occurs. Use separate API keys and webhook secrets per environment.
- Can I test activation without scanning a QR? Yes. Use the LPA string (SM‑DP+ and activation code) from activation.ready to test your UI. In sandbox, you can display it without provisioning a real profile.
- What happens if my webhook endpoint is down? Simology retries with exponential backoff for a defined window (for example, up to 48 hours). Keep processing idempotent and return 2xx only after you have safely stored/handled the event.
- How should I handle plan regions in my UX? Keep your SKUs aligned with clear coverage descriptions (country vs region). Link to destination pages like Esim United States or Esim Western Europe for clarity, and aggregate them under Destinations.
- Can I issue refunds or cancellations via API? Many setups support POST /v1/refunds or cancelling unpaid checkouts. Always wait for webhook confirmation (refund.processed) before altering customer entitlements.
- Do you support top‑ups and usage queries? Yes in most cases—use the lines and topups endpoints as shown. Cache usage responses briefly and inform travellers about reporting delays when roaming.
Next step: Ready to get credentials and sandbox access? Visit the Partner Hub to kick off your integration.