# 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=&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.