Skip to main content

Query eSIM Usage

Get detailed usage information for a specific eSIM by ICCID or Order ID.

Endpoint​

GET /api/v1/business/esims/usage/query

AI prompt — Query eSIM Usage

Open raw .txt

Paste into ChatGPT, Claude, Cursor, Copilot or any coding agent to generate this part of your integration. Built-in recommendation: On demand when a customer opens one eSIM, cached 5–15 min and persisted locally — never in a per-eSIM cron.

Show prompt text (48 lines)
# eSIMfly Business API — Query eSIM Usage (GET /esims/usage/query) — prompt for AI coding assistants

TASK: show a customer how much data is left on ONE eSIM. Call on demand when the customer opens the
eSIM, cache the result, and never loop over all eSIMs with this endpoint.

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
  GET https://esimfly.net/api/v1/business/esims/usage/query?iccid=<iccid>
  or  GET https://esimfly.net/api/v1/business/esims/usage/query?order_id=<orderReference>
  Exactly one of iccid / order_id is required (prefer iccid). from_date/to_date are reserved (ignored today).

RESPONSE 200
  { success: true, data: {
      esim: { iccid, order_id, package_name, status },                       // status: NEW|ACTIVE|EXPIRED|...
      data: { total_mb, used_mb, remaining_mb, usage_percentage, is_unlimited },   // unlimited: total_mb = 0, remaining_mb = 0
      validity: { days, activated_at, expires_at, is_expired } } }
  usage_percentage is capped at 100.

ERRORS
  400 "Either iccid or order_id is required"; 404 "eSIM not found or you do not have access to it"; 401 auth errors.

INTEGRATION PATTERN
1. Trigger: customer opens "My eSIM" / taps refresh; support agent opens an eSIM. Nothing else.
2. Cache per ICCID for 5–15 minutes (shorter while status is ACTIVE and usage_percentage > 80, e.g. 2 min).
   Also persist the latest values on our esims row so lists and emails can render without any API call.
3. Do NOT run this per eSIM in a cron. If we need fleet-wide usage, use the nightly GET /esims?status=ACTIVE
   reconciliation (100 eSIMs per request) instead — it is 100x cheaper.
4. Low-data / expiry notifications: compute from the values stored during customer views and the nightly
   reconciliation, not from live calls.
5. 404 means the ICCID is not on this account — treat as "not found", not as a retryable error.

DELIVERABLE: getEsimUsage(iccid) with per-ICCID cache, persistence of the last known usage on our esims
row, and the customer "remaining data" view fed from it.

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

Query Parameters​

ParameterTypeRequiredDescription
iccidStringNo*ICCID of the eSIM to query
order_idStringNo*Order ID associated with the eSIM
from_dateStringNoStart date for usage history (YYYY-MM-DD)
to_dateStringNoEnd date for usage history (YYYY-MM-DD)

*Either iccid or order_id is required, but not both.

Response​

Success Response (200 OK)​

{
"success": true,
"data": {
"esim": {
"iccid": "8910300001234567890",
"order_id": "ESF_1234567890",
"package_name": "Sweden 1GB - 7 Days",
"status": "ACTIVE"
},
"data": {
"total_mb": 1024,
"used_mb": 256,
"remaining_mb": 768,
"usage_percentage": 25,
"is_unlimited": false
},
"validity": {
"days": 7,
"activated_at": "2024-01-29T10:30:00Z",
"expires_at": "2024-02-05T10:30:00Z",
"is_expired": false
}
}
}

Response Fields​

FieldTypeDescription
esimObjectBasic eSIM information
esim.iccidStringICCID (SIM card number)
esim.order_idStringOrder reference ID
esim.package_nameStringPackage display name
esim.statusStringStandardized status (NEW, ACTIVE, EXPIRED, etc.)
dataObjectData usage information
data.total_mbIntegerTotal data in MB (0 for unlimited)
data.used_mbIntegerData used in MB
data.remaining_mbIntegerData remaining in MB (0 for unlimited)
data.usage_percentageNumberUsage percentage (0-100)
data.is_unlimitedBooleanWhether plan has unlimited data
validityObjectValidity period information
validity.daysIntegerTotal validity days
validity.activated_atStringActivation timestamp (ISO 8601)
validity.expires_atStringExpiration timestamp (ISO 8601)
validity.is_expiredBooleanWhether eSIM has expired

Examples​

Query by ICCID​

const queryParams = new URLSearchParams({
iccid: '8910300001234567890'
});

const response = await fetch(
`https://esimfly.net/api/v1/business/esims/usage/query?${queryParams}`,
{
headers: generateHMACHeaders() // Your HMAC function
}
);

Query by Order ID​

const queryParams = new URLSearchParams({
order_id: 'ESF_1234567890'
});

const response = await fetch(
`https://esimfly.net/api/v1/business/esims/usage/query?${queryParams}`,
{
headers: generateHMACHeaders()
}
);

Query with Date Range (Future Feature)​

const queryParams = new URLSearchParams({
iccid: '8910300001234567890',
from_date: '2024-01-01',
to_date: '2024-01-31'
});

const response = await fetch(
`https://esimfly.net/api/v1/business/esims/usage/query?${queryParams}`,
{
headers: generateHMACHeaders()
}
);

// When implemented, response will include:
// "usage_history": [
// {
// "date": "2024-01-15",
// "data_used_mb": 100,
// "cumulative_mb": 256
// }
// ]

Full Example (Node.js)​

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

async function queryESIMUsage(identifier, identifierType = 'iccid') {
const accessCode = 'esf_your_access_code';
const secretKey = 'sk_your_secret_key';

// Generate HMAC headers
const timestamp = Date.now().toString();
const requestId = uuidv4();
const signData = timestamp + requestId + accessCode;
const signature = crypto.createHmac('sha256', secretKey)
.update(signData)
.digest('hex')
.toUpperCase();

// Build query parameters
const queryParams = new URLSearchParams({
[identifierType]: identifier
});

const response = await fetch(
`https://esimfly.net/api/v1/business/esims/usage/query?${queryParams}`,
{
headers: {
'RT-AccessCode': accessCode,
'RT-RequestID': requestId,
'RT-Timestamp': timestamp,
'RT-Signature': signature
}
}
);

const data = await response.json();

if (data.success) {
const { esim, data: usage, validity } = data.data;

console.log(`eSIM: ${esim.package_name}`);
console.log(`Status: ${esim.status}`);
console.log(`Usage: ${usage.used_mb}MB / ${usage.total_mb}MB (${usage.usage_percentage}%)`);
console.log(`Remaining: ${usage.remaining_mb}MB`);

if (validity.is_expired) {
console.log('Status: EXPIRED');
} else {
const daysLeft = Math.ceil(
(new Date(validity.expires_at) - new Date()) / (1000 * 60 * 60 * 24)
);
console.log(`Days remaining: ${daysLeft} of ${validity.days}`);
}
}

return data;
}

// Example usage
queryESIMUsage('8910300001234567890', 'iccid');
queryESIMUsage('ESF_1234567890', 'order_id');

Error Responses​

400 Bad Request​

Missing required parameters:

{
"error": "Bad Request",
"message": "Either iccid or order_id is required"
}

404 Not Found​

eSIM not found:

{
"error": "Not Found",
"message": "eSIM not found or you do not have access to it"
}

401 Unauthorized​

Authentication errors follow the same pattern as other endpoints:

{
"success": false,
"error": "Authentication required",
"message": "Please provide either Bearer token or complete HMAC signature authentication"
}

Use Cases​

1. Real-time Usage Monitoring​

Monitor data consumption for active eSIMs:

async function checkDataUsage(iccid) {
const usage = await queryESIMUsage(iccid, 'iccid');

if (usage.data.usage_percentage > 80) {
console.warn(`High usage alert: ${usage.data.usage_percentage}% consumed`);
// Send notification or trigger top-up
}
}

2. Expiry Tracking​

Check if eSIMs are about to expire:

async function checkExpiry(orderIds) {
for (const orderId of orderIds) {
const result = await queryESIMUsage(orderId, 'order_id');

if (result.success) {
const { validity } = result.data;

if (!validity.is_expired) {
const daysLeft = Math.ceil(
(new Date(validity.expires_at) - new Date()) / (1000 * 60 * 60 * 24)
);

if (daysLeft <= 3) {
console.log(`eSIM ${orderId} expires in ${daysLeft} days`);
}
}
}
}
}

3. Customer Support​

Quickly check eSIM status for support queries:

async function supportLookup(identifier) {
// Try ICCID first
let result = await queryESIMUsage(identifier, 'iccid');

// If not found, try as order ID
if (!result.success) {
result = await queryESIMUsage(identifier, 'order_id');
}

if (result.success) {
const { esim, data, validity } = result.data;

console.log('=== eSIM Support Information ===');
console.log(`Package: ${esim.package_name}`);
console.log(`Status: ${esim.status}`);
console.log(`Data: ${data.used_mb}/${data.total_mb}MB`);
console.log(`Expires: ${validity.expires_at || 'N/A'}`);
}
}

Best Practices​

  1. Cache Results Appropriately

    • Usage data changes as customers use data
    • Consider caching for 5-15 minutes for non-critical displays
    • Always fetch fresh data for critical operations
  2. Error Handling

    • Always check if the eSIM exists before processing
    • Handle both 404 (not found) and 401 (unauthorized) errors
    • Implement retry logic for network failures
  3. Identifier Choice

    • Use ICCID when available (more specific)
    • Order ID is useful for customer-facing lookups
    • Store both identifiers in your system for flexibility
  4. Performance

    • This endpoint queries a single eSIM - very fast
    • For bulk operations, consider using the list endpoint with filters
    • Implement parallel requests carefully to avoid rate limits

Notes​

  • Data usage is calculated in real-time from provider data
  • All data values are in megabytes (MB) for consistency
  • Unlimited plans show total_mb: 0 and is_unlimited: true
  • The from_date and to_date parameters are reserved for future usage history features
  • Usage percentages are capped at 100% even if over-usage occurs