Skip to main content

eSIM Status

Get the live status of one of your eSIMs — current status, the network it last connected to, device details, activation/usage timestamps, and data usage — pulled directly from the network in real time. The stored record is updated with the fresh values at the same time.

Endpoint​

POST /api/v1/business/esims/status

AI prompt — eSIM Status (live)

Open raw .txt

Paste into ChatGPT, Claude, Cursor, Copilot or any coding agent to generate this part of your integration. Built-in recommendation: Support-console button only (live carrier query), throttled per eSIM — never on page load or in jobs.

Show prompt text (50 lines)
# eSIMfly Business API — eSIM Status, live (POST /esims/status) — prompt for AI coding assistants

TASK: build a SUPPORT / DIAGNOSTIC tool that fetches the LIVE status of one eSIM straight from the
network. This is the most expensive read in the API (it goes to the carrier in real time). It is
on-demand only: never on page load, never in a cron, never for every eSIM.

COMMON RULES (apply to every eSIMfly request)
- Base URL: https://esimfly.net/api/v1/business
- Headers on every call: RT-AccessCode (esf_...), RT-RequestID (fresh UUID v4 per request; reuse -> 400 DUPLICATE_REQUEST),
  RT-Timestamp (ms since epoch; >5 min old -> 401 INVALID_TIMESTAMP),
  RT-Signature = UPPERCASE hex HMAC-SHA256(secretKey, timestamp + requestId + accessCode + rawBody).
  rawBody = "" for GET; for POST/PUT sign the exact body string you send, with Content-Type: application/json.
- Keep access code + secret key server-side in env vars. Never ship them to a browser or mobile app.
- Responses: { success: true, ... } or { success: false, error|message, code }. Branch on `success` and `code`.
- Rate limits are per API key, shown in the business dashboard (typically 100/minute, 1,000/hour, 10,000/day) -> RATE_LIMIT_EXCEEDED. Pace bulk work at <= 1 req/s.
- Read `currency` from responses (USD | IQD | EUR for enterprise). Never hard-code it. IQD amounts are integers.
- Package codes are opaque strings: store and send back verbatim, never parse or prefix them.
- Node.js/TypeScript: use the official SDK instead of raw HTTP — `npm install @esimfly/sdk`
  (https://github.com/eSimfly-Official/esimfly-sdk-nodejs); it implements these rules. Other languages: implement the contract below.
- Full multi-endpoint prompt: https://docs.esimfly.net/llm/esimfly-api-full-prompt.txt

ENDPOINT
  POST https://esimfly.net/api/v1/business/esims/status
  Body: { "iccid": "8948010010036785060" }   or   { "esimId": 15757 }   (one of them)

RESPONSE 200
  { success: true, message: "Live eSIM status retrieved", data: {
      iccid, status: "NEW"|"ACTIVE"|"EXPIRED"|"DEPLETED", esim_status: "New"|"Not Active"|"Active"|"Installed"|"Assigned (Not Installed)",
      smdp_status, profile: "Enabled"|"Disabled"|"Not Installed"|null, unlimited,
      last_network: { operator, mcc, mnc, country, country_iso2, connection_type },   // null fields until first connection
      device: { model, imei },                                                          // null until installed
      activation_date|null, last_usage_date|null, expiry_date|null,
      data_usage: { used_gb, total_gb|null (unlimited), unlimited } } }
  The stored record on eSIMfly is refreshed with these values at the same time.

ERRORS: 400 MISSING_IDENTIFIER; 403 FORBIDDEN (not your eSIM); 404 ESIM_NOT_FOUND; 502 PROVIDER_ERROR (network unreachable — show "try again", do not auto-retry in a loop).

INTEGRATION PATTERN
1. Expose it as a "Check live status" button in the support/admin console and (optionally) a
   customer-facing "Diagnose my connection" action, rate-limited to e.g. 1 call per eSIM per 60 s.
2. Use it to answer: is the profile installed? which network did it last attach to? is it active?
   which device? — typical "no data" tickets. Pair with POST /esims/network-events for the event trail.
3. For routine "how much data is left" use GET /esims/usage/query instead (cheaper, cacheable).
4. Persist the returned snapshot on our esims row (last_network, device, activation_date, usage) so the
   ticket view can show the last known state without calling again.
5. Never call this for all eSIMs in a batch or from a scheduled job.

DELIVERABLE: getLiveEsimStatus(iccid) in the shared client, a per-eSIM 60 s throttle, and the support
console panel that renders the snapshot.

Building the whole integration? Use the complete prompt for all endpoints instead of combining the per-endpoint ones.

Authentication​

This endpoint requires HMAC authentication. See Authentication for details.

Request Headers​

HeaderTypeRequiredDescription
RT-AccessCodeStringYesYour API access code
RT-RequestIDStringYesUnique request ID (UUID v4)
RT-TimestampStringYesRequest timestamp in milliseconds
RT-SignatureStringYesHMAC-SHA256 signature
Content-TypeStringYesMust be "application/json"

Request Body​

Identify the eSIM by iccid (recommended) or esimId.

FieldTypeRequiredDescription
iccidStringYes*The ICCID of the eSIM to query
esimIdIntegerYes*The eSIM id (from the eSIM list/order response). Used if iccid is not provided.

* Provide either iccid or esimId.

{
"iccid": "8948010010036785060"
}

Response​

Success Response (200 OK)​

{
"success": true,
"message": "Live eSIM status retrieved",
"data": {
"iccid": "8948010010036785060",
"status": "ACTIVE",
"esim_status": "Active",
"smdp_status": "AFFECTED",
"profile": "Enabled",
"unlimited": false,
"last_network": {
"operator": "Optus",
"mcc": "505",
"mnc": "2",
"country": "Australia",
"country_iso2": "AU",
"connection_type": "4G - LTE"
},
"device": {
"model": "GTF7P",
"imei": "350000000000000"
},
"activation_date": "2026-06-26T14:34:40.000Z",
"last_usage_date": "2026-06-26T14:35:21.000Z",
"expiry_date": "2026-07-26T14:34:40.000Z",
"data_usage": {
"used_gb": 0,
"total_gb": 1,
"unlimited": false
}
}
}

Response Fields​

FieldTypeDescription
successBooleanWhether the live status was retrieved
messageStringHuman-readable summary
data.iccidStringThe ICCID of the eSIM
data.statusStringLifecycle status (e.g. NEW, ACTIVE, EXPIRED, DEPLETED)
data.esim_statusStringInstallation/usage state: New, Not Active, Active, Installed, or Assigned (Not Installed)
data.smdp_statusStringSM-DP+ profile status
data.profileString/nulleSIM profile installation state: Enabled, Disabled, or Not Installed
data.unlimitedBooleanWhether the plan is unlimited
data.last_networkObjectThe network the eSIM most recently connected to (null fields if it has not connected yet)
data.last_network.operatorStringNetwork operator name
data.last_network.mccStringMobile Country Code
data.last_network.mncStringMobile Network Code
data.last_network.countryStringCountry of the last network
data.last_network.country_iso2StringISO 3166-1 alpha-2 country code
data.last_network.connection_typeStringRadio access technology (e.g. 4G - LTE, 5G)
data.deviceObjectThe device the eSIM is installed on (null fields if not installed yet)
data.device.modelStringDevice model
data.device.imeiStringDevice IMEI
data.activation_dateString/nullWhen the eSIM was first activated (ISO 8601), or null if not activated
data.last_usage_dateString/nullTimestamp of the most recent data session (ISO 8601), derived from the network event log
data.expiry_dateString/nullWhen the plan expires (ISO 8601)
data.data_usageObjectData usage summary
data.data_usage.used_gbNumberData used, in GB
data.data_usage.total_gbNumber/nullPlan allowance in GB (null for unlimited plans)
data.data_usage.unlimitedBooleanWhether the plan is unlimited

Error Responses​

400 Bad Request​

Missing identifier:

{ "success": false, "message": "Provide either iccid or esimId", "code": "MISSING_IDENTIFIER" }

403 Forbidden​

eSIM does not belong to your account:

{ "success": false, "message": "You do not have permission to access this eSIM", "code": "FORBIDDEN" }

404 Not Found​

{ "success": false, "message": "eSIM not found", "code": "ESIM_NOT_FOUND" }

502 Bad Gateway​

The network could not be reached:

{ "success": false, "message": "Failed to fetch live status from the provider", "code": "PROVIDER_ERROR" }

Example​

const crypto = require('crypto');
const { v4: uuidv4 } = require('uuid');

async function getEsimStatus(iccid) {
const accessCode = 'esf_your_access_code';
const secretKey = 'sk_your_secret_key';

const body = JSON.stringify({ iccid });
const timestamp = Date.now().toString();
const requestId = uuidv4();
const signData = timestamp + requestId + accessCode + body;
const signature = crypto.createHmac('sha256', secretKey)
.update(signData)
.digest('hex')
.toUpperCase();

const response = await fetch('https://esimfly.net/api/v1/business/esims/status', {
method: 'POST',
headers: {
'RT-AccessCode': accessCode,
'RT-RequestID': requestId,
'RT-Timestamp': timestamp,
'RT-Signature': signature,
'Content-Type': 'application/json'
},
body
});

const data = await response.json();
if (data.success) {
const d = data.data;
console.log(`${d.status} on ${d.last_network.operator || 'no network'} — ${d.data_usage.used_gb} GB used`);
} else {
console.error(`Status lookup failed: ${data.message}`);
}
return data;
}

Notes​

  • Status is fetched live from the network on every call, so it always reflects the current state.
  • last_network, device, and activation_date are populated only once the eSIM has been installed and has connected to a network — they are null beforehand.
  • For unlimited plans, data_usage.total_gb is null and validity is governed by expiry_date.