Skip to main content

Orders

Retrieve your order history with detailed filtering and search options.

Endpoint​

GET /api/v1/business/orders

AI prompt — Orders

Open raw .txt

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.

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​

ParameterTypeDefaultDescription
pageInteger1Page number for pagination
limitInteger20Number of results per page (max 100)
statusStringallFilter by order status: "all", "pending", "completed", "failed", "cancelled"
from_dateString-Filter orders from this date (ISO 8601 format)
to_dateString-Filter orders until this date (ISO 8601 format)
searchString-Search in order_reference, package_name, or package_code
sort_byStringcreated_atSort field: "created_at", "amount", "status"
sort_orderStringdescSort 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​

FieldTypeDescription
successBooleanRequest success status
data.ordersArrayList of order objects
data.summaryObjectSummary statistics
data.paginationObjectPagination information

Order Object Fields​

FieldTypeDescription
idIntegerOrder ID
order_referenceStringUnique order reference
package_nameStringeSIM package name
package_codeStringPackage code
amountNumberOrder amount in user's preferred currency
currencyStringOrder currency: USD or IQD, or EUR for an enterprise account
statusStringOrder status
flag_urlStringCountry flag image URL
created_atStringOrder creation timestamp (ISO 8601)
esimObject/nulleSIM details for this order (null if no eSIM is linked, e.g. balance top-ups)

eSIM Object Fields​

FieldTypeDescription
iccidString/nulleSIM ICCID number
imsiString/nullIMSI of the eSIM profile
msisdnString/nullThe profile's home number (MSISDN) — for eSIMfly-network eSIMs a roaming-hub number (+48 prefix) regardless of where the eSIM is used
sim_statusString/nullProvider SIM resource status (e.g. AFFECTED = assigned, FREE = released). Not an SM-DP+ status.
esim_statusString/nullHuman-readable lifecycle label: New, Assigned (Not Installed), Installed, Active, Not Active
profile_statusString/nulleSIM profile (BPP) install status (e.g. Enable, Disable)
unlimitedBooleanWhether the plan has unlimited data
total_volumeNumber/nullTotal data in bytes (e.g. 1073741824 = 1 GB)
total_durationNumber/nullValidity in days
expired_timeString/nullExpiry date (ISO 8601)

Summary Object Fields​

FieldTypeDescription
total_ordersIntegerTotal completed orders count
total_revenueNumberTotal revenue from completed orders in user's preferred currency

Pagination Object Fields​

FieldTypeDescription
pageIntegerCurrent page number
limitIntegerItems per page
totalIntegerTotal number of orders
total_pagesIntegerTotal 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​

StatusDescription
pendingOrder created but payment not confirmed
completedOrder successfully completed and eSIM delivered
failedOrder failed due to payment or provisioning issue
cancelledOrder cancelled by user or system

Filtering and Sorting​

Date Filtering​

  • Use ISO 8601 format for dates (e.g., "2024-01-15T10:30:00Z")
  • from_date is inclusive
  • to_date is 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 allowed
  • X-RateLimit-Remaining: Requests remaining
  • X-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_url field may be null for some orders
  • Consider caching order data for reporting purposes