NovaCodes

Manage an eSIM

This page is about travel eSIMs. Selling gift cards instead? See Gift card orders.

Status and data used, top-ups, and cancelling for a refund.

After delivery an eSIM is known by its iccid. With it you can read the eSIM's state and data used, add data to it, and cancel it for a refund while it was never installed. Amounts are in minor units, laari and cents: see Balances & amounts.

Status and data used

You read an eSIM by its ICCID. A key only sees eSIMs that were ordered through the API: one bought on the website, even by the same account, answers 404 not_found.

GET/esim/esims/{iccid}
One eSIM of your account: its state, its data and its install details. 404 not_found when there is no eSIM with that ICCID on your account.
Path fieldTypeRequiredMeaning
iccidstringyesThe eSIM's iccid from the order: 15 to 22 digits.
Request
curl -s https://api.novacodes.app/v1/esim/esims/8985224628000101 \
  -H "Authorization: Bearer $NOVACODES_KEY"
Response
{"data": {
  "iccid": "8985224628000101", "order": "NC-22748", "plan_id": 43, "destination": "Maldives",
  "state": "in_use", "data_total_mb": 1024, "data_used_mb": 256,
  "usage_at": "2026-09-21T21:18:48+00:00",
  "expires_at": "2027-03-18T10:00:00+00:00", "installed_at": "2026-09-21T21:18:48+00:00",
  "top_up": true, "cancellable": false,
  "install": {
    "lpa": "LPA:1$rsp.test$MATCH-1",
    "smdp_address": "rsp.test",
    "activation_code": "MATCH-1",
    "qr_svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" …>…</svg>",
    "ios_install_url": "https://esimsetup.apple.com/esim_qrcode_provisioning?carddata=LPA%3A1%24rsp.test%24MATCH-1"
  }}}
FieldTypeMeaning
iccidstringThe serial number of the eSIM.
orderstringThe number of the order that bought it.
plan_id, destinationinteger, stringThe plan it was bought with, and the destination’s name.
statestringready, installed, in_use, depleted, expired, cancelled or revoked. Explained in The life of an eSIM.
data_total_mbinteger or nullThe data on the eSIM, in MB, top-ups included. null while it is not known.
data_used_mbinteger or nullThe data used so far, in MB. null while it is not known.
usage_atstring or nullWhen state and the data figures were last read from the network. null when they were never read.
expires_atstring or nullWhen the eSIM ends, as the network reports it now. The date can move: when the plan starts, and when data is added.
installed_atstring or nullWhen we first saw the eSIM installed. null while it is ready.
top_upbooleanWhether data can be added to this eSIM.
cancellablebooleanWhether a cancel can succeed as far as we know. The real check is made when you cancel: see Cancel for a refund.
installobject or nullThe install details, as in the order. null when the eSIM is cancelled or revoked.

Times are ISO 8601 with a time zone offset.

How fresh the figures are

  • This call asks the network for the state and the data used, but at most once every five minutes per eSIM. In between, it answers with what it knew, and usage_at tells you how old that is.
  • So polling faster than every five minutes gains nothing. When you show usage to your customer, show usage_at with it.
  • The networks themselves report data use with a delay, which can be a few hours. Do not present data_used_mb as live.
  • When the network does not answer, you still get a normal answer, with the last known figures and their usage_at.
  • The eSIMs inside an order (GET /esim/orders/…) show the last known state and never ask the network. Read the eSIM itself for a current one.

What can be added to an eSIM

GET/esim/esims/{iccid}/topups
The plans that can be added to this eSIM, at your prices. An empty list means nothing can be added.
Request
curl -s https://api.novacodes.app/v1/esim/esims/8985224628000101/topups \
  -H "Authorization: Bearer $NOVACODES_KEY"
Response
{"data": [
  {"plan_id": 43, "name": "Maldives 1GB 7Days", "destination": {"code": "MV", "name": "Maldives"},
   "type": "fixed", "data_mb": 1024, "days": 7, "min_days": null, "max_days": null,
   "price": {"MVR": 18000, "USD": 899, "USDT": 872}, "retail_price": {"MVR": 24000, "USD": 1199, "USDT": 1199}, "price_days": null,
   "speed": "3G/4G", "after_daily_limit": null, "validity_starts": "first_use", "install_within_days": 180,
   "top_up": true, "phone_number": true, "ip_country": "PL", "countries": 1},
  {"plan_id": 45, "name": "Maldives 3GB 30Days", "destination": {"code": "MV", "name": "Maldives"},
   "type": "fixed", "data_mb": 3072, "days": 30, "min_days": null, "max_days": null,
   "price": {"MVR": 55000, "USD": 2749, "USDT": 2667}, "retail_price": {"MVR": 73000, "USD": 3649, "USDT": 3649}, "price_days": null,
   "speed": "3G/4G", "after_daily_limit": null, "validity_starts": "first_use", "install_within_days": 180,
   "top_up": true, "phone_number": true, "ip_country": "PL", "countries": 1}
]}
  • Each entry is a plan, with the same fields as in the catalogue.
  • Only these plans can be added. Another plan, even one for the same destination, is refused.
  • The list is empty when the eSIM's top_up is false, and when the eSIM is expired, cancelled or revoked. A depleted eSIM can still be topped up.

Add data (top up)

POST/esim/esims/{iccid}/topups
Buys one plan from the list above and adds it to this eSIM. The data lands on the same eSIM: your customer has nothing new to install.
FieldTypeRequiredMeaning
plan_idintegeryesA plan from GET /esim/esims/{iccid}/topups.
balancestringif the key has no default"MVR", "USD" or "USDT": the balance to charge, at that currency's price. Left out, the key's default currency is charged (USD when none is set).
referencestringyesYour own unique id for this purchase, with the same rules as for an order. Use a new one: the reference of the order that bought the eSIM, or of a top-up of another eSIM, is refused with 409 reference_in_use.
daysintegerdaily plansHow many days to add. Required when the plan is a daily plan, ignored otherwise.
Request
curl -s https://api.novacodes.app/v1/esim/esims/8985224628000101/topups \
  -H "Authorization: Bearer $NOVACODES_KEY" \
  -H "Content-Type: application/json" \
  -d '{"plan_id": 45, "balance": "MVR", "reference": "trip-8841-more"}'
Response · 201 (200 for a repeated reference)
{"data": {
  "number": "NC-22751", "reference": "trip-8841-more", "kind": "topup", "status": "completed",
  "plan_id": 45, "plan": "3 GB · 30 days", "destination": "Maldives", "days": 30,
  "quantity": 1, "delivered": 1, "processing": 0, "refunded_units": 0,
  "currency": "MVR", "unit_price": 55000, "total": 55000, "refunded": 0, "charged": 55000,
  "created_at": "2026-09-21T21:18:48+00:00",
  "iccid": "8985224628000101"}}
  • There is no quantity: a top-up is always one plan added to one eSIM.
  • The answer is an order of kind topup. It carries the iccid it was added to, and no esims.
  • It is an order like any other: the same statuses, the same safe retry with the same reference, and you read it with GET /esim/orders/{reference}.
  • Once an eSIM has been topped up, it can no longer be cancelled.
  • Read the eSIM afterwards to see its new data_total_mb and expires_at.
Refused · 422
{"error": {"code": "topup_not_allowed", "message": "That data cannot be added to this eSIM any more."}}

Cancel for a refund

POST/esim/esims/{iccid}/cancel
Cancels an eSIM that was never installed and returns its full price to the balance that paid. No request body.
Request
curl -s -X POST https://api.novacodes.app/v1/esim/esims/8985224628000102/cancel \
  -H "Authorization: Bearer $NOVACODES_KEY"
Response · 200
{"data": {"iccid": "8985224628000102", "state": "cancelled", "refunded": 18000, "currency": "MVR"}}
FieldMeaning
iccid, stateThe eSIM, now cancelled. It can no longer be installed, and its install is null from now on.
refunded, currencyThe amount returned, in minor units, and the balance it went to: the one that paid for the eSIM.

A cancel succeeds only when all of this is true:

  • The eSIM was never installed: its state is ready. We ask the network at the moment you cancel, so an eSIM your customer installed a minute ago is refused even if you last saw cancellable: true.
  • It was never topped up.
  • It was not cancelled before. An eSIM is refunded once.

Otherwise the answer is 409 not_cancellable, nothing changes and nothing is refunded. The message says which rule applied. It also says so when the network could not be asked just now: that is the one case where trying again a minute later can help.

Refused · 409
{"error": {"code": "not_cancellable", "message": "This eSIM has been installed, so it can no longer be cancelled."}}

After a cancel, the order that bought the eSIM counts it in refunded_units and refunded, and its status becomes partial_refunded or refunded.

Only cancel an eSIM that your customer will not install. A cancelled eSIM cannot be installed, and an installed eSIM cannot be refunded.