Get Topup Packages
Retrieve available top-up packages for a specific eSIM with your pricing.
Endpoint
GET /api/v1/business/topup/packages
AI prompt — Get Topup Packages
Paste into ChatGPT, Claude, Cursor, Copilot or any coding agent to generate this part of your integration. Built-in recommendation: Call only when the customer opens the top-up screen; cache per ICCID for 10 minutes; never pre-fetch for all eSIMs.
Show prompt text (46 lines)
# eSIMfly Business API — Get Topup Packages (GET /topup/packages) — prompt for AI coding assistants
TASK: fetch the top-up options for ONE eSIM when the customer opens the top-up screen. Top-up
packages are eSIM-specific (they depend on the eSIM's provider and location), so they cannot be
synced in bulk like the main catalogue — but they must not be pre-fetched for every eSIM either.
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/topup/packages?iccid=<iccid>&page=1&limit=100
Query: iccid (REQUIRED), page (default 1), limit (default 50, max 100).
RESPONSE 200
{ "success": true, "data": { "packages": [
{ "package_code": "TOPUP_PXOO225PI", "name": "Iraq 3GB 30Days", "data_amount_gb": 3, "validity_days": 30,
"cost": 10.56, "currency": "USD", "features": { "is_rechargeable": true }, "is_unlimited": false } ],
"pagination": { "page": 1, "limit": 100, "total": 8, "total_pages": 1 } } }
package_code here is what you pass to POST /topup/order. cost = your buy price.
ERRORS
400 MISSING_ICCID; 400 ESIM_NOT_TOPPABLE ("Current status: EXPIRED" — only ACTIVE, DEPLETED, USED_EXPIRED,
or NEW for eSIMfly-provided eSIMs can be topped up); 403 ESIM_ACCESS_DENIED (not your eSIM); 500.
INTEGRATION PATTERN
1. Call ONLY when a customer (or support agent) opens the top-up screen for a specific eSIM.
2. Cache the result per ICCID for ~10 minutes (memory/Redis) so refreshes and back-navigation don't re-call.
3. Never iterate over all eSIMs to pre-load top-up options, and never put this in a cron.
4. Apply our margin to cost for display; pass the exact package_code to POST /topup/order.
5. Treat ESIM_NOT_TOPPABLE as a normal UI state ("this eSIM can't be topped up"), not as an exception.
6. One page with limit=100 is enough in practice; only paginate if total_pages > 1.
DELIVERABLE: getTopupPackages(iccid) with a 10-minute per-ICCID cache, and the top-up screen data loader.
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 | Required | Description |
|---|---|---|---|
| iccid | String | Yes | eSIM ICCID to get compatible topup packages |
| page | Integer | No | Page number for pagination (default: 1) |
| limit | Integer | No | Number of results per page (default: 50, max: 100) |
Response
Success Response (200 OK)
USD User Example:
{
"success": true,
"data": {
"packages": [
{
"package_code": "TOPUP_PXOO225PI",
"name": "Iraq 3GB 30Days",
"data_amount_gb": 3,
"validity_days": 30,
"cost": 10.56,
"currency": "USD",
"features": {
"is_rechargeable": true
},
"is_unlimited": false
},
{
"package_code": "turkey-7days-1gb-topup",
"name": "Turkey 1GB 7Days",
"data_amount_gb": 1,
"validity_days": 7,
"cost": 2.45,
"currency": "USD",
"features": {
"is_rechargeable": true
},
"is_unlimited": false
}
],
"pagination": {
"page": 1,
"limit": 50,
"total": 8,
"total_pages": 1
}
}
}
IQD User Example:
{
"success": true,
"data": {
"packages": [
{
"package_code": "TOPUP_PXOO225PI",
"name": "Iraq 3GB 30Days",
"data_amount_gb": 3,
"validity_days": 30,
"cost": 13939,
"currency": "IQD",
"features": {
"is_rechargeable": true
},
"is_unlimited": false
},
{
"package_code": "turkey-7days-1gb-topup",
"name": "Turkey 1GB 7Days",
"data_amount_gb": 1,
"validity_days": 7,
"cost": 3234,
"currency": "IQD",
"features": {
"is_rechargeable": true
},
"is_unlimited": false
}
],
"pagination": {
"page": 1,
"limit": 50,
"total": 8,
"total_pages": 1
}
}
}
Package Fields
| Field | Type | Description |
|---|---|---|
| package_code | String | Topup package identifier (use this for topup operations) |
| name | String | Package display name |
| data_amount_gb | Number | Data allowance in GB |
| validity_days | Integer | Validity period in days |
| cost | Number | Your cost price in user's preferred currency |
| currency | String | Currency code based on the account: USD or IQD, or EUR for an enterprise account |
| features | Object | Package features object |
| features.is_rechargeable | Boolean | Always true for topup packages |
| is_unlimited | Boolean | Unlimited data flag |
Examples
Get Topup Packages for Specific eSIM
const queryParams = new URLSearchParams({
iccid: '8943108170003135816',
limit: 20
});
const response = await fetch(
`https://esimfly.net/api/v1/business/topup/packages?${queryParams}`,
{
headers: generateHMACHeaders() // Your HMAC function
}
);
const data = await response.json();
console.log(`Found ${data.data.packages.length} topup packages`);
With Pagination
const queryParams = new URLSearchParams({
iccid: '8943108170003135816',
page: 1,
limit: 10
});
const response = await fetch(
`https://esimfly.net/api/v1/business/topup/packages?${queryParams}`,
{
headers: generateHMACHeaders()
}
);
Error Responses
400 Bad Request
Missing ICCID parameter:
{
"success": false,
"error": "ICCID parameter is required",
"message": "Topup packages are specific to an eSIM. Please provide the ICCID parameter.",
"code": "MISSING_ICCID"
}
400 Bad Request
eSIM cannot be topped up due to status:
{
"success": false,
"error": "eSIM cannot be topped up. Current status: EXPIRED",
"message": "Only ACTIVE, DEPLETED, or USED_EXPIRED eSIMs can be topped up (NEW is also allowed for esimfly eSIMs)",
"code": "ESIM_NOT_TOPPABLE"
}
Status comparison is case-insensitive (ACTIVE, Active, and active are all accepted). eSIMs in NEW status can also be topped up when the eSIM is provided by eSIMfly.
403 Forbidden
eSIM not found or access denied:
{
"success": false,
"error": "eSIM not found or access denied",
"code": "ESIM_ACCESS_DENIED"
}
401 Unauthorized
See Packages endpoint for common authentication errors.
500 Internal Server Error
{
"success": false,
"error": "Failed to fetch top-up packages"
}
Important Notes
Multi-Currency Pricing
- Pricing Display: Topup prices are shown in your account currency (
USD,IQD, orEURfor enterprise accounts) - Currency Conversion: IQD prices are converted using real-time exchange rates
- Currency Preference: Set your preferred currency in the business dashboard settings
- Format: USD prices show 2 decimals, IQD prices are whole numbers
Provider-Agnostic Response
- Package codes are cleaned and standardized
- Different package code formats are used depending on the provider
- All provider-specific handling is done automatically
Package Availability
- Topup packages are eSIM-specific - each eSIM has different available options
- Packages are automatically filtered by the eSIM's location
- Only compatible topup packages for that specific eSIM are returned
Security
- Users can only access topup packages for eSIMs they own
- ICCID ownership is verified for each request
- All requests are logged and monitored
Integration Tips
- Always specify ICCID: This endpoint requires the specific eSIM identifier
- Use returned package_code: Use the exact
package_codefrom response for topup operations - Automatic handling: The API handles all backend complexity automatically
- Pagination: Use pagination for eSIMs with many topup options
- Error handling: Always handle the case where no topup packages are available
Relationship to Other Endpoints
- Use with Get eSIMs to get ICCIDs
- Use
package_codefrom this endpoint with topup operations - Pricing matches your account's profit margin settings