{"activeVersionTag":"latest","latestAvailableVersionTag":"latest","collection":{"info":{"_postman_id":"cc0390ba-b1ae-4861-b8ff-6fe3bdc1329b","name":"Nomad eSIMfx API Doc","description":"## eSIMfx API: Reselling eSIM has never been easier\n\nThis document provides comprehensive guidance on integrating and using the eSIMfx API to seamlessly embed global eSIM connectivity services into your applications.\n\n## Core Capabilities\n\nThe eSIMfx API offers a robust suite of endpoints that give you full programmatic control over the eSIM lifecycle and associated services.\n\n**Key functionalities include:**\n\n- **Authentication & Profile Management:** Securely authenticate and retrieve your reseller profile details.\n    \n- **Product & Catalogue Management:** Access a global catalogue of eSIM data plans and top-up products to build your offerings.\n    \n- **End-to-End Order Management:** Create orders, automatically provision eSIMs, and bind data packages to them in a single, streamlined process. The API supports idempotent requests to ensure reliable order processing.\n    \n- **Active eSIM Lifecycle Control**: Manage subscriptions post-activation with capabilities to activate, terminate, or block eSIMs based on your business rules.\n    \n- **Comprehensive Reporting & Monitoring**: Retrieve detailed information on orders, check the status of individual eSIMs, and view all orders associated with a specific eSIM for full visibility.\n    \n\n## Key Features & Benefits\n\nBy leveraging the eSIMfx API, you can accelerate your time-to-market and maintain complete customization over your service.\n\n- **Global Network Access**: Access to 1,000+ networks in 200+ destinations.\n    \n- **Zero Financial Risk**: Prepaid system with bundled data packs ensures no overages or hidden charges.\n    \n- **Rapid Deployment**: Easy to integrate with existing platforms and applications. Launch your own eSIM services in days, not months.\n    \n- **Complete Control**: You control the branding, pricing, and customer experience.\n    \n- **Scalability**: Built to handle growing demand and large-scale deployments.\n    \n- **Reliable Infrastructure**: Enterprise-grade security and performance\n    \n\n# Quick Start: Order Your First eSIM\n\nThis guide walks you through the most common use case: authenticating with our API, browsing available packages, placing an order, and monitoring your eSIM status. By following these steps, you'll successfully complete your first eSIM order!\n\n**Before you can get started with this guide:**\n\n- Please [contact us](https://esimfx.com/contact-us/) to create a eSIMfx portal account\n    \n- You can log in to your account to get your client id and client key (Available in Reseller > Client ID, and Client Key.) You can use `/account/api/v1/auth` to get API Access Token with your client ID and Key.\n    \n- Sufficient account balance (We will issue an initial test amount when create your account)\n    \n\n## Overview\n\nEverything starts with travelers and their connectivity needs. In this guide, we'll follow an example scenario:\n\n> Sarah, a digital nomad, is traveling from San Francisco to Tokyo for a 1-week business trip. She needs reliable mobile data immediately upon arrival for navigation, work emails, and staying connected with her team back home. She wants a data package that covers Japan with the option to extend if needed. \n  \n\nTo complete this scenario, we'll be:\n\n1. **Selecting the right data package** for her 1-week stay\n    \n2. **Creating an order** and assigning the eSIM to her device\n    \n3. **Monitoring her data usage** throughout the trip\n    \n4. **Top Up to an eSIM**\n    \n\n## Step 1: Browse Available Packages for Japan\n\nFirst, let's search for available eSIM packages that cover Japan and match Sarah's 1-week trip duration.\n\n**Endpoint**: GET `/product/api/v1/get_products`\n\nThis API is used to get all products. The output can be filtered on `countries`, `region`. When both `countries` and `region` have values, only region takes effect.\n\nYou can use the `page_start` and `page_size` fields to perform paging operations. When `last_evaluated_key` has a value, it means there is a next page.\n\n**Request example**:\n\n``` json\n{\n  \"page_start\": {},\n  \"page_size\": 10,\n  \"countries\": \"JP\"\n}\n\n ```\n\n**Response Example**:\n\n``` json\n{\n  \"code\": 0,\n  \"message\": \"Success\",\n  \"data\": {\n    \"products\": [\n      {\n        \"id\": \"ca7e9da3-ca97-47cc-9d40-a77610c2xxxx\", // product id\n        \"name\": \"japan_10GB_7Day\",\n        \"duration\": 7,\n        \"duration_unit\": \"DAY\",\n        \"amount\": 10,\n        \"amount_unit\": \"GB\",\n        \"coverage\": [\n          \"JP\"\n        ],\n        \"networks\": [\n          {\n            \"mccmnc\": \"44020\",\n            \"name\": \"SOFTBANK\",\n            \"speed\": \"5G\"\n          },\n          {\n            \"mccmnc\": \"44051\",\n            \"name\": \"KDDI au\",\n            \"speed\": \"5G\"\n          }\n        ],\n        \"imsi_profile\": \"Green\",\n        \"price\": 12, \n        \"price_unit\": \"USD\",\n      }\n    ],\n    \"last_evaluated_key\": {}\n  }\n}\n\n ```\n\n## Step 2: Create the Order and Assign eSIM\n\nNow let's place the order and assign the eSIM to Sarah's device.\n\n**API Endpoint**: POST `/order/api/v1/create_order`\n\nThis API is used to create a new order or topup order.\n\nWhen creating a new order, you must fill in the fields `operation_type` and `product.id`, and the value of the `operation_type` field is `NEW`. It can automatically allocate a new eSIM and bind subscription.\n\n**Request example**:\n\n``` json\n{\n  \"operation_type\": \"NEW\",\n  \"product\": {\n    \"id\": \"ca7e9da3-ca97-47cc-9d40-a77610c2xxxx\"\n  }\n}\n\n ```\n\n**Response Example**:\n\n``` json\n{\n  \"code\": 0,\n  \"message\": \"Success\",\n  \"data\": {\n    \"id\": \"01b47ffa-4a74-4209-87e2-d282e274xxxx\", // order id\n    \"status\": \"COMPLETED\",\n    \"subscription\": {\n      \"upper_limit_amount\": 10737418240, \n      \"amount_unit\": \"Byte\", \n      \"status\": \"PENDING\", \n      \"activation_time\": \"2025-09-30T03:07:11Z\", \n      \"expiry\": \"2025-10-07T03:07:11Z\", \n      \"activate_by\": \"2025-09-30T03:07:11Z\" \n    },\n    \"creation_time\": \"2025-08-01T03:07:11Z\",\n    \"esim\": {\n      \"iccid\": \"89440000000000000000\", // ICCID of the purchases eSIM\n      \"esim_qr\": \"LPA:1$rsp.truphone.com$JQ-2D51JC-XXXXXX\", // LPA activation information\n      \"status\": \"PROVISIONED\"\n      }\n  }\n}\n\n ```\n\n## Step 3: Monitor Data Usage During the Trip\n\nThroughout her trip, Sarah can monitor her data usage to ensure she doesn't run out.\n\n### **Check Current eSIM Status**\n\n**API Endpoint**: GET `/order/api/v1/get_esim_status`\n\nThis API is used to get eSIM status by ICCID. Below are the common values you may see for eSIM status:\n\n- **Provisioned:** An eSIM will be in this state after a purchase has been made. This is the first status the eSIM will be in.\n    \n- **Active:** This tells you that the eSIM is currently in use.\n    \n- **Expired:** All of the data plans of the eSIM validity period have ended.\n    \n- **Blocked:** The eSIM profile has been permanently deactivated after being in the Expired state for 60 days.\n    \n\n**Request example**:\n\n``` json\n/order/api/v1/get_esim_status?iccid=89440000000000000000\n\n ```\n\n**Response Example**:\n\n``` json\n{\n  \"code\": 0,\n  \"message\": \"Success\",\n  \"data\": {\n    \"iccid\": \"89440000000000000000\",\n    \"esim_qr\": \"LPA:1$rsp.truphone.com$JQ-2D1JE2-XXXXXX\",\n    \"status\": \"PROVISIONED\"\n  }\n}\n\n ```\n\n### **Check Detailed Package Usage**\n\n**API Endpoint**: GET `/order/api/v1/get_order`\n\nThis API is used to get order details by order id. You can know the real time subscription status as below:\n\n- **Subscription Upper Limit Amount:** Amount of data allocated to the subscription.\n    \n- **Subscription Used Amount:** Amount of data consumed by the end user to-date.\n    \n- **Subscription Amount Unit:** This is the unit measure of data, typically GB, but may also be MB, and for Unlimited Plans would be Days.\n    \n- **Subscription Activation Time:** Timestamp (in UTC) when the eSIM first connected to an eligible network in the destination country.\n    \n- **Subscription Expiry:**\n    \n    - For an eSIM whose subscription has not yet been activated: Timestamp (in UTC) when the eSIM is set to expire after order creation.\n        \n    - For an eSIM whose subscription has been activated: Timestamp (in UTC) when the subscription is set to expire, which should equal Activation Time + Package Validity.\n        \n    - For an eSIM whose subscription has already expired: Timestamp (in UTC) when the subscription expired.\n        \n- **Subscription Status:** You will see 1 of 4 values on each Subscription:\n    \n    - **Pending:** This status means that the data plan is not yet activated.\n        \n    - **Active:** This status indicates that the data plan has been activated. Activation occurs when the eSIM connects to an eligible network at the destination or within 60 days from activation irrespective of the device being in the destination country or not (whichever comes first).\n        \n    - **Expired:** This status indicates that the data plan has expired naturally.\n        \n    - **Terminated:** This status indicates the data plan was terminated manually.\n        \n\n**Request example**:\n\n``` json\n/order/api/v1/get_order?order_id=ab9b30e5-4c83-49f8-bc12-e7c1a84cxxxx\n\n ```\n\n**Response Example**:\n\n``` json\n{\n  \"code\": 0,\n  \"message\": \"Success\",\n  \"data\": {\n    \"id\": \"01b47ffa-4a74-4209-87e2-d282e274xxxx\",// order id\n    \"iccid\": \"89440000000000000000\",\n    \"product\": {\n      \"id\": \"ca7e9da3-ca97-47cc-9d40-a77610c2xxxx\",\n      \"name\": \"japan_10GB_7Day\",\n      \"duration\": 7,\n      \"duration_unit\": \"DAY\",\n      \"imsi_profile\": \"Green\"\n    },\n    \"subscription\": {\n      \"upper_limit_amount\": 10737418240,\n      \"used_amount\": 0,\n      \"amount_unit\": \"Byte\",\n      \"activation_time\": \"2025-09-30T05:20:12Z\",\n      \"expiry\": \"2025-10-07T05:20:12Z\",\n      \"status\": \"PENDING\",\n      \"activate_by\": \"2025-09-30T05:20:12Z\"\n    },\n    \"status\": \"COMPLETED\",\n    \"creation_time\": \"2025-09-24T05:20:12Z\"\n  }\n}\n\n ```\n\n## Step 4: Top Up to an eSIM\n\nAfter Sarah finished her business trip in Japan, she decided to spend another week in Japan for a good vacatioin. Now, she would like to top up another 10 GB / 7 days on her eSIM.\n\n### **Check Avaliable Top Up Product**\n\n**API Endpoint**: GET `product/api/v1/get_available_topups`\n\nBefore create a top-up order, we suggest calling the `get_avaliable_topup` endpoint to get avaliable topup products list before create the top up order. Because only products with the same imsi_profile field in the same region or coverage can top up with each other.\n\n- The request should contains either product_id or iccid:\n    \n    - `product_id`: The current product id in using, OR\n        \n    - `ICCID`: The ICCID of the eSIM for which you want to top up\n        \n- The response will contains a list of all avaliable products to top up on current product_id or ICCID\n    \n\n**Request example**:\n\n``` curl\n/product/api/v1/get_available_topups?product_id=ca7e9da3-ca97-47cc-9d40-a77610c2xxxx&iccid=89440000000000000000\n\n ```\n\n**Response Example**:\n\n``` json\n{\n  \"code\": 0,\n  \"message\": \"Success\",\n  \"data\": {\n    \"products\": [\n      {\n        \"id\": \"ca7e9da3-ca97-47cc-9d40-a77610c2xxxx\", \n        \"name\": \"Japan_10GB_7Day\", \n        \"duration\": 7, \n        \"duration_unit\": \"DAY\",\n        \"amount\": 10, \n        \"amount_unit\": \"GB\", \n        \"coverage\": [  \n        ],\n        \"networks\": [ \n          {\n            \"mccmnc\": \"44020\",\n            \"name\": \"SOFTBANK\",\n            \"speed\": \"5G\"\n          },\n          {\n            \"mccmnc\": \"44051\",\n            \"name\": \"KDDI au\",\n            \"speed\": \"5G\"\n          }\n        ],\n        \"imsi_profile\": \"Green\",\n        \"price\": 12, \n        \"price_unit\": \"USD\",\n        }\n      }\n    ]\n  }\n}\n\n ```\n\n### **Create Top Up Order**\n\n**API Endpoint**: POST `/order/api/v1/create_order`\n\nThis API is also used to create a topup order to an existing eSIM\n\n- Select from the displayed avaliable Top Up packages get from the `get_available_topups` , Sarah choose to keep top 10 GB / 7Days plan to her eSIM.\n    \n- You would call this `create_order` endpoint with `operation_type: \"TOPUP\"`, the existing **`iccid`**, and the selected `product.id`.\n    \n\n**Request example**:\n\n``` json\n{\n  \"operation_type\": \"TOPUP\", \n  \"iccid\" : \"89440000000000000000\", \n  \"product\": {\n    \"id\": \"ca7e9da3-ca97-47cc-9d40-a77610c2xxxx\" \n  }\n\n ```\n\n**Response Example**:\n\n``` json\n{\n  \"code\": 0,\n  \"message\": \"Success\",\n  \"data\": {\n    \"id\": \"13bd78f-4a74-4873-87e2-d234y475xxxx\", // order id\n    \"status\": \"COMPLETED\",\n    \"subscription\": {\n      \"upper_limit_amount\": 10737418240, \n      \"amount_unit\": \"Byte\", \n      \"status\": \"PENDING\", \n      \"activation_time\": \"2025-10-08T03:07:11Z\", \n      \"expiry\": \"2025-10-14T03:07:11Z\", \n      \"activate_by\": \"2025-10-08T03:07:11Z\"\n    },\n    \"creation_time\": \"2025-08-01T03:07:11Z\",\n    \"esim\": {\n      \"iccid\": \"89440000000000000000\", // ICCID of the purchases eSIM\n      \"esim_qr\": \"LPA:1$rsp.truphone.com$JQ-2D51JC-XXXXXX\", // LPA activation information\n      \"status\": \"ACTIVE\"\n      }\n  }\n}\n\n ```\n\n# **AI-Readable Project Context** file\n\n## **Overview**\n\nTo help you integrate the eSIMfx API faster, we have created an **AI-Readable Project Context** file. Large Language Models (LLMs) and AI coding assistants (like Cursor, GitHub Copilot, ChatGPT, or Claude) are great at writing code, but they often lack specific business logic or API constraints, leading to hallucinations.\n\nThis `.md` file is specifically structured to teach your AI exactly how our API works. It includes our mandatory workflows, idempotency rules, data usage calculations, and top-up constraints so your AI generates production-ready code on the first try.\n\n## **How to Use This Context File**\n\n1. **Download the Context File:** Download the `Nomad eSIMfx Project Context.md` file provided in this section.\n    \n2. **Export the Postman Collection:** Export our complete API documentation as a JSON file (`Nomad eSIMfx API Doc.json`) from Postman.\n    \n3. **Provide Context to Your AI:** Upload both the `.md` context file and the `.json` Postman collection to your AI assistant.\n    \n4. **Prompt the AI:** Ask your AI to build your integration. Be sure to provide it with your specific framework (e.g., Node.js, Python, React) and your Sandbox credentials (`baseUrl`, `client_id`, `client_key`).\n    \n\n## Nomad eSIMfx Project Context.md\n\n``` markdown\n---\ndescription: Context, integration rules, and core workflows for the eSIMfx Reseller API.\nglobs: [\"**/*.ts\", \"**/*.js\", \"**/*.py\", \"**/*.go\", \"**/*.java\", \"**/*.php\"]\nDisclaimer: This AI-readable project context file is intended as a reference to accelerate API integration when using AI coding assistants. While it significantly reduces development effort, provisioning eSIMs and executing orders involve real financial transactions and monetary impacts. Before deploying any integration to a production environment, human developers MUST conduct thorough code reviews, security audits, and extensive edge-case testing. Nomad eSIMfx assumes no liability for unauthorized charges, logical errors, or integration flaws caused by AI-generated code.\n---\n# eSIMfx API Integration Instructions\nThis document provides the foundational context, endpoints, and business rules for integrating with the eSIMfx Reseller API. When generating API clients, writing integration logic, or designing workflows, you MUST adhere strictly to the constraints defined below. \nThe eSIMfx API enables programmatic control over the entire eSIM lifecycle, including purchasing data plans, provisioning eSIMs, managing top-ups, and handling subscriptions.\n## 1. Global API Conventions\n* **Disclaimer:** Before starting, display **Disclaimer** for human to read first.\n* **Full API Document:** Before starting, ask human to send the `Nomad eSIMfx API Doc.json` to you. Tell them they can Import Collection `Nomad eSIMfx API Doc` to their own postman workspace, and click `Export Collections` to get the a `Nomad eSIMfx API Doc.json` file. \n* **Base URL:** Before starting, ask human to input the `{{baseUrl}}` to you. Tell them they can get the `{{baseUrl}}` in eSIMfx portal > Reseller tab > API domain\n* **Authentication:** All endpoints except Auth require an access token passed in the `Authorization` header.\n* **Token Retrieval:** Call `POST /account/api/v1/auth` with `client_id` and `client_key`. When need `client_id` and `client_key`, ask human to input these to you. Tell them they can get the `{{baseUrl}}` in eSIMfx portal > Reseller tab > `client_id` and `client_key`.\n* **Token Expiry:** Tokens are valid for exactly 1 hour. \n* **Standard Response Format:** All endpoints return a JSON object containing `code`, `message`, and `data`. \n* **Success Condition:** Always verify that `code === 0` before processing the `data` payload.\n* **Pagination:** Endpoints returning lists use `page_start` (mapping to `last_evaluated_key`) and `page_size`.\n* **Pagination Continuation:** If the `last_evaluated_key` in the response is not an empty object, it signifies a next page exists.\n---\n## 2. Extended Integration Workflows for AI Context\nThis section defines the exact API call sequences and data extraction rules for common user journeys. When implementing these flows, the AI MUST follow the prescribed sequence and payload structures.\n## Flow A: Display/Search Available Products by Destination for User to select\n### Execution Sequence\n1. **Query Catalog:** Call `POST /product/api/v2/get_products` to fetch the product catalog filtered by the desired destination.\n   * **Payload:** `{\"countries\": \"<ISO_CODES>\", \"page_start\": {}, \"page_size\": 20}` (e.g., `\"countries\": \"US,CA\"`).\n2. **Extraction for Frontend:** Iterate over the `data.products` array. Extract key fields for display: `price`, `amount`, `amount_unit`, `duration`, `duration_unit`, `networks`, and `is_unlimited`.\n3. **Pagination Handling:**\n   * Check the `data.last_evaluated_key` object.\n   * If it is NOT empty, store this object and pass it into `page_start` on the subsequent request to fetch the next page of results.\n## Flow B: Search for Specific Plan\n### Execution Sequence\n1. **Query Product Details:** Call `GET /product/api/v1/get_product?id=<PRODUCT_ID>` using the unique product identifier.\n2. **Extraction:** Retrieve the detailed plan payload from the `data` object. \n   * Extract key fields for display: `coverage`, `price`, `amount`, `amount_unit`, `duration`, `duration_unit`, `networks`, and `is_unlimited`.\n## Flow C: New eSIM Purchase\n### Execution Sequence\n1. **Fetch Catalog:** Call `POST /product/api/v2/get_products` to fetch available products. Use the V2 endpoint to get stable `esimfx_*` product IDs.\n2. **Create Order:** Call `POST /order/api/v1/create_order` to allocate a new eSIM hardware profile and bind the selected data subscription.\n   * **CRITICAL Header:** MUST include `X-Idempotency-Key: <UUID>`.\n   * **Payload:** `{\"operation_type\": \"NEW\", \"product\": {\"id\": \"esimfx_...\"}}`.\n### Extraction After Creation\n* **QR Code:** Extract the LPA string at `data.esim.esim_qr` (e.g., `LPA:1$rsp.truphone.com$...`) to pass to the frontend for QR code generation.\n* **ICCID:** Extract the assigned hardware identifier at `data.esim.iccid` to store in your database for future management.\n## Flow D: Top-Up Existing eSIM\n### Execution Sequence\n1. **Fetch Eligible Products:** Call `GET /product/api/v1/get_available_topups?iccid=<target_iccid>`. \n   * **Rule:** You MUST use this endpoint before topping up, as the system filters available products based on the existing eSIM's `imsi_profile` compatibility.\n2. **Create Order:** Call `POST /order/api/v1/create_order` to apply the selected top-up package to the eSIM.\n   * **CRITICAL Header:** MUST include `X-Idempotency-Key: <UUID>`.\n   * **Payload:** `{\"operation_type\": \"TOPUP\", \"iccid\": \"<target_iccid>\", \"product\": {\"id\": \"esimfx_...\"}}`.\n## Flow E: Check Data Used and Data Left by Current ICCID\n### Execution Sequence\n1. **Fetch Subscriptions:** Call `GET /order/api/v1/get_esim_orders?iccid=<target_iccid>` to retrieve all historical and active orders attached to the hardware.\n2. **Target Identification:** Iterate through the `data.orders` array to find the order with `subscription.status === \"ACTIVE\"` or `\"PENDING\"`.\n3. **Data Calculation:** * Extract `subscription.used_amount` and `subscription.upper_limit_amount`.\n   * Both values are returned in the unit specified by `subscription.amount_unit` (typically `Byte`).\n   * **Formula:** `Remaining Data = upper_limit_amount - used_amount`.\n## Flow F: End User Refund / Terminate Package\n### Execution Sequence\n1. **Trigger Termination:** Call `POST /order/api/v1/terminate_subscription`.\n   * **Payload:** `{\"order_id\": \"<target_order_id>\"}`.\n   * **Result:** Changes the specific subscription status to `TERMINATED`.\n2. **Refund Logic Verification:** Check the `data.refund.need_refund` flag in the responses of the above API calls. \n   * **Rule:** If the order was in `PENDING` status and the termination occurred within 60 days of order creation, eSIMfx automatically issues a refund and sets `need_refund` to `true`.\n## Flow G: Get eSIM Install QR Code Again\n### Execution Sequence\n1. **Query Hardware:** Call `GET /order/api/v1/get_esim_status?iccid=<target_iccid>` to retrieve the global eSIM status.\n2. **Extraction:** Locate `data.esim_qr` in the response object. \n   * Pass this LPA string (e.g., `LPA:1$rsp.truphone.com$...`) back to the frontend to regenerate the installation QR code if the user lost the original.\n## Flow H: User to Check All Packages on the eSIM\n### Execution Sequence\n1. **Fetch Subscriptions:** Call `GET /order/api/v1/get_esim_orders?iccid=<target_iccid>` to retrieve the full list of subscriptions linked to that eSIM hardware.\n2. **Process List:** Iterate through the `data.orders` array to display all historical and active packages to the end user.\n3. **Status Mapping:** Map the `subscription.status` field to the frontend UI. Statuses will be one of four values:\n   * `PENDING`: Not yet activated.\n   * `ACTIVE`: Currently in use.\n   * `EXPIRED`: Data exhausted or validity period has naturally ended.\n   * `TERMINATED`: Manually cancelled.\n## Flow I: Send Data Usage Notification to End Users (Webhook Integration)\n### Execution Sequence\n1. **Configure Webhook**: Set up a receiver endpoint on your server. Ask human to configure a new webhook with the Event Type `DATA_USAGE` and select your desired Data Usage Thresholds (e.g., 50%, 80%, 90%), In the eSIMfx portal.\n2. **Receive & Validate**: When a user's data consumption hits the threshold, your endpoint will receive a POST request. You MUST validate the `token` header against your configured \"Secret Key\" to ensure the request is securely originating from eSIMfx.\n3. **Process Payload**: Parse the incoming webhook payload to identify the affected `iccid` or `order_id`. Ensure your endpoint logic is designed to be idempotent to gracefully handle any duplicate webhook deliveries.\n4. **Notify User**: Map the `iccid` or `order_id` to your internal user database. Trigger your internal communication service (email, SMS, or in-app notification) to alert the user that their data is running low, and prompt them to initiate **Flow D (Top-Up Existing eSIM)** before they hit the 100% `EXPIRATION` event.\n---\n## 3. Product Catalog Constraints\n* **Version Requirement:** You MUST use the V2 Product API (`POST /product/api/v2/get_products`) instead of V1.\n* **ID Stability:** V2 returns stable, human-readable IDs (e.g., `esimfx_10G_7D_BR`) and includes a `meta_product_id`.\n---\n## 4. Order Creation & Idempotency\n### CRITICAL: Idempotency Headers\n* **Requirement:** All requests to `POST /order/api/v1/create_order` MUST include an `X-Idempotency-Key` header (e.g., a UUID).\n* **Validity:** Keys remain valid for 6 months to prevent duplicate charges on retries.\n### Operation Types\n| Type | Endpoint | Payload Structure | Purpose |\n| :--- | :--- | :--- | :--- |\n| **NEW** | `POST /order/api/v1/create_order` | `{\"operation_type\": \"NEW\", \"product\": {\"id\": \"esimfx_...\"}}` | Allocates new eSIM hardware and binds a data subscription. |\n| **TOPUP** | `POST /order/api/v1/create_order` | `{\"operation_type\": \"TOPUP\", \"iccid\": \"...\", \"product\": {\"id\": \"esimfx_...\"}}` | Adds a data package to an existing eSIM. |\n* **Top-Up Eligibility Rule:** An existing eSIM can ONLY be topped up with products sharing the exact same `imsi_profile` in the same region.\n* **Top-Up Fetching:** Always query `GET /product/api/v1/get_available_topups?iccid=<ICCID>` to retrieve valid top-up packages before initiating a top-up order.\n### Extraction After Creation\n* **QR Code:** For `NEW` orders, extract the LPA string from the response at `data.esim.esim_qr` to generate the installation QR code.\n* **ICCID:** For `NEW` orders, extract the eSIM ICCID at `data.esim.iccid`.\n---\n## 5. eSIM Lifecycle & Subscriptions\n### eSIM Hardware Status\n* **Query:** Use `GET /order/api/v1/get_esim_status?iccid=<ICCID>`.\n* **PROVISIONED:** Purchased, assigned, but not yet active.\n* **Installed:** Purchased, assigned, installed to device, but not yet active.\n* **ACTIVE:** Currently in use on a network.\n* **EXPIRED:** Data plans have concluded.\n* **BLOCKED:** Permanently deactivated.\n* **DEACTIVATED:** Unexpected errors to the eSIM may occur at any stage, but are exceedingly rare.\n### Subscription Status\n* **Query:** Use `GET /order/api/v1/get_order?order_id=<ORDER_ID>`.\n* **PENDING:** Data plan not yet activated.\n* **ACTIVE:** Activated via local network connection or manual trigger.\n* **EXPIRED:** Data exhausted or validity period ended.\n* **TERMINATED:** Cancelled manually through portal or API.\n### Activation Rules\n* **Auto-Activation:** **All** eSIM packages will be automatically activated when the user first connects to a local network.\n* **Manual Activation:** The `activate_subscription` API is only used for manual activation prior to connecting to the local network.\n* **Time-Based Activation:** We strongly suggest to ask users to activate their eSIM package **within 60 days** of purchase. If the eSIM package has not been activated **within 60 days** of purchase, might be infunctional based on sponsor policy.\n### Cancellations & Refunds\n* **Terminate Order:** `POST /order/api/v1/terminate_subscription` triggers an automatic refund if the order is `PENDING` and within 60 days of creation.\nFor unused data package (subscription status is `PENDING`): Refund will be automatically triggered when the subscription is `TERMINATED` from `PENDING` status within the 60 days creation of the order. If valid, \n* the package fee will be automatically deducted from invoice. \n* the eSIM fee will not be refunded, because the eSIM is already created\n---\n## 6. Asynchronous Webhooks\n* **Security:** Every incoming webhook includes a `token` header.\n* **Validation:** The code MUST validate the `token` header against the \"Secret Key\" configured in the eSIMfx portal.\n* **Event `DATA_USAGE`:** Sent when configured thresholds (e.g., 50%, 80%) are reached.\n* **Event `ACTIVATION`:** Sent when an eSIM hits a local network for the first time.\n* **Event `EXPIRATION`:** Sent when validity ends or 100% data exhaustion occurs.\n* **Resiliency:** Webhook receiver endpoints must be idempotent to handle duplicate deliveries gracefully.\n---\n## 7. Security & Payment Prerequisites\n* **Credential Management:** The AI MUST ensure `client_id` and `client_key` are stored in a secure location (e.g., environment variables, a secret manager) and NEVER hardcoded or published to public repositories.\n* **Payment Validation Constraint:** Before executing `create_order` (for both `NEW` and `TOPUP` operations), the system MUST ensure that the end-customer's payment has been successfully captured and validated. \n* **Fraud Prevention:** We strongly suggest using robust, anti-fraud payment gateways like **Stripe**.\n* **Human Action Required:** The AI MUST explicitly prompt the human developer to define and integrate a secure payment flow before generating the final API call logic. The financial transaction between the client and the end-user is strictly outside of Nomad eSIMfx's control.\n---\n## 8. Frontend UX & UI Guidance (End-User Instructions)\nWhen generating frontend UI components or building user instruction screens, the AI MUST incorporate the following guidance to ensure a seamless end-user experience:\n* **Before Installation (Pre-Install):** * Warn the user: *\"This eSIM can only be installed once. Do not remove it from your phone.\"*\n  * Instruct them to ensure they have a stable WiFi/network connection before installation.\n  * Advise them to rename their eSIM label (e.g., to \"eSIM\") for easy management.\n  * Instruct them to select their \"Primary\" line as the default for calls/messages.\n  * Remind them to turn off \"Allow Cellular Data Switching\" to avoid unexpected roaming bills on their home carrier.\n* **After Installation (Post-Install / \"How to Start\"):** * Provide a clear 4-step activation guide:\n    1. **Turn on eSIM:** Toggle the new eSIM line on.\n    2. **Turn on Data Roaming:** Enable data roaming specifically for the eSIM.\n    3. **Set as Cellular Data:** Select the new eSIM as the default Cellular Data line.\n    4. **Configure APN:** If required by the plan, instruct them to set the APN (e.g., `data.esim`).\n* **Managing eSIMs (\"My eSIM\" Screen):** * Structure the help interface into clear, sequential steps: *\"01 Install your eSIM\"* (with a note that they can check phone settings to verify) and *\"02 Start your eSIM\"*.\n* **Before Purchasing a Top-Up (Add-On Rules):** * Present clear rules before payment:\n    1. *\"Once data from your current plan is used up or expires, your add-on data will be automatically activated.\"*\n    2. *\"The countdown towards expiry will start when you start using data from the add-on package.\"*\n    3. *\"You do not need to re-install the eSIM or manually activate your add-on plan.\"*\n\n ```\n\n## **Important Disclaimer**\n\nWhile this context file would reduce development effort, provisioning eSIMs and executing orders involve real financial transactions. **Before deploying any integration to a production environment, human developers MUST conduct thorough code reviews, security audits, and extensive edge-case testing.** Nomad eSIMfx assumes no liability for unauthorized charges, logical errors, or integration flaws caused by AI-generated code.\n\n# FAQ\n\n1. **How to get my API Authentication token?**  \n    When users need to integrate our API, please [contact us](https://esimfx.com/contact-us/) to create a portal account. Resellers can log in to their account to view their API key (Available in Reseller > Client ID, and Client Key) and then access the API to begin the integration process.\n    \n2. **Could you please whitelist this IP on your side so we can successfully authenticate against the API?**  \n    We dont have IP restriction on our portal.\n    \n3. **For usage notifications (50% and 80%), is there a webhook available, or do we need to handle this differently?**  \n    Webhooks are configured on our portal page. Default notifications include: Activation, Expiration, 100% Usage, and a configurable usage threshold notification.\n    \n4. **For eSIM status updates (download, install, enable, etc.), do we receive a webhook, or should we call an API to retrieve this information?**  \n    eSIM status is queried via API. We provide the /get_esim_status API for this purpose.\n    \n5. **Regarding the product API – do we first need to create the products and then assign them to our eSIMs?**  \n    We offer a fixed product list for selection. When placing an order, simply pass our product ID to have it associated with the eSIM.  \n    We provide the /create_order API for this purpose.\n    \n6. **Is there an API available to check the balance of a package?**  \n    Data usage (consumed and remaining) per package can be queried using the /get_order API.\n    \n7. **How is my subscription activated?**  \n    Your subscription can be activated in one of three ways:\n    \n    1. **Automatically by First Data Usage (Most Common)**: The subscription will be activated automatically the first time the eSIM connects to a network and uses data. This is the most common method and provides a seamless \"out-of-the-box\" experience for the end-user.\n        \n    2. **Automatically at 60 Days**: If the subscription has not been activated by data usage, it will be automatically activated on the 60th day after purchase. This ensures that the validity period of the data package begins even if the eSIM has not yet been used.\n        \n    3. **Manually via the API:** You can proactively activate the subscription at any time before the 60-day period by calling the `activate subscription`API endpoint. This is useful for scenarios where you want to control the exact activation time.\n        \n\n# eSIMfx API Doc v1.8\n\n**What's New in v1.8:**\n\n- Added `/product/api/v2/get_products` - returns product_v2 data with new id  \n    format (esimfx_\\*), includes `meta_product_id`\n    \n    - _**Note:**_ _the_ `/product/api/v1/get_products` _will still be valid. But we recomend to upgrade to v2 to get a more stable product catalogue service._\n        \n- `get_product` support both legacy (UUID) and new (esimfx_\\*) product ids","schema":"https://schema.getpostman.com/json/collection/v2.0.0/collection.json","isPublicCollection":false,"owner":"49515304","team":10481124,"collectionId":"cc0390ba-b1ae-4861-b8ff-6fe3bdc1329b","publishedId":"2sBXcHiJqg","public":true,"publicUrl":"https://docs.esimfx.com","privateUrl":"https://go.postman.co/documentation/49515304-cc0390ba-b1ae-4861-b8ff-6fe3bdc1329b","customColor":{"top-bar":"FFFFFF","right-sidebar":"303030","highlight":"5143D0"},"documentationLayout":"classic-double-column","customisation":{"metaTags":[{"name":"description","value":""},{"name":"title","value":""}],"appearance":{"default":"light","themes":[{"name":"dark","logo":"https://content.pstmn.io/0a0b3f4a-99af-4ff0-9fce-7fb6430a98d5/bm9tYWQgJiBlc2ltZngucG5n","colors":{"top-bar":"212121","right-sidebar":"303030","highlight":"5143D0"}},{"name":"light","logo":"https://content.pstmn.io/0a0b3f4a-99af-4ff0-9fce-7fb6430a98d5/bm9tYWQgJiBlc2ltZngucG5n","colors":{"top-bar":"FFFFFF","right-sidebar":"303030","highlight":"5143D0"}}]}},"version":"8.10.1","publishDate":"2026-02-28T05:47:51.000Z","activeVersionTag":"latest","documentationTheme":"light","metaTags":{"title":"","description":""},"logos":{"logoLight":"https://content.pstmn.io/0a0b3f4a-99af-4ff0-9fce-7fb6430a98d5/bm9tYWQgJiBlc2ltZngucG5n","logoDark":"https://content.pstmn.io/0a0b3f4a-99af-4ff0-9fce-7fb6430a98d5/bm9tYWQgJiBlc2ltZngucG5n"}},"statusCode":200},"environments":[{"name":"esimfx","id":"302aebd4-6e1e-40d3-97d4-e3e1d0f6e7a3","owner":"49515304","values":[{"key":"baseUrl","value":"","enabled":true,"type":"default"},{"key":"access_token","value":"","enabled":true,"type":"default"}],"published":true}],"user":{"authenticated":false,"permissions":{"publish":false}},"run":{"button":{"js":"https://run.pstmn.io/button.js","css":"https://run.pstmn.io/button.css"}},"web":"https://www.getpostman.com/","team":{"logo":"https://res.cloudinary.com/postman/image/upload/t_team_logo_pubdoc/v1/team/b9c29f008807f5663a65a6654be5a7b2242506d526154b1edd1167ad74a940bc","favicon":"https://res.cloudinary.com/postman/image/upload/v1762507306/team/f685f72bacf45422bbb64f2fa75cde5f.ico"},"isEnvFetchError":false,"languages":"[{\"key\":\"csharp\",\"label\":\"C#\",\"variant\":\"HttpClient\"},{\"key\":\"csharp\",\"label\":\"C#\",\"variant\":\"RestSharp\"},{\"key\":\"curl\",\"label\":\"cURL\",\"variant\":\"cURL\"},{\"key\":\"dart\",\"label\":\"Dart\",\"variant\":\"http\"},{\"key\":\"go\",\"label\":\"Go\",\"variant\":\"Native\"},{\"key\":\"http\",\"label\":\"HTTP\",\"variant\":\"HTTP\"},{\"key\":\"java\",\"label\":\"Java\",\"variant\":\"OkHttp\"},{\"key\":\"java\",\"label\":\"Java\",\"variant\":\"Unirest\"},{\"key\":\"javascript\",\"label\":\"JavaScript\",\"variant\":\"Fetch\"},{\"key\":\"javascript\",\"label\":\"JavaScript\",\"variant\":\"jQuery\"},{\"key\":\"javascript\",\"label\":\"JavaScript\",\"variant\":\"XHR\"},{\"key\":\"c\",\"label\":\"C\",\"variant\":\"libcurl\"},{\"key\":\"nodejs\",\"label\":\"NodeJs\",\"variant\":\"Axios\"},{\"key\":\"nodejs\",\"label\":\"NodeJs\",\"variant\":\"Native\"},{\"key\":\"nodejs\",\"label\":\"NodeJs\",\"variant\":\"Request\"},{\"key\":\"nodejs\",\"label\":\"NodeJs\",\"variant\":\"Unirest\"},{\"key\":\"objective-c\",\"label\":\"Objective-C\",\"variant\":\"NSURLSession\"},{\"key\":\"ocaml\",\"label\":\"OCaml\",\"variant\":\"Cohttp\"},{\"key\":\"php\",\"label\":\"PHP\",\"variant\":\"cURL\"},{\"key\":\"php\",\"label\":\"PHP\",\"variant\":\"Guzzle\"},{\"key\":\"php\",\"label\":\"PHP\",\"variant\":\"HTTP_Request2\"},{\"key\":\"php\",\"label\":\"PHP\",\"variant\":\"pecl_http\"},{\"key\":\"powershell\",\"label\":\"PowerShell\",\"variant\":\"RestMethod\"},{\"key\":\"python\",\"label\":\"Python\",\"variant\":\"http.client\"},{\"key\":\"python\",\"label\":\"Python\",\"variant\":\"Requests\"},{\"key\":\"r\",\"label\":\"R\",\"variant\":\"httr\"},{\"key\":\"r\",\"label\":\"R\",\"variant\":\"RCurl\"},{\"key\":\"ruby\",\"label\":\"Ruby\",\"variant\":\"Net::HTTP\"},{\"key\":\"shell\",\"label\":\"Shell\",\"variant\":\"Httpie\"},{\"key\":\"shell\",\"label\":\"Shell\",\"variant\":\"wget\"},{\"key\":\"swift\",\"label\":\"Swift\",\"variant\":\"URLSession\"}]","languageSettings":[{"key":"csharp","label":"C#","variant":"HttpClient"},{"key":"csharp","label":"C#","variant":"RestSharp"},{"key":"curl","label":"cURL","variant":"cURL"},{"key":"dart","label":"Dart","variant":"http"},{"key":"go","label":"Go","variant":"Native"},{"key":"http","label":"HTTP","variant":"HTTP"},{"key":"java","label":"Java","variant":"OkHttp"},{"key":"java","label":"Java","variant":"Unirest"},{"key":"javascript","label":"JavaScript","variant":"Fetch"},{"key":"javascript","label":"JavaScript","variant":"jQuery"},{"key":"javascript","label":"JavaScript","variant":"XHR"},{"key":"c","label":"C","variant":"libcurl"},{"key":"nodejs","label":"NodeJs","variant":"Axios"},{"key":"nodejs","label":"NodeJs","variant":"Native"},{"key":"nodejs","label":"NodeJs","variant":"Request"},{"key":"nodejs","label":"NodeJs","variant":"Unirest"},{"key":"objective-c","label":"Objective-C","variant":"NSURLSession"},{"key":"ocaml","label":"OCaml","variant":"Cohttp"},{"key":"php","label":"PHP","variant":"cURL"},{"key":"php","label":"PHP","variant":"Guzzle"},{"key":"php","label":"PHP","variant":"HTTP_Request2"},{"key":"php","label":"PHP","variant":"pecl_http"},{"key":"powershell","label":"PowerShell","variant":"RestMethod"},{"key":"python","label":"Python","variant":"http.client"},{"key":"python","label":"Python","variant":"Requests"},{"key":"r","label":"R","variant":"httr"},{"key":"r","label":"R","variant":"RCurl"},{"key":"ruby","label":"Ruby","variant":"Net::HTTP"},{"key":"shell","label":"Shell","variant":"Httpie"},{"key":"shell","label":"Shell","variant":"wget"},{"key":"swift","label":"Swift","variant":"URLSession"}],"languageOptions":[{"label":"C# - HttpClient","value":"csharp - HttpClient - C#"},{"label":"C# - RestSharp","value":"csharp - RestSharp - C#"},{"label":"cURL - cURL","value":"curl - cURL - cURL"},{"label":"Dart - http","value":"dart - http - Dart"},{"label":"Go - Native","value":"go - Native - Go"},{"label":"HTTP - HTTP","value":"http - HTTP - HTTP"},{"label":"Java - OkHttp","value":"java - OkHttp - Java"},{"label":"Java - Unirest","value":"java - Unirest - Java"},{"label":"JavaScript - Fetch","value":"javascript - Fetch - JavaScript"},{"label":"JavaScript - jQuery","value":"javascript - jQuery - JavaScript"},{"label":"JavaScript - XHR","value":"javascript - XHR - JavaScript"},{"label":"C - libcurl","value":"c - libcurl - C"},{"label":"NodeJs - Axios","value":"nodejs - Axios - NodeJs"},{"label":"NodeJs - Native","value":"nodejs - Native - NodeJs"},{"label":"NodeJs - Request","value":"nodejs - Request - NodeJs"},{"label":"NodeJs - Unirest","value":"nodejs - Unirest - NodeJs"},{"label":"Objective-C - NSURLSession","value":"objective-c - NSURLSession - Objective-C"},{"label":"OCaml - Cohttp","value":"ocaml - Cohttp - OCaml"},{"label":"PHP - cURL","value":"php - cURL - PHP"},{"label":"PHP - Guzzle","value":"php - Guzzle - PHP"},{"label":"PHP - HTTP_Request2","value":"php - HTTP_Request2 - PHP"},{"label":"PHP - pecl_http","value":"php - pecl_http - PHP"},{"label":"PowerShell - RestMethod","value":"powershell - RestMethod - PowerShell"},{"label":"Python - http.client","value":"python - http.client - Python"},{"label":"Python - Requests","value":"python - Requests - Python"},{"label":"R - httr","value":"r - httr - R"},{"label":"R - RCurl","value":"r - RCurl - R"},{"label":"Ruby - Net::HTTP","value":"ruby - Net::HTTP - Ruby"},{"label":"Shell - Httpie","value":"shell - Httpie - Shell"},{"label":"Shell - wget","value":"shell - wget - Shell"},{"label":"Swift - URLSession","value":"swift - URLSession - Swift"}],"layoutOptions":[{"value":"classic-single-column","label":"Single Column"},{"value":"classic-double-column","label":"Double Column"}],"versionOptions":[],"environmentOptions":[{"value":"0","label":"No Environment"},{"label":"esimfx","value":"49515304-302aebd4-6e1e-40d3-97d4-e3e1d0f6e7a3"}],"canonicalUrl":"https://docs.esimfx.com/view/metadata/2sBXcHiJqg"}