Orders
Retrieve your order history with detailed filtering and search options.
Endpoint
GET /api/v1/business/orders
AI prompt — Orders
Paste into ChatGPT, Claude, Cursor, Copilot or any coding agent to generate this part of your integration. Built-in recommendation: Incremental daily reconciliation with from_date and limit=100; never poll to confirm an order.
Show prompt text (47 lines)
# eSIMfly Business API — Orders (GET /orders) — prompt for AI coding assistants
TASK: use order history for FINANCE RECONCILIATION and support search — not to learn whether an order
succeeded (the Create Order / Topup Order response already told you). Incremental daily pulls only.
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/orders?page=1&limit=100&status=completed&from_date=2026-09-01T00:00:00Z&to_date=2026-09-02T00:00:00Z&sort_by=created_at&sort_order=asc
Query: page (default 1), limit (default 20, max 100), status = all|pending|completed|failed|cancelled,
from_date / to_date (ISO 8601, inclusive), search (order_reference | package_name | package_code),
sort_by = created_at|amount|status, sort_order = asc|desc.
RESPONSE 200
{ success: true, data: {
orders: [{ id, order_reference, package_name, package_code, amount, currency, status, flag_url, created_at,
esim: { iccid, imsi, msisdn, sim_status, esim_status, profile_status, unlimited, total_volume, total_duration, expired_time } | null }],
summary: { total_orders, total_revenue }, // completed orders in your account currency
pagination: { page, limit, total, total_pages } } }
Only orders in your account currency are returned. status: pending | completed | failed | cancelled.
INTEGRATION PATTERN
1. Daily reconciliation job: from_date = last successful run, to_date = now, status=all, limit=100,
sort_by=created_at asc; page through at 1 req/s; upsert by order_reference into our orders table and
flag any eSIMfly order we have no local record for (and vice-versa) for an admin to review.
A reseller doing 500 orders/day needs ~5 requests/day for this.
2. Support search: GET /orders?search=<order_reference or package name>&limit=20 when an agent searches.
3. Never poll /orders after placing an order; never use it to build customer dashboards — read our DB.
4. Monthly statement: use summary.total_orders / total_revenue from a from_date/to_date query, one call.
5. Store `currency` with every amount; do not assume USD.
DELIVERABLE: listOrders(params) in the shared client, the incremental daily reconciliation job with
mismatch reporting, and the support search.
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 |
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| page | Integer | 1 | Page number for pagination |
| limit | Integer | 20 | Number of results per page (max 100) |
| status | String | all | Filter by order status: "all", "pending", "completed", "failed", "cancelled" |
| from_date | String | - | Filter orders from this date (ISO 8601 format) |
| to_date | String | - | Filter orders until this date (ISO 8601 format) |
| search | String | - | Search in order_reference, package_name, or package_code |
| sort_by | String | created_at | Sort field: "created_at", "amount", "status" |
| sort_order | String | desc | Sort direction: "asc" or "desc" |
Response
Success Response (200 OK)
USD User Example:
{
"success": true,
"data": {
"orders": [
{
"id": 12345,
"order_reference": "ES-1234567890-ABC",
"package_name": "United States 1GB 7Days",
"package_code": "PHAJHEAYP",
"amount": 1.44,
"currency": "USD",
"status": "completed",
"flag_url": "/img/flags/US.png",
"created_at": "2024-01-15T10:30:00Z",
"esim": {
"iccid": "8948010010036785060",
"imsi": "260010185757766",
"msisdn": "48267753430",
"sim_status": "AFFECTED",
"esim_status": "Assigned (Not Installed)",
"profile_status": null,
"unlimited": false,
"total_volume": 1073741824,
"total_duration": 7,
"expired_time": "2026-08-24T17:00:31.884Z"
}
},
{
"id": 12346,
"order_reference": "ES-1234567891-DEF",
"package_name": "Europe Regional 5GB 30Days",
"package_code": "EUROP5GB30",
"amount": 5.50,
"currency": "USD",
"status": "completed",
"flag_url": "/img/flags/EU.png",
"created_at": "2024-01-14T15:45:00Z"
}
],
"summary": {
"total_orders": 156,
"total_revenue": 1234.56
},
"pagination": {
"page": 1,
"limit": 20,
"total": 156,
"total_pages": 8
}
}
}
IQD User Example:
{
"success": true,
"data": {
"orders": [
{
"id": 12347,
"order_reference": "ES-1234567892-GHI",
"package_name": "Iraq 2GB 15Days",
"package_code": "IRQ2GB15",
"amount": 6600,
"currency": "IQD",
"status": "completed",
"flag_url": "/img/flags/IQ.png",
"created_at": "2024-01-15T10:30:00Z"
}
],
"summary": {
"total_orders": 25,
"total_revenue": 165000
},
"pagination": {
"page": 1,
"limit": 20,
"total": 25,
"total_pages": 2
}
}
}
Response Fields
| Field | Type | Description |
|---|---|---|
| success | Boolean | Request success status |
| data.orders | Array | List of order objects |
| data.summary | Object | Summary statistics |
| data.pagination | Object | Pagination information |
Order Object Fields
| Field | Type | Description |
|---|---|---|
| id | Integer | Order ID |
| order_reference | String | Unique order reference |
| package_name | String | eSIM package name |
| package_code | String | Package code |
| amount | Number | Order amount in user's preferred currency |
| currency | String | Order currency: USD or IQD, or EUR for an enterprise account |
| status | String | Order status |
| flag_url | String | Country flag image URL |
| created_at | String | Order creation timestamp (ISO 8601) |
| esim | Object/null | eSIM details for this order (null if no eSIM is linked, e.g. balance top-ups) |
eSIM Object Fields
| Field | Type | Description |
|---|---|---|
| iccid | String/null | eSIM ICCID number |
| imsi | String/null | IMSI of the eSIM profile |
| msisdn | String/null | The profile's home number (MSISDN) — for eSIMfly-network eSIMs a roaming-hub number (+48 prefix) regardless of where the eSIM is used |
| sim_status | String/null | Provider SIM resource status (e.g. AFFECTED = assigned, FREE = released). Not an SM-DP+ status. |
| esim_status | String/null | Human-readable lifecycle label: New, Assigned (Not Installed), Installed, Active, Not Active |
| profile_status | String/null | eSIM profile (BPP) install status (e.g. Enable, Disable) |
| unlimited | Boolean | Whether the plan has unlimited data |
| total_volume | Number/null | Total data in bytes (e.g. 1073741824 = 1 GB) |
| total_duration | Number/null | Validity in days |
| expired_time | String/null | Expiry date (ISO 8601) |
Summary Object Fields
| Field | Type | Description |
|---|---|---|
| total_orders | Integer | Total completed orders count |
| total_revenue | Number | Total revenue from completed orders in user's preferred currency |
Pagination Object Fields
| Field | Type | Description |
|---|---|---|
| page | Integer | Current page number |
| limit | Integer | Items per page |
| total | Integer | Total number of orders |
| total_pages | Integer | Total number of pages |
Examples
Get Recent Orders
const crypto = require('crypto');
const { v4: uuidv4 } = require('uuid');
async function getRecentOrders() {
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();
const response = await fetch('https://esimfly.net/api/v1/business/orders', {
headers: {
'RT-AccessCode': accessCode,
'RT-RequestID': requestId,
'RT-Timestamp': timestamp,
'RT-Signature': signature
}
});
const data = await response.json();
console.log(`Found ${data.data.orders.length} orders`);
}
Search Orders by Package
const queryParams = new URLSearchParams({
search: 'United States',
limit: 50,
sort_by: 'created_at',
sort_order: 'desc'
});
const response = await fetch(
`https://esimfly.net/api/v1/business/orders?${queryParams}`,
{
headers: generateHMACHeaders() // Your HMAC function
}
);
Filter Orders by Date Range
const queryParams = new URLSearchParams({
from_date: '2024-01-01T00:00:00Z',
to_date: '2024-01-31T23:59:59Z',
status: 'completed',
limit: 100
});
const response = await fetch(
`https://esimfly.net/api/v1/business/orders?${queryParams}`,
{
headers: generateHMACHeaders()
}
);
Get Failed Orders
const queryParams = new URLSearchParams({
status: 'failed',
sort_by: 'created_at',
sort_order: 'desc'
});
const response = await fetch(
`https://esimfly.net/api/v1/business/orders?${queryParams}`,
{
headers: generateHMACHeaders()
}
);
Paginate Through Orders
async function getAllOrders() {
let page = 1;
let allOrders = [];
let hasMore = true;
while (hasMore) {
const queryParams = new URLSearchParams({
page: page.toString(),
limit: '100'
});
const response = await fetch(
`https://esimfly.net/api/v1/business/orders?${queryParams}`,
{
headers: generateHMACHeaders()
}
);
const data = await response.json();
allOrders = allOrders.concat(data.data.orders);
hasMore = page < data.data.pagination.total_pages;
page++;
}
return allOrders;
}
Python Example
import hashlib
import hmac
import time
import uuid
import requests
from datetime import datetime, timedelta
def get_orders_last_7_days():
access_code = 'esf_your_access_code'
secret_key = 'sk_your_secret_key'
# Generate HMAC headers
timestamp = str(int(time.time() * 1000))
request_id = str(uuid.uuid4())
sign_data = timestamp + request_id + access_code
signature = hmac.new(
secret_key.encode('utf-8'),
sign_data.encode('utf-8'),
hashlib.sha256
).hexdigest().upper()
headers = {
'RT-AccessCode': access_code,
'RT-RequestID': request_id,
'RT-Timestamp': timestamp,
'RT-Signature': signature
}
# Get orders from last 7 days
from_date = (datetime.now() - timedelta(days=7)).isoformat() + 'Z'
params = {
'from_date': from_date,
'status': 'completed',
'limit': 100
}
response = requests.get(
'https://esimfly.net/api/v1/business/orders',
headers=headers,
params=params
)
data = response.json()
print(f"Orders in last 7 days: {data['data']['pagination']['total']}")
print(f"Total revenue: ${data['data']['summary']['total_revenue']}")
Order Status Values
| Status | Description |
|---|---|
| pending | Order created but payment not confirmed |
| completed | Order successfully completed and eSIM delivered |
| failed | Order failed due to payment or provisioning issue |
| cancelled | Order cancelled by user or system |
Filtering and Sorting
Date Filtering
- Use ISO 8601 format for dates (e.g., "2024-01-15T10:30:00Z")
from_dateis inclusiveto_dateis inclusive- Both dates are optional and can be used independently
Search Functionality
- Searches across order_reference, package_name, and package_code
- Case-insensitive search
- Partial matches are supported
Sorting Options
sort_by: Choose from "created_at", "amount", or "status"sort_order: Use "asc" for ascending or "desc" for descending- Default: sorted by created_at in descending order (newest first)
Error Responses
400 Bad Request
Invalid request ID format:
{
"success": false,
"error": "Invalid or missing RT-RequestID header. Must be a valid UUID v4.",
"code": "INVALID_REQUEST_ID"
}
401 Unauthorized
Missing authentication:
{
"success": false,
"error": "Authentication required",
"message": "Please provide either Bearer token or complete HMAC signature authentication"
}
Invalid API key:
{
"success": false,
"error": "Invalid API key",
"code": "INVALID_API_KEY"
}
403 Forbidden
Not a business account:
{
"success": false,
"error": "Invalid user or not a business account",
"code": "INVALID_USER"
}
500 Internal Server Error
{
"success": false,
"error": "Failed to fetch orders"
}
Rate Limiting
This endpoint is subject to the standard rate limit of 1000 requests per hour. Rate limit information is included in response headers:
X-RateLimit-Limit: Maximum requests allowedX-RateLimit-Remaining: Requests remainingX-RateLimit-Reset: Time when the limit resets
Notes
- Currency Filtering: Only orders in your preferred currency are returned
- Multi-Currency Support: USD users see only USD orders, IQD users see only IQD orders
- Currency Preference: Set your preferred currency in the business dashboard settings
- Only your own orders are returned
- Summary statistics only include completed orders in your preferred currency
- Maximum 100 orders can be returned per request
- Use pagination to retrieve all orders
- The
flag_urlfield may be null for some orders - Consider caching order data for reporting purposes