Partner API v1 documentation

REST API for the catalog, wallet balance, and eSIM orders. Live keys start with mega_live_, sandbox keys with mega_test_. There is no top-up endpoint: fund the wallet in the portal (card or Wise).

Base URL — server

https://api.megaesim.us/api/v1

Recommended for backends (Render, Node, Python) — bypasses Cloudflare bot challenges.

Base URL — browser

https://megaesim.us/api/v1

Manual tests or calls from an authenticated browser session.

Authentication: Authorization: Bearer mega_live_… · mega_test_…

MethodPathDescription
GET/meVerify the key and return account info
GET/plansPlan catalog (B2B pricing per account)
GET/plans/{id}Plan details
GET/walletWallet balance + recent transactions
GET/ordersOrder list (?limit=25, max 100)
POST/ordersPlace an order (debits wallet)
GET/orders/{id}Order status
GET/orders/{id}/esimeSIM data after delivery (QR, LPA, ICCID)
GET/esims/{iccid}/usageLive usage per ICCID (activation, data, expiry)

Quickstart

1. In the portal: Developers → new key. Sandbox keys start with mega_test_ and do not debit the wallet.

2. GET /plans and take the plan id. 3. POST /orders with a unique idempotencyKey. 4. If autoDelivered is false, poll GET /orders/{id} until delivered, then GET /orders/{id}/esim. 5. The QR payload is qrCodeData (LPA string).

cURL

curl https://api.megaesim.us/api/v1/plans \
  -H "Authorization: Bearer mega_test_..."

curl -X POST https://api.megaesim.us/api/v1/orders \
  -H "Authorization: Bearer mega_test_..." \
  -H "Content-Type: application/json" \
  -d '{"planId":7985,"deliveryEmail":"[email protected]","idempotencyKey":"order-2026-001"}'

Node.js

const res = await fetch("https://api.megaesim.us/api/v1/orders", {
  method: "POST",
  headers: {
    Authorization: "Bearer mega_test_...",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    planId: 7985,
    deliveryEmail: "[email protected]",
    idempotencyKey: "order-2026-001",
  }),
});
const order = await res.json();

Verify key — GET /me

Response 200: ok, accountEmail, apiKeyName, apiKeyId.

Request

GET https://megaesim.us/api/v1/me
Authorization: Bearer mega_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Catalog — GET /plans

Returns plans[]: id, name, nameEn, dataDescription, coverage, priceEuro, priceCents, validityDays, carrier, hasInstantDelivery, available, outOfStock.

Request

GET https://megaesim.us/api/v1/plans
Authorization: Bearer mega_live_…

Wallet — GET /wallet

Returns balanceCents, currency, and transactions[]. There is no top-up endpoint in the API — fund the wallet in the portal: card (Stripe, with fee) or Wise (from €100, no fee, credit 1:1).

Request

GET https://megaesim.us/api/v1/wallet
Authorization: Bearer mega_live_…

Place order — POST /orders

Response: orderId, amountCents, fulfillmentStatus, autoDelivered, autoRefunded, manualPending, emailSent, esimId (if auto-delivered).

Poll status: GET /orders/{id} — same order object as in the list. Orange ES: LPA may take a few minutes — poll until delivered, then GET /orders/{id}/esim.

In GET /plans, Orange ES plans include supportsActivationScheduling: true.

FieldRequiredDescription
planIdyesPlan ID from /plans
deliveryEmailnoEnd-customer email; omit = your account
customerNotenoInternal note (max 500 chars)
idempotencyKeyrecommendedSame key → same order
activationnoOrange ES only (7984–7986): startDate (YYYY-MM-DD, Europe/Bucharest) + durationMonths (1|2|3). Debit = priceCents × durationMonths. Default: today + 1 month.

Request

POST https://megaesim.us/api/v1/orders
Authorization: Bearer mega_live_…
Content-Type: application/json

{
  "planId": 7985,
  "deliveryEmail": "[email protected]",
  "customerNote": "Internal ref #12345",
  "idempotencyKey": "your-unique-key-2026-001",
  "activation": {
    "startDate": "2026-10-05",
    "durationMonths": 2
  }
}

Poll eSIM — GET /orders/{id}/esim

After delivery: esim with iccid, activationCode, qrCodeData, smdpAddress, deliveredAt.

If not ready yet: 404 with code esim_not_ready.

Request

GET https://megaesim.us/api/v1/orders/123456/esim
Authorization: Bearer mega_live_…

Live usage — GET /esims/{iccid}/usage

Look up usage and line status using the ICCID returned by /orders/{id}/esim.

200 response → usage object: iccid, supported, status (active | inactive | paused | expired | unknown), dataPlanStatus, dataUsedMb, activatedAt, orderedAt, expiresAt, expiryKind (data_ends | install_by | after_activation), planValidityDays, dailyResetAt, refreshedAt.

Data is cached ~3 minutes per eSIM. Add ?refresh=1 for a live read (use sparingly).

Usage fields are available only for eSIMs on networks that report consumption; otherwise supported:false and usage fields are null. Remaining data is not exposed — only dataUsedMb (total).

Unknown ICCID on your account → 404 esim_not_found. Usage provider temporarily down → 503 usage_upstream_unavailable.

Request

GET https://megaesim.us/api/v1/esims/8939104610004735215/usage
Authorization: Bearer mega_live_…

Webhooks — events to your URL

Register an HTTPS URL under Developers → Webhooks. We POST JSON for order.placed, order.delivered, order.refunded, wallet.topup.

Header: x-megaesim-signature = t=<unix>,v1=<hmac-sha256(secret, timestamp.body)>.

The payload id uniquely identifies the event. If your server is down, we resend the SAME id (1 min, 5 min, 30 min, 2 h) — we never create a new order or debit the wallet again.

Always send idempotencyKey on POST /orders so your own retries do not place two orders.

Public order statuses: pending_delivery, processing, delivered, failed_refunded. Internal supplier states are returned as processing.

Verify signature (Node)

const crypto = require("crypto");

function verifyMegaesim(secret, header, rawBody) {
  const t = String(header).match(/t=(\d+)/)?.[1];
  const v1 = String(header).match(/v1=([a-f0-9]+)/)?.[1];
  if (!t || !v1) return false;
  const expected = crypto.createHmac("sha256", secret).update(t + "." + rawBody).digest("hex");
  if (expected.length !== v1.length) return false;
  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(v1));
}

Sandbox — mega_test_

GET /me and GET /plans are real (your prices). GET /wallet returns balanceCents 0 and sandbox: true.

POST /orders does not debit and does not buy an eSIM. orderId = 900000000 + planId, fulfillmentStatus delivered, with a test qrCodeData that cannot be installed.

GET /esims/{iccid}/usage on a sandbox key returns simulated usage and does not call the network.

Common errors

The body is JSON: error (text), plus code on known failures. 402 may include missingCents.

  • 400 · bad_input — Invalid JSON, missing planId, or bad activation
  • 401 — Missing, invalid, or revoked key, or API access off
  • 402 · insufficient_balance — Wallet too low. missingCents is the shortfall
  • 404 · plan_not_found — Unknown plan
  • 404 · esim_not_ready — eSIM not delivered yet — keep polling
  • 404 · esim_not_found — ICCID is not on your account
  • 404 · account_not_found — The key's account no longer exists
  • 409 · out_of_stock — No stock, or supplier balance blocked
  • 410 · plan_inactive — Plan is no longer for sale
  • 409 · price_tbd — No price is set for this account
  • 429 — Rate limit. Body includes retryAfterSec
  • 503 · jit_disabled — Automatic delivery is temporarily off
  • 503 · usage_upstream_unavailable — Live usage is temporarily unavailable

Rate limits (per API key)

Reads (GET): 120 / minute · Orders (POST /orders): 30 / minute. When exceeded: HTTP 429 + retryAfterSec.

Security

  • Keep the key server-side only — never expose it in a public frontend.
  • Use idempotencyKey on every order (retry-safe).
  • Revoke compromised keys immediately in the section above.
  • Responses do not expose internal provisioning details.

Recommended flow

  1. GET /plans — show the catalog with your B2B prices.
  2. GET /wallet — check balance before ordering.
  3. POST /orders with idempotencyKey — place the order.
  4. If autoDelivered: false, poll GET /orders/{id} until fulfillmentStatus = delivered.
  5. GET /orders/{id}/esim — fetch QR / LPA / ICCID for the customer.
  6. GET /esims/{iccid}/usage — check line usage, activation and expiry anytime.

Postman

The collection includes every v1 endpoint, with baseUrl and apiKey variables. It does not contain your key.

Download Postman collection

Technical or commercial questions: [email protected]

Partner API v1 documentation — MegaEsim · MegaEsim