Usage Report
Get a daily data-usage report for one of your eSIMs over a period (7, 14, or 30 days): total and average usage, a day-by-day breakdown, and a breakdown by country and operator. Useful for showing customers where and how much data they've used.
Endpoint
POST /api/v1/business/esims/usage-report
AI prompt — Usage Report
Paste into ChatGPT, Claude, Cursor, Copilot or any coding agent to generate this part of your integration. Built-in recommendation: On-demand per-eSIM report with a 1-hour cache; use the usage query for the headline number.
Show prompt text (44 lines)
# eSIMfly Business API — Usage Report (POST /esims/usage-report) — prompt for AI coding assistants
TASK: produce a daily data-usage report (totals, per-day, per-country, per-operator) for ONE eSIM over the
last 7 / 14 / 30 days (max 90). On-demand report for a customer or support screen; cache it; never
generate it for every eSIM on a schedule.
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/usage-report
Body: { "iccid": "8948010010036785060", "days": 7 } // days optional (default 7, max 90); esimId may replace iccid
RESPONSE 200
{ success: true, data: { iccid, period_days, start_date, end_date,
summary: { total_data_mb, total_data_gb, avg_daily_mb, avg_daily_gb }, // avg over days WITH usage
daily_usage: [{ date: "YYYY-MM-DD", data_mb, data_gb }], // newest first, UTC days
by_country: [{ country, mcc, data_mb, data_gb, operators: [{ operator, mnc, data_mb, data_gb }] }] } }
If the eSIM has not connected yet, totals are 0 and arrays are empty.
ERRORS: 400 MISSING_IDENTIFIER; 400 NOT_SUPPORTED (no reports for this eSIM — hide the feature); 403 FORBIDDEN; 404 ESIM_NOT_FOUND.
INTEGRATION PATTERN
1. Trigger from a "Usage details" tab or a support request; cache per (iccid, days) for 60 minutes.
2. For the headline "remaining data" number use GET /esims/usage/query instead — cheaper and fresher.
3. Offer 7 / 14 / 30 day presets; do not request 90 days by default.
4. Render daily bars + a country/operator breakdown; keep MB precision from the API, format GB for display.
5. Never loop this endpoint over the fleet for analytics; if fleet-level usage is needed, aggregate from
the nightly GET /esims reconciliation instead.
DELIVERABLE: getUsageReport(iccid, days) with a 1-hour cache and the report view.
Authentication
This endpoint requires HMAC authentication. See Authentication for details.
Request Headers
| Header | Type | Required | Description |
|---|---|---|---|
| RT-AccessCode | String | Yes | Your API access code |
| RT-RequestID | String | Yes | Unique request ID (UUID v4) |
| RT-Timestamp | String | Yes | Request timestamp in milliseconds |
| RT-Signature | String | Yes | HMAC-SHA256 signature |
| Content-Type | String | Yes | Must be "application/json" |
Request Body
Identify the eSIM by iccid (recommended) or esimId.
| Field | Type | Required | Description |
|---|---|---|---|
| iccid | String | Yes* | The ICCID of the eSIM |
| esimId | Integer | Yes* | The eSIM id (from the eSIM list/order response). Used if iccid is not provided. |
| days | Integer | No | Reporting window in days (default 7, max 90). Typical values: 7, 14, 30. |
* Provide either iccid or esimId.
{
"iccid": "8948010010036785060",
"days": 7
}
Response
Success Response (200 OK)
{
"success": true,
"message": "Usage report retrieved",
"data": {
"iccid": "8948010010036785060",
"period_days": 7,
"start_date": "2026-06-21T00:00:00.000Z",
"end_date": "2026-06-27T00:00:00.000Z",
"summary": {
"total_data_mb": 1260,
"total_data_gb": 1.23,
"avg_daily_mb": 1260,
"avg_daily_gb": 1.23
},
"daily_usage": [
{ "date": "2026-06-27", "data_mb": 1260, "data_gb": 1.23 }
],
"by_country": [
{
"country": "Turkey",
"mcc": "286",
"data_mb": 1260,
"data_gb": 1.23,
"operators": [
{ "operator": "Turkcell", "mnc": "01", "data_mb": 1260, "data_gb": 1.23 }
]
}
]
}
}
Response Fields
| Field | Type | Description |
|---|---|---|
| success | Boolean | Whether the report was retrieved |
| data.iccid | String | The ICCID of the eSIM |
| data.period_days | Integer | The reporting window used |
| data.start_date / data.end_date | String | The report period (ISO 8601) |
| data.summary.total_data_mb / total_data_gb | Number | Total data used in the period |
| data.summary.avg_daily_mb / avg_daily_gb | Number | Average per day with usage |
| data.daily_usage | Array | Per-day usage, newest first |
| data.daily_usage[].date | String | Day (YYYY-MM-DD) |
| data.daily_usage[].data_mb / data_gb | Number | Data used that day |
| data.by_country | Array | Usage grouped by country |
| data.by_country[].country | String | Country name |
| data.by_country[].mcc | String | Mobile Country Code |
| data.by_country[].data_mb / data_gb | Number | Data used in that country |
| data.by_country[].operators | Array | Per-operator breakdown within the country |
| data.by_country[].operators[].operator | String | Operator name |
| data.by_country[].operators[].mnc | String | Mobile Network Code |
| data.by_country[].operators[].data_mb / data_gb | Number | Data used on that operator |
Error Responses
400 Bad Request
{ "success": false, "message": "Provide either iccid or esimId", "code": "MISSING_IDENTIFIER" }
Not supported for this eSIM:
{ "success": false, "message": "Usage reports are not available for this eSIM", "code": "NOT_SUPPORTED" }
403 Forbidden
{ "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" }
Example
const crypto = require('crypto');
const { v4: uuidv4 } = require('uuid');
async function getUsageReport(iccid, days = 7) {
const accessCode = 'esf_your_access_code';
const secretKey = 'sk_your_secret_key';
const body = JSON.stringify({ iccid, days });
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/usage-report', {
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) {
console.log(`${data.data.summary.total_data_gb} GB over ${data.data.period_days} days`);
} else {
console.error(`Usage report failed: ${data.message}`);
}
return data;
}
Notes
- Reports cover the last
daysdays (max 90). Data is reported per UTC day. avg_dailyis averaged over days that had usage, not the full window.- If the eSIM has not connected yet, totals are
0and the breakdowns are empty.