{
    "info": {
        "name": "JoNet API",
        "description": "JoNet API -- buy data, airtime, electricity, cable TV and e-pins from your own app or website.\n\nFull documentation: https://jonet.com.ng/documentation\n\n**Base URL:** `https://jonet.com.ng/api_live/v1/`\n\n**Authentication:** send your API key in the `Authorization` header (set the `api_key` variable). Generate it under API Keys in your JoNet dashboard. https only; 50 requests a minute per key.\n\n**Customer ID:** every purchase needs a unique `customer_id` that starts with today's date and hour in Lagos time (`YYYYMMDDHH`, minute recommended), 10-20 characters (letters, digits, `-`).\n\n**Pending orders:** never resend a Pending (201/202/203/2031/2032/JO105) order with a new customer_id. Wait for the webhook or use Requery.\n\n### Response codes\n\n| Code | Meaning | Treat as |\n|---|---|---|\n| 200 | Successful. On Requery, 200 only means the order was found -- read `status` for its state. | Success |\n| 201, 202, 203 | Processing / status not final yet. The order is charged; it completes or is refunded shortly. Wait for the webhook or Requery. | Pending |\n| 2031, 2032 | Electricity: duplicate at the vendor (2031) or unknown status (2032). Not refunded -- Requery. | Pending |\n| JO105 | This customer_id was already used on your account. Requery that customer_id -- do not resend with a new one. | Pending |\n| JO106, JO107, JO1061 | Failed. Your wallet has been refunded. | Failed |\n| 002, 10114 | Your wallet could not be charged. Nothing was taken. | Failed |\n| 101 | No Authorization header found. | Failed |\n| 102 | Invalid API key (Get Wallet answers an invalid key with 103). | Failed |\n| 103 | Wrong request method (e.g. GET on a POST endpoint), or invalid authorization: the token does not belong to this key's account, or the account is not an API account. | Failed |\n| 104 | Insecure connection -- use https. | Failed |\n| 105 | Unable to process: unknown plan / package / disco, or an invalid amount or quantity. | Failed |\n| 106 | This API key has expired. Generate a new one on your dashboard. | Failed |\n| 107 | This API key has been paused, or the account has been suspended. | Failed |\n| 108, 109 | Account not found, no vendor set up for this service, or busy -- try again. | Failed |\n| 110, 1014, 424 | Insufficient balance (424 is also used for \"cannot be done right now\", e.g. out of stock, Airtime to Cash errors). | Failed |\n| 1005, 1050 | Unable to process request. If it persists, contact support. | Failed |\n| 1015 | This account is not eligible to make purchases. | Failed |\n| JO101 | This service is temporarily switched off (or not supported for this provider). | Failed |\n| JO102 | Missing or invalid request fields. | Failed |\n| JO103 | Wrong phone number format (must start with 0). | Failed |\n| JO104 | Wrong customer_id format (see Customer ID below). | Failed |\n| JO1051 | Wrong network name (Airtime). | Failed |\n| JO109 | No webhook URL set on your account. | Failed |\n| JO110 | Transaction not found. | Failed |\n| JO119 | Transaction not completed yet (webhook can only be resent for a finished order). | Failed |\n| JO121 | Your wallet balance is negative. Fund your wallet first. | Failed |\n| JO123 | The meter or smartcard could not be verified with the vendor. You were not charged. | Failed |\n| 409 | Another action on your wallet is in progress -- try again. | Failed |\n| 429 | Too many requests (more than 50 a minute per key) -- slow down. | Failed |\n| 500 | Temporary error -- try again. | Failed |\n| Your IP address | This request came from an IP address not on your allowed list. | Failed |\n| INVALID_JSON, PAYLOAD_TOO_LARGE | The body is not valid JSON, or is larger than 64 KB. | Failed |\n| SERVICE_UNAVAILABLE | The same customer_id is already being processed (sent twice at the same time), or the service is briefly unavailable -- wait a moment, then requery that customer_id before retrying. | Failed |\n\n### Webhook\n\nWhen a Pending order finishes we POST this to your webhook URL, with your API key in the `Authorization` header:\n\n```json\n{\n    \"status\": \"Successful\",\n    \"server_response\": \"Successful\",\n    \"type\": \"Airtime\",\n    \"data\": {\n        \"receipent\": \"08031234567\",\n        \"customer_id\": \"2026100114305581234\",\n        \"vendor_id\": \"\",\n        \"balance\": \"12856\"\n    }\n}\n```\n",
        "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
    },
    "auth": {
        "type": "apikey",
        "apikey": [
            {
                "key": "key",
                "value": "Authorization",
                "type": "string"
            },
            {
                "key": "value",
                "value": "{{api_key}}",
                "type": "string"
            },
            {
                "key": "in",
                "value": "header",
                "type": "string"
            }
        ]
    },
    "variable": [
        {
            "key": "base_url",
            "value": "https://jonet.com.ng/api_live/v1/",
            "type": "string"
        },
        {
            "key": "api_key",
            "value": "YOUR_API_KEY",
            "type": "string"
        }
    ],
    "item": [
        {
            "name": "Wallet",
            "description": "Your wallet balance and account details.",
            "item": [
                {
                    "name": "Get Wallet",
                    "request": {
                        "method": "GET",
                        "header": [],
                        "url": {
                            "raw": "{{base_url}}get_wallet.php"
                        },
                        "description": "Your current wallet balance and the bank accounts you can fund it through.\n\n**Notes**\n\n- Note the field names under Accounts: `bankName` holds the account number and `accountNumber` holds the bank name. This is long-standing behaviour that existing integrations rely on, so it is kept as is.\n"
                    },
                    "response": [
                        {
                            "name": "Successful",
                            "originalRequest": {
                                "method": "GET",
                                "header": [],
                                "url": {
                                    "raw": "{{base_url}}get_wallet.php"
                                },
                                "description": "Your current wallet balance and the bank accounts you can fund it through.\n\n**Notes**\n\n- Note the field names under Accounts: `bankName` holds the account number and `accountNumber` holds the bank name. This is long-standing behaviour that existing integrations rely on, so it is kept as is.\n"
                            },
                            "status": "OK",
                            "code": 200,
                            "_postman_previewlanguage": "json",
                            "header": [
                                {
                                    "key": "Content-Type",
                                    "value": "application/json"
                                }
                            ],
                            "body": "{\n    \"responseCode\": \"200\",\n    \"walletBalance\": \"19176\",\n    \"user\": {\n        \"email\": \"partner@example.com\",\n        \"usrtel\": \"08031234567\",\n        \"AccountCreated\": \"2019-05-18 12:12:50\",\n        \"LastModified\": \"2026-09-05 00:23:00\",\n        \"Accounts\": {\n            \"AccountDetails\": {\n                \"bankName\": \"8594950150\",\n                \"accountNumber\": \"Providus Bank\"\n            },\n            \"BackupAccountDetails\": {\n                \"bankName\": \"7589497373\",\n                \"accountNumber\": \"Sterling Bank\"\n            }\n        },\n        \"referral_link\": \"https://jonet.com.ng/signup?referral_id=76099008c\"\n    }\n}"
                        }
                    ]
                }
            ]
        },
        {
            "name": "Data",
            "description": "Get the data plans, then buy one with its `code`.",
            "item": [
                {
                    "name": "Get Data Bundles",
                    "request": {
                        "method": "GET",
                        "header": [],
                        "url": {
                            "raw": "{{base_url}}get_data_bundles.php"
                        },
                        "description": "All active data plans, grouped by provider and then by network. Store them on your side and refresh regularly.\n\n**Notes**\n\n- Use `code` as the `code` in Purchase Data.\n- `Price` is the plan price. Your API commission is taken off when you buy; Purchase Data returns what was actually charged in `amountcharged`.\n"
                    },
                    "response": [
                        {
                            "name": "Successful",
                            "originalRequest": {
                                "method": "GET",
                                "header": [],
                                "url": {
                                    "raw": "{{base_url}}get_data_bundles.php"
                                },
                                "description": "All active data plans, grouped by provider and then by network. Store them on your side and refresh regularly.\n\n**Notes**\n\n- Use `code` as the `code` in Purchase Data.\n- `Price` is the plan price. Your API commission is taken off when you buy; Purchase Data returns what was actually charged in `amountcharged`.\n"
                            },
                            "status": "OK",
                            "code": 200,
                            "_postman_previewlanguage": "json",
                            "header": [
                                {
                                    "key": "Content-Type",
                                    "value": "application/json"
                                }
                            ],
                            "body": "{\n    \"MTN\": {\n        \"MTN_CG\": [\n            {\n                \"name\": \"MTN CG\",\n                \"size\": \"1GB\",\n                \"code\": \"7\",\n                \"Plan_ID\": \"7\",\n                \"Price\": \"240\"\n            },\n            {\n                \"name\": \"MTN CG\",\n                \"size\": \"2GB\",\n                \"code\": \"4\",\n                \"Plan_ID\": \"4\",\n                \"Price\": \"480\"\n            }\n        ]\n    }\n}"
                        }
                    ]
                },
                {
                    "name": "Purchase Data",
                    "request": {
                        "method": "POST",
                        "header": [
                            {
                                "key": "Content-Type",
                                "value": "application/json"
                            }
                        ],
                        "url": {
                            "raw": "{{base_url}}purchase_data.php"
                        },
                        "description": "Buy a data plan for a phone number.\n\n**Body (JSON)**\n\n| Field | Required | Description |\n|---|---|---|\n| `code` (string) | Yes | The plan `code` from Get Data Bundles. |\n| `phone` (string) | Yes | Beneficiary number. Must start with 0 (07…, 08…, 09…). |\n| `customer_id` (string) | Yes | Your unique reference -- see Customer ID. |\n\n**Common errors**\n\n- `JO102` Missing code, phone or customer_id\n- `JO103` Phone number does not start with 0\n- `JO104` customer_id format\n- `JO105` customer_id already used\n- `SERVICE_UNAVAILABLE` Same customer_id sent twice at the same time (HTTP 503) -- requery it\n- `105` Unknown plan code\n- `JO101` Data switched off\n- `110` Insufficient balance\n- `002` Wallet could not be charged\n- `1015 / 1050 / JO121` Account checks (see response codes)\n",
                        "body": {
                            "mode": "raw",
                            "raw": "{\n    \"code\": \"7\",\n    \"phone\": \"08031234567\",\n    \"customer_id\": \"2026100114305581234\"\n}",
                            "options": {
                                "raw": {
                                    "language": "json"
                                }
                            }
                        }
                    },
                    "response": [
                        {
                            "name": "Successful (200)",
                            "originalRequest": {
                                "method": "POST",
                                "header": [
                                    {
                                        "key": "Content-Type",
                                        "value": "application/json"
                                    }
                                ],
                                "url": {
                                    "raw": "{{base_url}}purchase_data.php"
                                },
                                "description": "Buy a data plan for a phone number.\n\n**Body (JSON)**\n\n| Field | Required | Description |\n|---|---|---|\n| `code` (string) | Yes | The plan `code` from Get Data Bundles. |\n| `phone` (string) | Yes | Beneficiary number. Must start with 0 (07…, 08…, 09…). |\n| `customer_id` (string) | Yes | Your unique reference -- see Customer ID. |\n\n**Common errors**\n\n- `JO102` Missing code, phone or customer_id\n- `JO103` Phone number does not start with 0\n- `JO104` customer_id format\n- `JO105` customer_id already used\n- `SERVICE_UNAVAILABLE` Same customer_id sent twice at the same time (HTTP 503) -- requery it\n- `105` Unknown plan code\n- `JO101` Data switched off\n- `110` Insufficient balance\n- `002` Wallet could not be charged\n- `1015 / 1050 / JO121` Account checks (see response codes)\n",
                                "body": {
                                    "mode": "raw",
                                    "raw": "{\n    \"code\": \"7\",\n    \"phone\": \"08031234567\",\n    \"customer_id\": \"2026100114305581234\"\n}",
                                    "options": {
                                        "raw": {
                                            "language": "json"
                                        }
                                    }
                                }
                            },
                            "status": "OK",
                            "code": 200,
                            "_postman_previewlanguage": "json",
                            "header": [
                                {
                                    "key": "Content-Type",
                                    "value": "application/json"
                                }
                            ],
                            "body": "{\n    \"responseCode\": \"200\",\n    \"status\": \"Successful\",\n    \"message\": \"1GB MTN_CG to 08031234567 Successful\",\n    \"receipent\": \"08031234567\",\n    \"email\": \"partner@example.com\",\n    \"amountcharged\": \"228\",\n    \"commissionGiven\": \"12\",\n    \"balance\": \"8600\",\n    \"chargeMethod\": \"Wallet\",\n    \"channel\": \"API\",\n    \"customer_id\": \"2026100114305581234\",\n    \"vendor_id\": \"13397889\",\n    \"server_response\": \"Dear Customer, You have successfully shared 1GB Data to 2348031234567.\",\n    \"createdOn\": \"2026-10-01 14:30:55\"\n}"
                        },
                        {
                            "name": "Processing (203) -- wait for the webhook or Requery",
                            "originalRequest": {
                                "method": "POST",
                                "header": [
                                    {
                                        "key": "Content-Type",
                                        "value": "application/json"
                                    }
                                ],
                                "url": {
                                    "raw": "{{base_url}}purchase_data.php"
                                },
                                "description": "Buy a data plan for a phone number.\n\n**Body (JSON)**\n\n| Field | Required | Description |\n|---|---|---|\n| `code` (string) | Yes | The plan `code` from Get Data Bundles. |\n| `phone` (string) | Yes | Beneficiary number. Must start with 0 (07…, 08…, 09…). |\n| `customer_id` (string) | Yes | Your unique reference -- see Customer ID. |\n\n**Common errors**\n\n- `JO102` Missing code, phone or customer_id\n- `JO103` Phone number does not start with 0\n- `JO104` customer_id format\n- `JO105` customer_id already used\n- `SERVICE_UNAVAILABLE` Same customer_id sent twice at the same time (HTTP 503) -- requery it\n- `105` Unknown plan code\n- `JO101` Data switched off\n- `110` Insufficient balance\n- `002` Wallet could not be charged\n- `1015 / 1050 / JO121` Account checks (see response codes)\n",
                                "body": {
                                    "mode": "raw",
                                    "raw": "{\n    \"code\": \"7\",\n    \"phone\": \"08031234567\",\n    \"customer_id\": \"2026100114305581234\"\n}",
                                    "options": {
                                        "raw": {
                                            "language": "json"
                                        }
                                    }
                                }
                            },
                            "status": "OK",
                            "code": 200,
                            "_postman_previewlanguage": "json",
                            "header": [
                                {
                                    "key": "Content-Type",
                                    "value": "application/json"
                                }
                            ],
                            "body": "{\n    \"responseCode\": \"203\",\n    \"status\": \"Processing\",\n    \"message\": \"\",\n    \"receipent\": \"08031234567\",\n    \"email\": \"partner@example.com\",\n    \"amountcharged\": \"228\",\n    \"commissionGiven\": \"12\",\n    \"balance\": \"8372\",\n    \"chargeMethod\": \"Wallet\",\n    \"channel\": \"API\",\n    \"customer_id\": \"2026100114307719042\",\n    \"server_response\": \"Processing, it will be successful or refunded within 1 minute\",\n    \"createdOn\": \"2026-10-01 14:30:57\"\n}"
                        },
                        {
                            "name": "Failed -- refunded (JO107)",
                            "originalRequest": {
                                "method": "POST",
                                "header": [
                                    {
                                        "key": "Content-Type",
                                        "value": "application/json"
                                    }
                                ],
                                "url": {
                                    "raw": "{{base_url}}purchase_data.php"
                                },
                                "description": "Buy a data plan for a phone number.\n\n**Body (JSON)**\n\n| Field | Required | Description |\n|---|---|---|\n| `code` (string) | Yes | The plan `code` from Get Data Bundles. |\n| `phone` (string) | Yes | Beneficiary number. Must start with 0 (07…, 08…, 09…). |\n| `customer_id` (string) | Yes | Your unique reference -- see Customer ID. |\n\n**Common errors**\n\n- `JO102` Missing code, phone or customer_id\n- `JO103` Phone number does not start with 0\n- `JO104` customer_id format\n- `JO105` customer_id already used\n- `SERVICE_UNAVAILABLE` Same customer_id sent twice at the same time (HTTP 503) -- requery it\n- `105` Unknown plan code\n- `JO101` Data switched off\n- `110` Insufficient balance\n- `002` Wallet could not be charged\n- `1015 / 1050 / JO121` Account checks (see response codes)\n",
                                "body": {
                                    "mode": "raw",
                                    "raw": "{\n    \"code\": \"7\",\n    \"phone\": \"08031234567\",\n    \"customer_id\": \"2026100114305581234\"\n}",
                                    "options": {
                                        "raw": {
                                            "language": "json"
                                        }
                                    }
                                }
                            },
                            "status": "OK",
                            "code": 200,
                            "_postman_previewlanguage": "json",
                            "header": [
                                {
                                    "key": "Content-Type",
                                    "value": "application/json"
                                }
                            ],
                            "body": "{\n    \"responseCode\": \"JO107\",\n    \"status\": \"Failed\",\n    \"message\": \"\",\n    \"receipent\": \"08031234567\",\n    \"email\": \"partner@example.com\",\n    \"amountcharged\": \"228\",\n    \"commissionGiven\": \"12\",\n    \"balance\": \"8600\",\n    \"chargeMethod\": \"Wallet\",\n    \"channel\": \"API\",\n    \"customer_id\": \"2026100114309920117\",\n    \"server_response\": \"Invalid phone number for this network\",\n    \"createdOn\": \"2026-10-01 14:31:02\"\n}"
                        },
                        {
                            "name": "Request rejected (example)",
                            "originalRequest": {
                                "method": "POST",
                                "header": [
                                    {
                                        "key": "Content-Type",
                                        "value": "application/json"
                                    }
                                ],
                                "url": {
                                    "raw": "{{base_url}}purchase_data.php"
                                },
                                "description": "Buy a data plan for a phone number.\n\n**Body (JSON)**\n\n| Field | Required | Description |\n|---|---|---|\n| `code` (string) | Yes | The plan `code` from Get Data Bundles. |\n| `phone` (string) | Yes | Beneficiary number. Must start with 0 (07…, 08…, 09…). |\n| `customer_id` (string) | Yes | Your unique reference -- see Customer ID. |\n\n**Common errors**\n\n- `JO102` Missing code, phone or customer_id\n- `JO103` Phone number does not start with 0\n- `JO104` customer_id format\n- `JO105` customer_id already used\n- `SERVICE_UNAVAILABLE` Same customer_id sent twice at the same time (HTTP 503) -- requery it\n- `105` Unknown plan code\n- `JO101` Data switched off\n- `110` Insufficient balance\n- `002` Wallet could not be charged\n- `1015 / 1050 / JO121` Account checks (see response codes)\n",
                                "body": {
                                    "mode": "raw",
                                    "raw": "{\n    \"code\": \"7\",\n    \"phone\": \"08031234567\",\n    \"customer_id\": \"2026100114305581234\"\n}",
                                    "options": {
                                        "raw": {
                                            "language": "json"
                                        }
                                    }
                                }
                            },
                            "status": "OK",
                            "code": 200,
                            "_postman_previewlanguage": "json",
                            "header": [
                                {
                                    "key": "Content-Type",
                                    "value": "application/json"
                                }
                            ],
                            "body": "{\n    \"message\": \"Wrong customer ID format. Please check the documentation for the right format\",\n    \"responseCode\": \"JO104\",\n    \"status\": \"Failed\"\n}"
                        }
                    ]
                }
            ]
        },
        {
            "name": "Airtime",
            "description": "Top up any MTN, Glo, Airtel or 9mobile number.",
            "item": [
                {
                    "name": "Purchase Airtime",
                    "request": {
                        "method": "POST",
                        "header": [
                            {
                                "key": "Content-Type",
                                "value": "application/json"
                            }
                        ],
                        "url": {
                            "raw": "{{base_url}}purchase_airtime.php"
                        },
                        "description": "Send airtime to a phone number.\n\n**Body (JSON)**\n\n| Field | Required | Description |\n|---|---|---|\n| `amount` (number) | Yes | Airtime amount in Naira, at least 50. |\n| `phone` (string) | Yes | Beneficiary number. Must start with 0. |\n| `network` (string) | Yes | Exactly one of `MTN`, `Glo`, `Airtel`, `9mobile` (case-sensitive). |\n| `customer_id` (string) | Yes | Your unique reference -- see Customer ID. |\n\n**Common errors**\n\n- `JO102` Missing field, or amount below 50\n- `JO103` Phone format\n- `JO104` customer_id format\n- `JO105` customer_id already used\n- `JO1051` Network name not one of MTN, Glo, Airtel, 9mobile\n- `JO101` Airtime switched off for this network\n- `1014 / 424` Insufficient balance\n- `10114` Wallet could not be charged\n- `109` Busy -- try again\n",
                        "body": {
                            "mode": "raw",
                            "raw": "{\n    \"amount\": \"100\",\n    \"phone\": \"08031234567\",\n    \"network\": \"MTN\",\n    \"customer_id\": \"2026100114325511870\"\n}",
                            "options": {
                                "raw": {
                                    "language": "json"
                                }
                            }
                        }
                    },
                    "response": [
                        {
                            "name": "Successful (200)",
                            "originalRequest": {
                                "method": "POST",
                                "header": [
                                    {
                                        "key": "Content-Type",
                                        "value": "application/json"
                                    }
                                ],
                                "url": {
                                    "raw": "{{base_url}}purchase_airtime.php"
                                },
                                "description": "Send airtime to a phone number.\n\n**Body (JSON)**\n\n| Field | Required | Description |\n|---|---|---|\n| `amount` (number) | Yes | Airtime amount in Naira, at least 50. |\n| `phone` (string) | Yes | Beneficiary number. Must start with 0. |\n| `network` (string) | Yes | Exactly one of `MTN`, `Glo`, `Airtel`, `9mobile` (case-sensitive). |\n| `customer_id` (string) | Yes | Your unique reference -- see Customer ID. |\n\n**Common errors**\n\n- `JO102` Missing field, or amount below 50\n- `JO103` Phone format\n- `JO104` customer_id format\n- `JO105` customer_id already used\n- `JO1051` Network name not one of MTN, Glo, Airtel, 9mobile\n- `JO101` Airtime switched off for this network\n- `1014 / 424` Insufficient balance\n- `10114` Wallet could not be charged\n- `109` Busy -- try again\n",
                                "body": {
                                    "mode": "raw",
                                    "raw": "{\n    \"amount\": \"100\",\n    \"phone\": \"08031234567\",\n    \"network\": \"MTN\",\n    \"customer_id\": \"2026100114325511870\"\n}",
                                    "options": {
                                        "raw": {
                                            "language": "json"
                                        }
                                    }
                                }
                            },
                            "status": "OK",
                            "code": 200,
                            "_postman_previewlanguage": "json",
                            "header": [
                                {
                                    "key": "Content-Type",
                                    "value": "application/json"
                                }
                            ],
                            "body": "{\n    \"responseCode\": \"200\",\n    \"status\": \"Successful\",\n    \"message\": \"100 MTN_Airtime VTU to 08031234567 Successful\",\n    \"receipent\": \"08031234567\",\n    \"email\": \"partner@example.com\",\n    \"amountcharged\": \"98\",\n    \"commissionGiven\": \"2\",\n    \"balance\": \"8502\",\n    \"chargeMethod\": \"Wallet\",\n    \"channel\": \"API\",\n    \"customer_id\": \"2026100114325511870\",\n    \"vendor_id\": \"230981\",\n    \"server_response\": \"Transaction successful\",\n    \"createdOn\": \"2026-10-01 14:32:55\"\n}"
                        },
                        {
                            "name": "Processing (203)",
                            "originalRequest": {
                                "method": "POST",
                                "header": [
                                    {
                                        "key": "Content-Type",
                                        "value": "application/json"
                                    }
                                ],
                                "url": {
                                    "raw": "{{base_url}}purchase_airtime.php"
                                },
                                "description": "Send airtime to a phone number.\n\n**Body (JSON)**\n\n| Field | Required | Description |\n|---|---|---|\n| `amount` (number) | Yes | Airtime amount in Naira, at least 50. |\n| `phone` (string) | Yes | Beneficiary number. Must start with 0. |\n| `network` (string) | Yes | Exactly one of `MTN`, `Glo`, `Airtel`, `9mobile` (case-sensitive). |\n| `customer_id` (string) | Yes | Your unique reference -- see Customer ID. |\n\n**Common errors**\n\n- `JO102` Missing field, or amount below 50\n- `JO103` Phone format\n- `JO104` customer_id format\n- `JO105` customer_id already used\n- `JO1051` Network name not one of MTN, Glo, Airtel, 9mobile\n- `JO101` Airtime switched off for this network\n- `1014 / 424` Insufficient balance\n- `10114` Wallet could not be charged\n- `109` Busy -- try again\n",
                                "body": {
                                    "mode": "raw",
                                    "raw": "{\n    \"amount\": \"100\",\n    \"phone\": \"08031234567\",\n    \"network\": \"MTN\",\n    \"customer_id\": \"2026100114325511870\"\n}",
                                    "options": {
                                        "raw": {
                                            "language": "json"
                                        }
                                    }
                                }
                            },
                            "status": "OK",
                            "code": 200,
                            "_postman_previewlanguage": "json",
                            "header": [
                                {
                                    "key": "Content-Type",
                                    "value": "application/json"
                                }
                            ],
                            "body": "{\n    \"responseCode\": \"203\",\n    \"status\": \"Processing\",\n    \"message\": \"VTU MTN_Airtime to 08031234567 Processing\",\n    \"receipent\": \"08031234567\",\n    \"email\": \"partner@example.com\",\n    \"amountcharged\": \"98\",\n    \"commissionGiven\": \"2\",\n    \"balance\": \"8404\",\n    \"chargeMethod\": \"Wallet\",\n    \"channel\": \"API\",\n    \"customer_id\": \"2026100114326640021\",\n    \"server_response\": \"Processing\",\n    \"createdOn\": \"2026-10-01 14:32:58\"\n}"
                        },
                        {
                            "name": "Failed -- refunded (JO107)",
                            "originalRequest": {
                                "method": "POST",
                                "header": [
                                    {
                                        "key": "Content-Type",
                                        "value": "application/json"
                                    }
                                ],
                                "url": {
                                    "raw": "{{base_url}}purchase_airtime.php"
                                },
                                "description": "Send airtime to a phone number.\n\n**Body (JSON)**\n\n| Field | Required | Description |\n|---|---|---|\n| `amount` (number) | Yes | Airtime amount in Naira, at least 50. |\n| `phone` (string) | Yes | Beneficiary number. Must start with 0. |\n| `network` (string) | Yes | Exactly one of `MTN`, `Glo`, `Airtel`, `9mobile` (case-sensitive). |\n| `customer_id` (string) | Yes | Your unique reference -- see Customer ID. |\n\n**Common errors**\n\n- `JO102` Missing field, or amount below 50\n- `JO103` Phone format\n- `JO104` customer_id format\n- `JO105` customer_id already used\n- `JO1051` Network name not one of MTN, Glo, Airtel, 9mobile\n- `JO101` Airtime switched off for this network\n- `1014 / 424` Insufficient balance\n- `10114` Wallet could not be charged\n- `109` Busy -- try again\n",
                                "body": {
                                    "mode": "raw",
                                    "raw": "{\n    \"amount\": \"100\",\n    \"phone\": \"08031234567\",\n    \"network\": \"MTN\",\n    \"customer_id\": \"2026100114325511870\"\n}",
                                    "options": {
                                        "raw": {
                                            "language": "json"
                                        }
                                    }
                                }
                            },
                            "status": "OK",
                            "code": 200,
                            "_postman_previewlanguage": "json",
                            "header": [
                                {
                                    "key": "Content-Type",
                                    "value": "application/json"
                                }
                            ],
                            "body": "{\n    \"responseCode\": \"JO107\",\n    \"status\": \"Failed\",\n    \"message\": \"\",\n    \"receipent\": \"08031234567\",\n    \"email\": \"partner@example.com\",\n    \"amountcharged\": \"98\",\n    \"commissionGiven\": \"2\",\n    \"balance\": \"8502\",\n    \"chargeMethod\": \"Wallet\",\n    \"channel\": \"API\",\n    \"customer_id\": \"2026100114328810455\",\n    \"server_response\": \"Transaction failed\",\n    \"createdOn\": \"2026-10-01 14:33:04\"\n}"
                        }
                    ]
                }
            ]
        },
        {
            "name": "Cable TV",
            "description": "DStv, GOtv and StarTimes. Get packages and add-ons, check a smartcard, then subscribe.",
            "item": [
                {
                    "name": "Get TV Packages",
                    "request": {
                        "method": "GET",
                        "header": [],
                        "url": {
                            "raw": "{{base_url}}get_tv_packages.php"
                        },
                        "description": "All active TV packages, grouped by package name, one entry per number of months. Cheapest first.\n\n**Notes**\n\n- Use `code` and `months` as `code` and `product_monthsPaidFor` in Purchase Cable TV.\n- `Plan_ID` is the plan code for the MSORG-style cable endpoint (sent there as `cableplan`); empty when that package has no MSORG plan.\n"
                    },
                    "response": [
                        {
                            "name": "Successful",
                            "originalRequest": {
                                "method": "GET",
                                "header": [],
                                "url": {
                                    "raw": "{{base_url}}get_tv_packages.php"
                                },
                                "description": "All active TV packages, grouped by package name, one entry per number of months. Cheapest first.\n\n**Notes**\n\n- Use `code` and `months` as `code` and `product_monthsPaidFor` in Purchase Cable TV.\n- `Plan_ID` is the plan code for the MSORG-style cable endpoint (sent there as `cableplan`); empty when that package has no MSORG plan.\n"
                            },
                            "status": "OK",
                            "code": 200,
                            "_postman_previewlanguage": "json",
                            "header": [
                                {
                                    "key": "Content-Type",
                                    "value": "application/json"
                                }
                            ],
                            "body": "{\n    \"DStv Yanga Bouquet E36\": [\n        {\n            \"title\": \"DStv Yanga Bouquet E36\",\n            \"service_type\": \"dstv\",\n            \"price\": \"4200\",\n            \"code\": \"NNJ1E36\",\n            \"Plan_ID\": \"34\",\n            \"months\": \"1\",\n            \"allowance\": \"1\",\n            \"s/n\": \"12\"\n        },\n        {\n            \"title\": \"DStv Yanga Bouquet E36\",\n            \"service_type\": \"dstv\",\n            \"price\": \"8400\",\n            \"code\": \"NNJ1E36\",\n            \"Plan_ID\": \"35\",\n            \"months\": \"2\",\n            \"allowance\": null,\n            \"s/n\": \"13\"\n        }\n    ]\n}"
                        }
                    ]
                },
                {
                    "name": "Get Add-on Packages",
                    "request": {
                        "method": "GET",
                        "header": [],
                        "url": {
                            "raw": "{{base_url}}get_tv_addon.php"
                        },
                        "description": "DStv / GOtv add-ons, grouped by add-on name, one entry per number of months.\n\n**Notes**\n\n- Send `addon_code` in Purchase Cable TV to add it. Add-ons are not available for StarTimes.\n"
                    },
                    "response": [
                        {
                            "name": "Successful",
                            "originalRequest": {
                                "method": "GET",
                                "header": [],
                                "url": {
                                    "raw": "{{base_url}}get_tv_addon.php"
                                },
                                "description": "DStv / GOtv add-ons, grouped by add-on name, one entry per number of months.\n\n**Notes**\n\n- Send `addon_code` in Purchase Cable TV to add it. Add-ons are not available for StarTimes.\n"
                            },
                            "status": "OK",
                            "code": 200,
                            "_postman_previewlanguage": "json",
                            "header": [
                                {
                                    "key": "Content-Type",
                                    "value": "application/json"
                                }
                            ],
                            "body": "{\n    \"French 11 Bouquet E36\": [\n        {\n            \"addon_title\": \"French 11 Bouquet E36\",\n            \"price\": \"5150\",\n            \"addon_code\": \"FRN11E36\",\n            \"months\": \"1\",\n            \"allowance\": null,\n            \"s/n\": \"1\"\n        }\n    ]\n}"
                        }
                    ]
                },
                {
                    "name": "Get SmartCard Info",
                    "request": {
                        "method": "POST",
                        "header": [
                            {
                                "key": "Content-Type",
                                "value": "application/json"
                            }
                        ],
                        "url": {
                            "raw": "{{base_url}}get_smartcard_info.php"
                        },
                        "description": "Check a smartcard / IUC number before paying -- the customer name, current bouquet and renewal amount. Free.\n\n**Body (JSON)**\n\n| Field | Required | Description |\n|---|---|---|\n| `SmartCard_no` (string) | Yes | The smartcard or IUC number. |\n| `service_type` (string) | Yes | `dstv`, `gotv` or `startimes`. |\n\n**Common errors**\n\n- `JO102` Missing field\n- `JO101` Lookup failed or service switched off\n- `109` No vendor set up for this service\n\n**Notes**\n\n- A field a vendor does not provide comes back as an empty string.\n",
                        "body": {
                            "mode": "raw",
                            "raw": "{\n    \"SmartCard_no\": \"7040373739\",\n    \"service_type\": \"dstv\"\n}",
                            "options": {
                                "raw": {
                                    "language": "json"
                                }
                            }
                        }
                    },
                    "response": [
                        {
                            "name": "DStv / GOtv",
                            "originalRequest": {
                                "method": "POST",
                                "header": [
                                    {
                                        "key": "Content-Type",
                                        "value": "application/json"
                                    }
                                ],
                                "url": {
                                    "raw": "{{base_url}}get_smartcard_info.php"
                                },
                                "description": "Check a smartcard / IUC number before paying -- the customer name, current bouquet and renewal amount. Free.\n\n**Body (JSON)**\n\n| Field | Required | Description |\n|---|---|---|\n| `SmartCard_no` (string) | Yes | The smartcard or IUC number. |\n| `service_type` (string) | Yes | `dstv`, `gotv` or `startimes`. |\n\n**Common errors**\n\n- `JO102` Missing field\n- `JO101` Lookup failed or service switched off\n- `109` No vendor set up for this service\n\n**Notes**\n\n- A field a vendor does not provide comes back as an empty string.\n",
                                "body": {
                                    "mode": "raw",
                                    "raw": "{\n    \"SmartCard_no\": \"7040373739\",\n    \"service_type\": \"dstv\"\n}",
                                    "options": {
                                        "raw": {
                                            "language": "json"
                                        }
                                    }
                                }
                            },
                            "status": "OK",
                            "code": 200,
                            "_postman_previewlanguage": "json",
                            "header": [
                                {
                                    "key": "Content-Type",
                                    "value": "application/json"
                                }
                            ],
                            "body": "{\n    \"responseCode\": \"200\",\n    \"status\": \"success\",\n    \"message\": \"Successful\",\n    \"data\": {\n        \"user\": {\n            \"customerName\": \"ADA OBI\",\n            \"outstandingBalance\": 0,\n            \"dueDate\": \"2026-10-23\",\n            \"Renewal_Amount\": 4200,\n            \"smartCardNumber\": \"7040373739\",\n            \"Customer_Number\": \"6347783\",\n            \"Status\": \"Open\"\n        },\n        \"hasDiscount\": \"true\",\n        \"currentBouquet\": \"DStv Yanga Bouquet E36\",\n        \"currentBouquetCode\": \"NNJ1E36\"\n    }\n}"
                        },
                        {
                            "name": "StarTimes",
                            "originalRequest": {
                                "method": "POST",
                                "header": [
                                    {
                                        "key": "Content-Type",
                                        "value": "application/json"
                                    }
                                ],
                                "url": {
                                    "raw": "{{base_url}}get_smartcard_info.php"
                                },
                                "description": "Check a smartcard / IUC number before paying -- the customer name, current bouquet and renewal amount. Free.\n\n**Body (JSON)**\n\n| Field | Required | Description |\n|---|---|---|\n| `SmartCard_no` (string) | Yes | The smartcard or IUC number. |\n| `service_type` (string) | Yes | `dstv`, `gotv` or `startimes`. |\n\n**Common errors**\n\n- `JO102` Missing field\n- `JO101` Lookup failed or service switched off\n- `109` No vendor set up for this service\n\n**Notes**\n\n- A field a vendor does not provide comes back as an empty string.\n",
                                "body": {
                                    "mode": "raw",
                                    "raw": "{\n    \"SmartCard_no\": \"7040373739\",\n    \"service_type\": \"dstv\"\n}",
                                    "options": {
                                        "raw": {
                                            "language": "json"
                                        }
                                    }
                                }
                            },
                            "status": "OK",
                            "code": 200,
                            "_postman_previewlanguage": "json",
                            "header": [
                                {
                                    "key": "Content-Type",
                                    "value": "application/json"
                                }
                            ],
                            "body": "{\n    \"responseCode\": \"200\",\n    \"status\": \"success\",\n    \"message\": \"Successful\",\n    \"data\": {\n        \"user\": {\n            \"customerName\": \"ADA OBI\",\n            \"outstandingBalance\": 0,\n            \"dueDate\": \"\",\n            \"balance\": \"0\",\n            \"smartCardNumber\": \"02134567890\",\n            \"accountNumber\": \"\"\n        },\n        \"hasDiscount\": \"false\",\n        \"currentBouquet\": \"Nova\"\n    }\n}"
                        }
                    ]
                },
                {
                    "name": "Purchase Cable TV",
                    "request": {
                        "method": "POST",
                        "header": [
                            {
                                "key": "Content-Type",
                                "value": "application/json"
                            }
                        ],
                        "url": {
                            "raw": "{{base_url}}purchase_tv.php"
                        },
                        "description": "Renew the current bouquet, or subscribe to a package (optionally with an add-on).\n\n**Body (JSON)**\n\n| Field | Required | Description |\n|---|---|---|\n| `SmartCard_no` (string) | Yes | The smartcard or IUC number. |\n| `service_type` (string) | Yes | `dstv`, `gotv` or `startimes`. |\n| `subscription_type` (string) | Yes | `renew` = renew / top up the current bouquet (uses any discount on the account). Anything else (e.g. `change`) = pay for the package in `code`. |\n| `code` (string) | For change | Package `code` from Get TV Packages. Ignored for renew (send `0`). |\n| `product_monthsPaidFor` (string) | For change | Number of months (from Get TV Packages). Ignored for renew. |\n| `amount` (number) | For renew | For renew: the amount to pay (e.g. Renewal_Amount from Get SmartCard Info). For change it is ignored -- the package price is always charged. |\n| `addon_code` (string) | No | An `addon_code` from Get Add-on Packages, or `0` for none. Not for StarTimes. |\n| `customer_id` (string) | Yes | Your unique reference -- see Customer ID. |\n\n**Common errors**\n\n- `JO102` Missing field\n- `JO104` customer_id format\n- `JO105` customer_id already used\n- `105` Unknown package code or months\n- `110` Insufficient balance, or renew amount is 0\n- `JO101` TV switched off, or renewal not supported for this provider\n- `JO123` Smartcard could not be verified -- not charged\n- `002 / 1005 / 1015` See response codes\n\n**Notes**\n\n- The failed reply has a different shape from success/processing (package details under `data`) -- this is long-standing behaviour.\n",
                        "body": {
                            "mode": "raw",
                            "raw": "{\n    \"SmartCard_no\": \"7040373739\",\n    \"subscription_type\": \"change\",\n    \"service_type\": \"dstv\",\n    \"code\": \"NNJ1E36\",\n    \"product_monthsPaidFor\": \"1\",\n    \"amount\": \"0\",\n    \"addon_code\": \"0\",\n    \"customer_id\": \"2026100114405590213\"\n}",
                            "options": {
                                "raw": {
                                    "language": "json"
                                }
                            }
                        }
                    },
                    "response": [
                        {
                            "name": "Successful (200)",
                            "originalRequest": {
                                "method": "POST",
                                "header": [
                                    {
                                        "key": "Content-Type",
                                        "value": "application/json"
                                    }
                                ],
                                "url": {
                                    "raw": "{{base_url}}purchase_tv.php"
                                },
                                "description": "Renew the current bouquet, or subscribe to a package (optionally with an add-on).\n\n**Body (JSON)**\n\n| Field | Required | Description |\n|---|---|---|\n| `SmartCard_no` (string) | Yes | The smartcard or IUC number. |\n| `service_type` (string) | Yes | `dstv`, `gotv` or `startimes`. |\n| `subscription_type` (string) | Yes | `renew` = renew / top up the current bouquet (uses any discount on the account). Anything else (e.g. `change`) = pay for the package in `code`. |\n| `code` (string) | For change | Package `code` from Get TV Packages. Ignored for renew (send `0`). |\n| `product_monthsPaidFor` (string) | For change | Number of months (from Get TV Packages). Ignored for renew. |\n| `amount` (number) | For renew | For renew: the amount to pay (e.g. Renewal_Amount from Get SmartCard Info). For change it is ignored -- the package price is always charged. |\n| `addon_code` (string) | No | An `addon_code` from Get Add-on Packages, or `0` for none. Not for StarTimes. |\n| `customer_id` (string) | Yes | Your unique reference -- see Customer ID. |\n\n**Common errors**\n\n- `JO102` Missing field\n- `JO104` customer_id format\n- `JO105` customer_id already used\n- `105` Unknown package code or months\n- `110` Insufficient balance, or renew amount is 0\n- `JO101` TV switched off, or renewal not supported for this provider\n- `JO123` Smartcard could not be verified -- not charged\n- `002 / 1005 / 1015` See response codes\n\n**Notes**\n\n- The failed reply has a different shape from success/processing (package details under `data`) -- this is long-standing behaviour.\n",
                                "body": {
                                    "mode": "raw",
                                    "raw": "{\n    \"SmartCard_no\": \"7040373739\",\n    \"subscription_type\": \"change\",\n    \"service_type\": \"dstv\",\n    \"code\": \"NNJ1E36\",\n    \"product_monthsPaidFor\": \"1\",\n    \"amount\": \"0\",\n    \"addon_code\": \"0\",\n    \"customer_id\": \"2026100114405590213\"\n}",
                                    "options": {
                                        "raw": {
                                            "language": "json"
                                        }
                                    }
                                }
                            },
                            "status": "OK",
                            "code": 200,
                            "_postman_previewlanguage": "json",
                            "header": [
                                {
                                    "key": "Content-Type",
                                    "value": "application/json"
                                }
                            ],
                            "body": "{\n    \"responseCode\": \"200\",\n    \"status\": \"Successful\",\n    \"message\": \"DStv Yanga Bouquet E36 dstv to 7040373739 Successful\",\n    \"receipent\": \"08031234567\",\n    \"email\": \"partner@example.com\",\n    \"amountcharged\": \"4137\",\n    \"commissionGiven\": \"63\",\n    \"balance\": \"35142\",\n    \"chargeMethod\": \"Wallet\",\n    \"channel\": \"API\",\n    \"customer_id\": \"2026100114405590213\",\n    \"vendor_id\": \"17592663\",\n    \"server_response\": \"TRANSACTION SUCCESSFUL\",\n    \"createdOn\": \"2026-10-01 14:40:59\"\n}"
                        },
                        {
                            "name": "Processing (203)",
                            "originalRequest": {
                                "method": "POST",
                                "header": [
                                    {
                                        "key": "Content-Type",
                                        "value": "application/json"
                                    }
                                ],
                                "url": {
                                    "raw": "{{base_url}}purchase_tv.php"
                                },
                                "description": "Renew the current bouquet, or subscribe to a package (optionally with an add-on).\n\n**Body (JSON)**\n\n| Field | Required | Description |\n|---|---|---|\n| `SmartCard_no` (string) | Yes | The smartcard or IUC number. |\n| `service_type` (string) | Yes | `dstv`, `gotv` or `startimes`. |\n| `subscription_type` (string) | Yes | `renew` = renew / top up the current bouquet (uses any discount on the account). Anything else (e.g. `change`) = pay for the package in `code`. |\n| `code` (string) | For change | Package `code` from Get TV Packages. Ignored for renew (send `0`). |\n| `product_monthsPaidFor` (string) | For change | Number of months (from Get TV Packages). Ignored for renew. |\n| `amount` (number) | For renew | For renew: the amount to pay (e.g. Renewal_Amount from Get SmartCard Info). For change it is ignored -- the package price is always charged. |\n| `addon_code` (string) | No | An `addon_code` from Get Add-on Packages, or `0` for none. Not for StarTimes. |\n| `customer_id` (string) | Yes | Your unique reference -- see Customer ID. |\n\n**Common errors**\n\n- `JO102` Missing field\n- `JO104` customer_id format\n- `JO105` customer_id already used\n- `105` Unknown package code or months\n- `110` Insufficient balance, or renew amount is 0\n- `JO101` TV switched off, or renewal not supported for this provider\n- `JO123` Smartcard could not be verified -- not charged\n- `002 / 1005 / 1015` See response codes\n\n**Notes**\n\n- The failed reply has a different shape from success/processing (package details under `data`) -- this is long-standing behaviour.\n",
                                "body": {
                                    "mode": "raw",
                                    "raw": "{\n    \"SmartCard_no\": \"7040373739\",\n    \"subscription_type\": \"change\",\n    \"service_type\": \"dstv\",\n    \"code\": \"NNJ1E36\",\n    \"product_monthsPaidFor\": \"1\",\n    \"amount\": \"0\",\n    \"addon_code\": \"0\",\n    \"customer_id\": \"2026100114405590213\"\n}",
                                    "options": {
                                        "raw": {
                                            "language": "json"
                                        }
                                    }
                                }
                            },
                            "status": "OK",
                            "code": 200,
                            "_postman_previewlanguage": "json",
                            "header": [
                                {
                                    "key": "Content-Type",
                                    "value": "application/json"
                                }
                            ],
                            "body": "{\n    \"responseCode\": \"203\",\n    \"status\": \"Processing\",\n    \"message\": \"DStv Yanga Bouquet E36 dstv to 7040373739 Processing\",\n    \"receipent\": \"08031234567\",\n    \"email\": \"partner@example.com\",\n    \"amountcharged\": \"4137\",\n    \"commissionGiven\": \"63\",\n    \"balance\": \"31005\",\n    \"chargeMethod\": \"Wallet\",\n    \"channel\": \"API\",\n    \"customer_id\": \"2026100114406612390\",\n    \"server_response\": \"\",\n    \"createdOn\": \"2026-10-01 14:41:02\"\n}"
                        },
                        {
                            "name": "Failed -- refunded (JO107; JO106 = network failure, adds server_response)",
                            "originalRequest": {
                                "method": "POST",
                                "header": [
                                    {
                                        "key": "Content-Type",
                                        "value": "application/json"
                                    }
                                ],
                                "url": {
                                    "raw": "{{base_url}}purchase_tv.php"
                                },
                                "description": "Renew the current bouquet, or subscribe to a package (optionally with an add-on).\n\n**Body (JSON)**\n\n| Field | Required | Description |\n|---|---|---|\n| `SmartCard_no` (string) | Yes | The smartcard or IUC number. |\n| `service_type` (string) | Yes | `dstv`, `gotv` or `startimes`. |\n| `subscription_type` (string) | Yes | `renew` = renew / top up the current bouquet (uses any discount on the account). Anything else (e.g. `change`) = pay for the package in `code`. |\n| `code` (string) | For change | Package `code` from Get TV Packages. Ignored for renew (send `0`). |\n| `product_monthsPaidFor` (string) | For change | Number of months (from Get TV Packages). Ignored for renew. |\n| `amount` (number) | For renew | For renew: the amount to pay (e.g. Renewal_Amount from Get SmartCard Info). For change it is ignored -- the package price is always charged. |\n| `addon_code` (string) | No | An `addon_code` from Get Add-on Packages, or `0` for none. Not for StarTimes. |\n| `customer_id` (string) | Yes | Your unique reference -- see Customer ID. |\n\n**Common errors**\n\n- `JO102` Missing field\n- `JO104` customer_id format\n- `JO105` customer_id already used\n- `105` Unknown package code or months\n- `110` Insufficient balance, or renew amount is 0\n- `JO101` TV switched off, or renewal not supported for this provider\n- `JO123` Smartcard could not be verified -- not charged\n- `002 / 1005 / 1015` See response codes\n\n**Notes**\n\n- The failed reply has a different shape from success/processing (package details under `data`) -- this is long-standing behaviour.\n",
                                "body": {
                                    "mode": "raw",
                                    "raw": "{\n    \"SmartCard_no\": \"7040373739\",\n    \"subscription_type\": \"change\",\n    \"service_type\": \"dstv\",\n    \"code\": \"NNJ1E36\",\n    \"product_monthsPaidFor\": \"1\",\n    \"amount\": \"0\",\n    \"addon_code\": \"0\",\n    \"customer_id\": \"2026100114405590213\"\n}",
                                    "options": {
                                        "raw": {
                                            "language": "json"
                                        }
                                    }
                                }
                            },
                            "status": "OK",
                            "code": 200,
                            "_postman_previewlanguage": "json",
                            "header": [
                                {
                                    "key": "Content-Type",
                                    "value": "application/json"
                                }
                            ],
                            "body": "{\n    \"responseCode\": \"JO107\",\n    \"status\": \"Failed\",\n    \"message\": \"Invalid smartcard number\",\n    \"phone\": \"08031234567\",\n    \"email\": \"partner@example.com\",\n    \"commissionGiven\": \"63\",\n    \"balance\": \"35142\",\n    \"data\": {\n        \"Service_type\": \"dstv\",\n        \"SmartCard_no\": \"7040373739\",\n        \"Package_type\": \"DStv Yanga Bouquet E36\",\n        \"amountcharged\": \"4137\",\n        \"months_paidfor\": \"1\",\n        \"addon\": \"0\"\n    },\n    \"chargeMethod\": \"Wallet\",\n    \"channel\": \"API\",\n    \"customer_id\": \"2026100114409910877\",\n    \"createdOn\": \"2026-10-01 14:41:08\"\n}"
                        }
                    ]
                }
            ]
        },
        {
            "name": "Electricity",
            "description": "Prepaid tokens and postpaid bill payments for every disco.",
            "item": [
                {
                    "name": "Get Discos",
                    "request": {
                        "method": "GET",
                        "header": [],
                        "url": {
                            "raw": "{{base_url}}get_disco.php"
                        },
                        "description": "All discos, prepaid and postpaid.\n\n**Notes**\n\n- Use `service_type` as `disco` in Get Meter Info and Purchase Electricity.\n"
                    },
                    "response": [
                        {
                            "name": "Successful",
                            "originalRequest": {
                                "method": "GET",
                                "header": [],
                                "url": {
                                    "raw": "{{base_url}}get_disco.php"
                                },
                                "description": "All discos, prepaid and postpaid.\n\n**Notes**\n\n- Use `service_type` as `disco` in Get Meter Info and Purchase Electricity.\n"
                            },
                            "status": "OK",
                            "code": 200,
                            "_postman_previewlanguage": "json",
                            "header": [
                                {
                                    "key": "Content-Type",
                                    "value": "application/json"
                                }
                            ],
                            "body": "[\n    {\n        \"title\": \"Ikeja Electric Prepaid\",\n        \"service_type\": \"ikeja_electric_prepaid\",\n        \"code\": \"ikeja\",\n        \"MeterType\": \"Prepaid\"\n    },\n    {\n        \"title\": \"Abuja Electric Postpaid\",\n        \"service_type\": \"abuja_electric_postpaid\",\n        \"code\": \"abuja\",\n        \"MeterType\": \"Postpaid\"\n    }\n]"
                        }
                    ]
                },
                {
                    "name": "Get Meter Info",
                    "request": {
                        "method": "POST",
                        "header": [
                            {
                                "key": "Content-Type",
                                "value": "application/json"
                            }
                        ],
                        "url": {
                            "raw": "{{base_url}}get_meter_info.php"
                        },
                        "description": "Check a meter number before paying -- customer name, address and minimum amount. Free.\n\n**Body (JSON)**\n\n| Field | Required | Description |\n|---|---|---|\n| `meter_no` (string) | Yes | The meter number. |\n| `disco` (string) | Yes | The disco `service_type` from Get Discos (e.g. `ikeja_electric_prepaid`). |\n\n**Common errors**\n\n- `JO102` Missing field\n- `JO101` Lookup failed or service switched off\n- `109` No vendor set up for this disco\n\n**Notes**\n\n- A field a vendor does not provide comes back as an empty string.\n",
                        "body": {
                            "mode": "raw",
                            "raw": "{\n    \"meter_no\": \"45067891234\",\n    \"disco\": \"ikeja_electric_prepaid\"\n}",
                            "options": {
                                "raw": {
                                    "language": "json"
                                }
                            }
                        }
                    },
                    "response": [
                        {
                            "name": "Successful",
                            "originalRequest": {
                                "method": "POST",
                                "header": [
                                    {
                                        "key": "Content-Type",
                                        "value": "application/json"
                                    }
                                ],
                                "url": {
                                    "raw": "{{base_url}}get_meter_info.php"
                                },
                                "description": "Check a meter number before paying -- customer name, address and minimum amount. Free.\n\n**Body (JSON)**\n\n| Field | Required | Description |\n|---|---|---|\n| `meter_no` (string) | Yes | The meter number. |\n| `disco` (string) | Yes | The disco `service_type` from Get Discos (e.g. `ikeja_electric_prepaid`). |\n\n**Common errors**\n\n- `JO102` Missing field\n- `JO101` Lookup failed or service switched off\n- `109` No vendor set up for this disco\n\n**Notes**\n\n- A field a vendor does not provide comes back as an empty string.\n",
                                "body": {
                                    "mode": "raw",
                                    "raw": "{\n    \"meter_no\": \"45067891234\",\n    \"disco\": \"ikeja_electric_prepaid\"\n}",
                                    "options": {
                                        "raw": {
                                            "language": "json"
                                        }
                                    }
                                }
                            },
                            "status": "OK",
                            "code": 200,
                            "_postman_previewlanguage": "json",
                            "header": [
                                {
                                    "key": "Content-Type",
                                    "value": "application/json"
                                }
                            ],
                            "body": "{\n    \"responseCode\": \"200\",\n    \"status\": \"success\",\n    \"message\": \"Successful\",\n    \"data\": {\n        \"minimumAmount\": 500,\n        \"outstandingBalance\": 0,\n        \"user\": {\n            \"customerName\": \"ADA OBI\",\n            \"address\": \"12 Allen Avenue, Ikeja\",\n            \"district\": \"Ikeja\",\n            \"meterNumber\": \"45067891234\",\n            \"accountNumber\": \"\",\n            \"paymentPlan\": \"Prepaid\",\n            \"tariff\": \"R2\",\n            \"rate\": \"\",\n            \"Customer_Number\": \"\",\n            \"Status\": \"Active\"\n        },\n        \"hasDiscount\": false,\n        \"errorMessage\": \"\"\n    }\n}"
                        }
                    ]
                },
                {
                    "name": "Purchase Electricity",
                    "request": {
                        "method": "POST",
                        "header": [
                            {
                                "key": "Content-Type",
                                "value": "application/json"
                            }
                        ],
                        "url": {
                            "raw": "{{base_url}}purchase_power.php"
                        },
                        "description": "Buy a prepaid token or pay a postpaid bill.\n\n**Body (JSON)**\n\n| Field | Required | Description |\n|---|---|---|\n| `meter_no` (string) | Yes | The meter number. |\n| `disco` (string) | Yes | The disco `service_type` from Get Discos (case-sensitive). |\n| `amount` (number) | Yes | Amount in Naira, at least 500. |\n| `phone` (string) | Yes | Phone number that receives the token by SMS. |\n| `customer_id` (string) | Yes | Your unique reference -- see Customer ID. |\n\n**Common errors**\n\n- `JO102` Missing field\n- `JO104` customer_id format\n- `JO105` customer_id already used\n- `105` Amount below 500, or unknown disco\n- `110` Insufficient balance\n- `JO101` Electricity switched off for this disco\n- `JO123` Meter could not be verified -- not charged\n- `2031 / 2032` Pending at the vendor -- Requery, not refunded\n- `002 / 1015` See response codes\n\n**Notes**\n\n- `user_details` is the meter name and address separated by `<br>`.\n",
                        "body": {
                            "mode": "raw",
                            "raw": "{\n    \"meter_no\": \"45067891234\",\n    \"disco\": \"ikeja_electric_prepaid\",\n    \"amount\": \"1000\",\n    \"phone\": \"08031234567\",\n    \"customer_id\": \"2026100114505512390\"\n}",
                            "options": {
                                "raw": {
                                    "language": "json"
                                }
                            }
                        }
                    },
                    "response": [
                        {
                            "name": "Successful (200)",
                            "originalRequest": {
                                "method": "POST",
                                "header": [
                                    {
                                        "key": "Content-Type",
                                        "value": "application/json"
                                    }
                                ],
                                "url": {
                                    "raw": "{{base_url}}purchase_power.php"
                                },
                                "description": "Buy a prepaid token or pay a postpaid bill.\n\n**Body (JSON)**\n\n| Field | Required | Description |\n|---|---|---|\n| `meter_no` (string) | Yes | The meter number. |\n| `disco` (string) | Yes | The disco `service_type` from Get Discos (case-sensitive). |\n| `amount` (number) | Yes | Amount in Naira, at least 500. |\n| `phone` (string) | Yes | Phone number that receives the token by SMS. |\n| `customer_id` (string) | Yes | Your unique reference -- see Customer ID. |\n\n**Common errors**\n\n- `JO102` Missing field\n- `JO104` customer_id format\n- `JO105` customer_id already used\n- `105` Amount below 500, or unknown disco\n- `110` Insufficient balance\n- `JO101` Electricity switched off for this disco\n- `JO123` Meter could not be verified -- not charged\n- `2031 / 2032` Pending at the vendor -- Requery, not refunded\n- `002 / 1015` See response codes\n\n**Notes**\n\n- `user_details` is the meter name and address separated by `<br>`.\n",
                                "body": {
                                    "mode": "raw",
                                    "raw": "{\n    \"meter_no\": \"45067891234\",\n    \"disco\": \"ikeja_electric_prepaid\",\n    \"amount\": \"1000\",\n    \"phone\": \"08031234567\",\n    \"customer_id\": \"2026100114505512390\"\n}",
                                    "options": {
                                        "raw": {
                                            "language": "json"
                                        }
                                    }
                                }
                            },
                            "status": "OK",
                            "code": 200,
                            "_postman_previewlanguage": "json",
                            "header": [
                                {
                                    "key": "Content-Type",
                                    "value": "application/json"
                                }
                            ],
                            "body": "{\n    \"responseCode\": \"200\",\n    \"status\": \"Successful\",\n    \"message\": \"\",\n    \"receipent\": \"08031234567\",\n    \"email\": \"partner@example.com\",\n    \"amountcharged\": \"988\",\n    \"commissionGiven\": \"12\",\n    \"balance\": \"34012\",\n    \"chargeMethod\": \"Wallet\",\n    \"channel\": \"API\",\n    \"service_type\": \"ikeja_electric_prepaid\",\n    \"user_details\": \"ADA OBI<br>12 Allen Avenue, Ikeja\",\n    \"meter_token\": \"3515-3990-0297-6774-2452\",\n    \"unit\": \"14.6\",\n    \"customer_id\": \"2026100114505512390\",\n    \"createdOn\": \"2026-10-01 14:50:59\"\n}"
                        },
                        {
                            "name": "Processing (203) -- token empty until it completes",
                            "originalRequest": {
                                "method": "POST",
                                "header": [
                                    {
                                        "key": "Content-Type",
                                        "value": "application/json"
                                    }
                                ],
                                "url": {
                                    "raw": "{{base_url}}purchase_power.php"
                                },
                                "description": "Buy a prepaid token or pay a postpaid bill.\n\n**Body (JSON)**\n\n| Field | Required | Description |\n|---|---|---|\n| `meter_no` (string) | Yes | The meter number. |\n| `disco` (string) | Yes | The disco `service_type` from Get Discos (case-sensitive). |\n| `amount` (number) | Yes | Amount in Naira, at least 500. |\n| `phone` (string) | Yes | Phone number that receives the token by SMS. |\n| `customer_id` (string) | Yes | Your unique reference -- see Customer ID. |\n\n**Common errors**\n\n- `JO102` Missing field\n- `JO104` customer_id format\n- `JO105` customer_id already used\n- `105` Amount below 500, or unknown disco\n- `110` Insufficient balance\n- `JO101` Electricity switched off for this disco\n- `JO123` Meter could not be verified -- not charged\n- `2031 / 2032` Pending at the vendor -- Requery, not refunded\n- `002 / 1015` See response codes\n\n**Notes**\n\n- `user_details` is the meter name and address separated by `<br>`.\n",
                                "body": {
                                    "mode": "raw",
                                    "raw": "{\n    \"meter_no\": \"45067891234\",\n    \"disco\": \"ikeja_electric_prepaid\",\n    \"amount\": \"1000\",\n    \"phone\": \"08031234567\",\n    \"customer_id\": \"2026100114505512390\"\n}",
                                    "options": {
                                        "raw": {
                                            "language": "json"
                                        }
                                    }
                                }
                            },
                            "status": "OK",
                            "code": 200,
                            "_postman_previewlanguage": "json",
                            "header": [
                                {
                                    "key": "Content-Type",
                                    "value": "application/json"
                                }
                            ],
                            "body": "{\n    \"responseCode\": \"203\",\n    \"status\": \"Processing\",\n    \"message\": \"\",\n    \"receipent\": \"08031234567\",\n    \"email\": \"partner@example.com\",\n    \"amountcharged\": \"988\",\n    \"commissionGiven\": \"12\",\n    \"balance\": \"33024\",\n    \"chargeMethod\": \"Wallet\",\n    \"channel\": \"API\",\n    \"service_type\": \"ikeja_electric_prepaid\",\n    \"user_details\": \"ADA OBI<br>12 Allen Avenue, Ikeja\",\n    \"meter_token\": \"\",\n    \"unit\": \"\",\n    \"customer_id\": \"2026100114506601234\",\n    \"createdOn\": \"2026-10-01 14:51:03\"\n}"
                        },
                        {
                            "name": "Failed -- refunded (JO1061; JO106 = network failure, adds server_response)",
                            "originalRequest": {
                                "method": "POST",
                                "header": [
                                    {
                                        "key": "Content-Type",
                                        "value": "application/json"
                                    }
                                ],
                                "url": {
                                    "raw": "{{base_url}}purchase_power.php"
                                },
                                "description": "Buy a prepaid token or pay a postpaid bill.\n\n**Body (JSON)**\n\n| Field | Required | Description |\n|---|---|---|\n| `meter_no` (string) | Yes | The meter number. |\n| `disco` (string) | Yes | The disco `service_type` from Get Discos (case-sensitive). |\n| `amount` (number) | Yes | Amount in Naira, at least 500. |\n| `phone` (string) | Yes | Phone number that receives the token by SMS. |\n| `customer_id` (string) | Yes | Your unique reference -- see Customer ID. |\n\n**Common errors**\n\n- `JO102` Missing field\n- `JO104` customer_id format\n- `JO105` customer_id already used\n- `105` Amount below 500, or unknown disco\n- `110` Insufficient balance\n- `JO101` Electricity switched off for this disco\n- `JO123` Meter could not be verified -- not charged\n- `2031 / 2032` Pending at the vendor -- Requery, not refunded\n- `002 / 1015` See response codes\n\n**Notes**\n\n- `user_details` is the meter name and address separated by `<br>`.\n",
                                "body": {
                                    "mode": "raw",
                                    "raw": "{\n    \"meter_no\": \"45067891234\",\n    \"disco\": \"ikeja_electric_prepaid\",\n    \"amount\": \"1000\",\n    \"phone\": \"08031234567\",\n    \"customer_id\": \"2026100114505512390\"\n}",
                                    "options": {
                                        "raw": {
                                            "language": "json"
                                        }
                                    }
                                }
                            },
                            "status": "OK",
                            "code": 200,
                            "_postman_previewlanguage": "json",
                            "header": [
                                {
                                    "key": "Content-Type",
                                    "value": "application/json"
                                }
                            ],
                            "body": "{\n    \"responseCode\": \"JO1061\",\n    \"status\": \"Failed\",\n    \"message\": \"\",\n    \"receipent\": \"08031234567\",\n    \"email\": \"partner@example.com\",\n    \"amountcharged\": \"988\",\n    \"commissionGiven\": \"12\",\n    \"balance\": \"34012\",\n    \"chargeMethod\": \"Wallet\",\n    \"channel\": \"API\",\n    \"service_type\": \"ikeja_electric_prepaid\",\n    \"user_details\": \"ADA OBI<br>12 Allen Avenue, Ikeja\",\n    \"meter_token\": \"\",\n    \"unit\": \"\",\n    \"customer_id\": \"2026100114507789001\",\n    \"createdOn\": \"2026-10-01 14:51:09\"\n}"
                        }
                    ]
                }
            ]
        },
        {
            "name": "E-Pins",
            "description": "Recharge-card pins (MTN, Glo, Airtel, 9mobile) and WAEC / NECO / JAMB exam pins.",
            "item": [
                {
                    "name": "Get E-Pin Plans",
                    "request": {
                        "method": "GET",
                        "header": [],
                        "url": {
                            "raw": "{{base_url}}get_epin_plans.php?network=",
                            "query": [
                                {
                                    "key": "network",
                                    "value": "",
                                    "description": "Optional filter: `MTN`, `Glo`, `Airtel`, `Etisalat`, `waec`, `neco`, `jamb`.",
                                    "disabled": true
                                }
                            ]
                        },
                        "description": "E-Pin plans with their price and what you pay per pin.\n\n**Query parameters**\n\n| Field | Required | Description |\n|---|---|---|\n| `network` (string) | No | Optional filter: `MTN`, `Glo`, `Airtel`, `Etisalat`, `waec`, `neco`, `jamb`. |\n\n**Notes**\n\n- `price` = face value per pin; `amount_charged` = what you pay per pin; `available: false` = out of stock (`stock` is a count only for plans sold from JoNet's own stock).\n"
                    },
                    "response": [
                        {
                            "name": "Successful",
                            "originalRequest": {
                                "method": "GET",
                                "header": [],
                                "url": {
                                    "raw": "{{base_url}}get_epin_plans.php?network=",
                                    "query": [
                                        {
                                            "key": "network",
                                            "value": "",
                                            "description": "Optional filter: `MTN`, `Glo`, `Airtel`, `Etisalat`, `waec`, `neco`, `jamb`.",
                                            "disabled": true
                                        }
                                    ]
                                },
                                "description": "E-Pin plans with their price and what you pay per pin.\n\n**Query parameters**\n\n| Field | Required | Description |\n|---|---|---|\n| `network` (string) | No | Optional filter: `MTN`, `Glo`, `Airtel`, `Etisalat`, `waec`, `neco`, `jamb`. |\n\n**Notes**\n\n- `price` = face value per pin; `amount_charged` = what you pay per pin; `available: false` = out of stock (`stock` is a count only for plans sold from JoNet's own stock).\n"
                            },
                            "status": "OK",
                            "code": 200,
                            "_postman_previewlanguage": "json",
                            "header": [
                                {
                                    "key": "Content-Type",
                                    "value": "application/json"
                                }
                            ],
                            "body": "{\n    \"responseCode\": \"200\",\n    \"status\": \"Successful\",\n    \"plans\": [\n        {\n            \"plan\": \"12\",\n            \"network\": \"MTN\",\n            \"name\": \"MTN 100\",\n            \"price\": 100,\n            \"amount_charged\": 98,\n            \"available\": true,\n            \"stock\": null\n        }\n    ]\n}"
                        }
                    ]
                },
                {
                    "name": "Purchase E-Pin",
                    "request": {
                        "method": "POST",
                        "header": [
                            {
                                "key": "Content-Type",
                                "value": "application/json"
                            }
                        ],
                        "url": {
                            "raw": "{{base_url}}purchase_epin.php"
                        },
                        "description": "Buy one or more pins. The pins and serials are in the reply.\n\n**Body (JSON)**\n\n| Field | Required | Description |\n|---|---|---|\n| `plan` (string) | Yes | The `plan` from Get E-Pin Plans. |\n| `quantity` (number) | Yes | 1 to 20 (JAMB is always 1). |\n| `phone` (string) | For WAEC/JAMB | Required for WAEC and JAMB. |\n| `profile_id` (string) | For JAMB | The candidate's JAMB Profile ID. Required for JAMB. |\n| `customer_id` (string) | Yes | Your unique reference -- see Customer ID. |\n\n**Common errors**\n\n- `JO102` Missing field\n- `JO104` customer_id format\n- `JO105` customer_id already used\n- `105` Unknown plan, quantity out of range, missing phone / profile_id, or plan unavailable\n- `424` Out of stock (or not enough for the quantity)\n- `110` Insufficient balance\n- `JO107` Vendor refused -- refunded\n- `JO101` E-Pins switched off\n- `002 / 1015` See response codes\n",
                        "body": {
                            "mode": "raw",
                            "raw": "{\n    \"plan\": \"12\",\n    \"quantity\": 3,\n    \"phone\": \"08031234567\",\n    \"profile_id\": \"\",\n    \"customer_id\": \"2026100115005512345\"\n}",
                            "options": {
                                "raw": {
                                    "language": "json"
                                }
                            }
                        }
                    },
                    "response": [
                        {
                            "name": "Successful (200)",
                            "originalRequest": {
                                "method": "POST",
                                "header": [
                                    {
                                        "key": "Content-Type",
                                        "value": "application/json"
                                    }
                                ],
                                "url": {
                                    "raw": "{{base_url}}purchase_epin.php"
                                },
                                "description": "Buy one or more pins. The pins and serials are in the reply.\n\n**Body (JSON)**\n\n| Field | Required | Description |\n|---|---|---|\n| `plan` (string) | Yes | The `plan` from Get E-Pin Plans. |\n| `quantity` (number) | Yes | 1 to 20 (JAMB is always 1). |\n| `phone` (string) | For WAEC/JAMB | Required for WAEC and JAMB. |\n| `profile_id` (string) | For JAMB | The candidate's JAMB Profile ID. Required for JAMB. |\n| `customer_id` (string) | Yes | Your unique reference -- see Customer ID. |\n\n**Common errors**\n\n- `JO102` Missing field\n- `JO104` customer_id format\n- `JO105` customer_id already used\n- `105` Unknown plan, quantity out of range, missing phone / profile_id, or plan unavailable\n- `424` Out of stock (or not enough for the quantity)\n- `110` Insufficient balance\n- `JO107` Vendor refused -- refunded\n- `JO101` E-Pins switched off\n- `002 / 1015` See response codes\n",
                                "body": {
                                    "mode": "raw",
                                    "raw": "{\n    \"plan\": \"12\",\n    \"quantity\": 3,\n    \"phone\": \"08031234567\",\n    \"profile_id\": \"\",\n    \"customer_id\": \"2026100115005512345\"\n}",
                                    "options": {
                                        "raw": {
                                            "language": "json"
                                        }
                                    }
                                }
                            },
                            "status": "OK",
                            "code": 200,
                            "_postman_previewlanguage": "json",
                            "header": [
                                {
                                    "key": "Content-Type",
                                    "value": "application/json"
                                }
                            ],
                            "body": "{\n    \"responseCode\": \"200\",\n    \"status\": \"Successful\",\n    \"message\": \"Successful\",\n    \"pins\": [\n        \"1234-5678-9012\",\n        \"2234-5678-9013\",\n        \"3234-5678-9014\"\n    ],\n    \"serials\": [\n        \"SN0001\",\n        \"SN0002\",\n        \"SN0003\"\n    ],\n    \"plan\": \"MTN 100\",\n    \"network\": \"MTN\",\n    \"quantity\": 3,\n    \"amountcharged\": 294,\n    \"commissionGiven\": 6,\n    \"balance\": 5000,\n    \"chargeMethod\": \"Wallet\",\n    \"channel\": \"API\",\n    \"customer_id\": \"2026100115005512345\",\n    \"createdOn\": \"2026-10-01 15:00:59\"\n}"
                        },
                        {
                            "name": "Processing (203) -- pins come later; Requery returns them",
                            "originalRequest": {
                                "method": "POST",
                                "header": [
                                    {
                                        "key": "Content-Type",
                                        "value": "application/json"
                                    }
                                ],
                                "url": {
                                    "raw": "{{base_url}}purchase_epin.php"
                                },
                                "description": "Buy one or more pins. The pins and serials are in the reply.\n\n**Body (JSON)**\n\n| Field | Required | Description |\n|---|---|---|\n| `plan` (string) | Yes | The `plan` from Get E-Pin Plans. |\n| `quantity` (number) | Yes | 1 to 20 (JAMB is always 1). |\n| `phone` (string) | For WAEC/JAMB | Required for WAEC and JAMB. |\n| `profile_id` (string) | For JAMB | The candidate's JAMB Profile ID. Required for JAMB. |\n| `customer_id` (string) | Yes | Your unique reference -- see Customer ID. |\n\n**Common errors**\n\n- `JO102` Missing field\n- `JO104` customer_id format\n- `JO105` customer_id already used\n- `105` Unknown plan, quantity out of range, missing phone / profile_id, or plan unavailable\n- `424` Out of stock (or not enough for the quantity)\n- `110` Insufficient balance\n- `JO107` Vendor refused -- refunded\n- `JO101` E-Pins switched off\n- `002 / 1015` See response codes\n",
                                "body": {
                                    "mode": "raw",
                                    "raw": "{\n    \"plan\": \"12\",\n    \"quantity\": 3,\n    \"phone\": \"08031234567\",\n    \"profile_id\": \"\",\n    \"customer_id\": \"2026100115005512345\"\n}",
                                    "options": {
                                        "raw": {
                                            "language": "json"
                                        }
                                    }
                                }
                            },
                            "status": "OK",
                            "code": 200,
                            "_postman_previewlanguage": "json",
                            "header": [
                                {
                                    "key": "Content-Type",
                                    "value": "application/json"
                                }
                            ],
                            "body": "{\n    \"responseCode\": \"203\",\n    \"status\": \"Processing\",\n    \"message\": \"\",\n    \"pins\": [],\n    \"serials\": [],\n    \"plan\": \"MTN 100\",\n    \"network\": \"MTN\",\n    \"quantity\": 3,\n    \"amountcharged\": 294,\n    \"commissionGiven\": 6,\n    \"balance\": 4706,\n    \"chargeMethod\": \"Wallet\",\n    \"channel\": \"API\",\n    \"customer_id\": \"2026100115006612345\",\n    \"createdOn\": \"2026-10-01 15:01:03\"\n}"
                        }
                    ]
                }
            ]
        },
        {
            "name": "Airtime to Cash",
            "description": "Your customer converts airtime on their own SIM; the payout goes to your wallet. Three steps, all within 15 minutes.",
            "item": [
                {
                    "name": "Get Airtime to Cash Networks",
                    "request": {
                        "method": "GET",
                        "header": [],
                        "url": {
                            "raw": "{{base_url}}get_a2c_networks.php"
                        },
                        "description": "Networks and rates. Only networks with `can_do_auto` ON work with the steps below.\n\n**Notes**\n\n- `percentage` is the rate paid on the converted amount.\n"
                    },
                    "response": [
                        {
                            "name": "Successful",
                            "originalRequest": {
                                "method": "GET",
                                "header": [],
                                "url": {
                                    "raw": "{{base_url}}get_a2c_networks.php"
                                },
                                "description": "Networks and rates. Only networks with `can_do_auto` ON work with the steps below.\n\n**Notes**\n\n- `percentage` is the rate paid on the converted amount.\n"
                            },
                            "status": "OK",
                            "code": 200,
                            "_postman_previewlanguage": "json",
                            "header": [
                                {
                                    "key": "Content-Type",
                                    "value": "application/json"
                                }
                            ],
                            "body": "[\n    {\n        \"network\": \"MTN\",\n        \"percentage\": \"80\",\n        \"can_do_auto\": \"ON\",\n        \"recipient\": \"08012345678\"\n    }\n]"
                        }
                    ]
                },
                {
                    "name": "Start Airtime to Cash",
                    "request": {
                        "method": "POST",
                        "header": [
                            {
                                "key": "Content-Type",
                                "value": "application/json"
                            }
                        ],
                        "url": {
                            "raw": "{{base_url}}a2c_start.php"
                        },
                        "description": "Starts a conversion and sends an OTP to the SIM.\n\n**Body (JSON)**\n\n| Field | Required | Description |\n|---|---|---|\n| `phone` (string) | Yes | The SIM holding the airtime (11 digits). |\n| `amount` (number) | Yes | Airtime to convert, up to 20,000. |\n| `network` (string) | Yes | A network from Get Airtime to Cash Networks with `can_do_auto` ON. |\n| `share_pin` (string) | Yes | The SIM's airtime-share PIN. Used once, never stored. |\n\n**Common errors**\n\n- `JO102` Missing field\n- `424` Network not automatic, invalid phone/amount, or amount too small after fees\n- `409` Wallet busy\n- `429` More than 5 starts a minute from your IP\n- `500` Try again\n",
                        "body": {
                            "mode": "raw",
                            "raw": "{\n    \"phone\": \"08031234567\",\n    \"amount\": 2000,\n    \"network\": \"MTN\",\n    \"share_pin\": \"1234\"\n}",
                            "options": {
                                "raw": {
                                    "language": "json"
                                }
                            }
                        }
                    },
                    "response": [
                        {
                            "name": "Successful",
                            "originalRequest": {
                                "method": "POST",
                                "header": [
                                    {
                                        "key": "Content-Type",
                                        "value": "application/json"
                                    }
                                ],
                                "url": {
                                    "raw": "{{base_url}}a2c_start.php"
                                },
                                "description": "Starts a conversion and sends an OTP to the SIM.\n\n**Body (JSON)**\n\n| Field | Required | Description |\n|---|---|---|\n| `phone` (string) | Yes | The SIM holding the airtime (11 digits). |\n| `amount` (number) | Yes | Airtime to convert, up to 20,000. |\n| `network` (string) | Yes | A network from Get Airtime to Cash Networks with `can_do_auto` ON. |\n| `share_pin` (string) | Yes | The SIM's airtime-share PIN. Used once, never stored. |\n\n**Common errors**\n\n- `JO102` Missing field\n- `424` Network not automatic, invalid phone/amount, or amount too small after fees\n- `409` Wallet busy\n- `429` More than 5 starts a minute from your IP\n- `500` Try again\n",
                                "body": {
                                    "mode": "raw",
                                    "raw": "{\n    \"phone\": \"08031234567\",\n    \"amount\": 2000,\n    \"network\": \"MTN\",\n    \"share_pin\": \"1234\"\n}",
                                    "options": {
                                        "raw": {
                                            "language": "json"
                                        }
                                    }
                                }
                            },
                            "status": "OK",
                            "code": 200,
                            "_postman_previewlanguage": "json",
                            "header": [
                                {
                                    "key": "Content-Type",
                                    "value": "application/json"
                                }
                            ],
                            "body": "{\n    \"responseCode\": \"200\",\n    \"status\": \"Successful\",\n    \"reference\": \"2026100115104412345\",\n    \"message\": \"OTP sent.\"\n}"
                        }
                    ]
                },
                {
                    "name": "Complete Airtime to Cash",
                    "request": {
                        "method": "POST",
                        "header": [
                            {
                                "key": "Content-Type",
                                "value": "application/json"
                            }
                        ],
                        "url": {
                            "raw": "{{base_url}}a2c_complete.php"
                        },
                        "description": "Confirms the OTP; the payout is credited to your wallet.\n\n**Body (JSON)**\n\n| Field | Required | Description |\n|---|---|---|\n| `reference` (string) | Yes | The `reference` from Start. |\n| `otp` (string) | Yes | The OTP the SIM received. |\n| `share_pin` (string) | Yes | The SIM's airtime-share PIN again. |\n\n**Common errors**\n\n- `JO102` Missing field\n- `424` Wrong OTP (try again or resend), not enough airtime, no longer pending, vendor refused, or \"needs manual review\" (airtime received -- support credits it)\n- `409` Wallet busy\n\n**Notes**\n\n- Payout = converted amount × the rate, minus NGN 50 per NGN 5,000 shared.\n",
                        "body": {
                            "mode": "raw",
                            "raw": "{\n    \"reference\": \"2026100115104412345\",\n    \"otp\": \"123456\",\n    \"share_pin\": \"1234\"\n}",
                            "options": {
                                "raw": {
                                    "language": "json"
                                }
                            }
                        }
                    },
                    "response": [
                        {
                            "name": "Successful",
                            "originalRequest": {
                                "method": "POST",
                                "header": [
                                    {
                                        "key": "Content-Type",
                                        "value": "application/json"
                                    }
                                ],
                                "url": {
                                    "raw": "{{base_url}}a2c_complete.php"
                                },
                                "description": "Confirms the OTP; the payout is credited to your wallet.\n\n**Body (JSON)**\n\n| Field | Required | Description |\n|---|---|---|\n| `reference` (string) | Yes | The `reference` from Start. |\n| `otp` (string) | Yes | The OTP the SIM received. |\n| `share_pin` (string) | Yes | The SIM's airtime-share PIN again. |\n\n**Common errors**\n\n- `JO102` Missing field\n- `424` Wrong OTP (try again or resend), not enough airtime, no longer pending, vendor refused, or \"needs manual review\" (airtime received -- support credits it)\n- `409` Wallet busy\n\n**Notes**\n\n- Payout = converted amount × the rate, minus NGN 50 per NGN 5,000 shared.\n",
                                "body": {
                                    "mode": "raw",
                                    "raw": "{\n    \"reference\": \"2026100115104412345\",\n    \"otp\": \"123456\",\n    \"share_pin\": \"1234\"\n}",
                                    "options": {
                                        "raw": {
                                            "language": "json"
                                        }
                                    }
                                }
                            },
                            "status": "OK",
                            "code": 200,
                            "_postman_previewlanguage": "json",
                            "header": [
                                {
                                    "key": "Content-Type",
                                    "value": "application/json"
                                }
                            ],
                            "body": "{\n    \"responseCode\": \"200\",\n    \"status\": \"Successful\",\n    \"reference\": \"2026100115104412345\",\n    \"amount\": 2000,\n    \"payout\": 1550,\n    \"balance\": 51550,\n    \"message\": \"Airtime converted successfully.\"\n}"
                        }
                    ]
                },
                {
                    "name": "Resend Airtime to Cash OTP",
                    "request": {
                        "method": "POST",
                        "header": [
                            {
                                "key": "Content-Type",
                                "value": "application/json"
                            }
                        ],
                        "url": {
                            "raw": "{{base_url}}a2c_resend.php"
                        },
                        "description": "Sends the OTP again.\n\n**Body (JSON)**\n\n| Field | Required | Description |\n|---|---|---|\n| `reference` (string) | Yes | The `reference` from Start. |\n\n**Common errors**\n\n- `JO102` Missing field\n- `424` No longer pending\n- `500` Try again\n",
                        "body": {
                            "mode": "raw",
                            "raw": "{\n    \"reference\": \"2026100115104412345\"\n}",
                            "options": {
                                "raw": {
                                    "language": "json"
                                }
                            }
                        }
                    },
                    "response": [
                        {
                            "name": "Successful",
                            "originalRequest": {
                                "method": "POST",
                                "header": [
                                    {
                                        "key": "Content-Type",
                                        "value": "application/json"
                                    }
                                ],
                                "url": {
                                    "raw": "{{base_url}}a2c_resend.php"
                                },
                                "description": "Sends the OTP again.\n\n**Body (JSON)**\n\n| Field | Required | Description |\n|---|---|---|\n| `reference` (string) | Yes | The `reference` from Start. |\n\n**Common errors**\n\n- `JO102` Missing field\n- `424` No longer pending\n- `500` Try again\n",
                                "body": {
                                    "mode": "raw",
                                    "raw": "{\n    \"reference\": \"2026100115104412345\"\n}",
                                    "options": {
                                        "raw": {
                                            "language": "json"
                                        }
                                    }
                                }
                            },
                            "status": "OK",
                            "code": 200,
                            "_postman_previewlanguage": "json",
                            "header": [
                                {
                                    "key": "Content-Type",
                                    "value": "application/json"
                                }
                            ],
                            "body": "{\n    \"responseCode\": \"200\",\n    \"status\": \"Successful\",\n    \"message\": \"OTP resent.\"\n}"
                        }
                    ]
                }
            ]
        },
        {
            "name": "Event Tickets",
            "description": "Sell tickets to events on JoNet, or list your own events. Ticket purchases are instant: tickets are issued (or nothing is charged) in the same call -- there is no Pending state.",
            "item": [
                {
                    "name": "Get Events",
                    "request": {
                        "method": "GET",
                        "header": [],
                        "url": {
                            "raw": "{{base_url}}get_events.php"
                        },
                        "description": "Approved events that haven't ended, soonest first (up to 100), with their ticket categories.\n\n**Notes**\n\n- Use the event `id` and a tier `id` in Purchase Ticket.\n"
                    },
                    "response": [
                        {
                            "name": "Successful",
                            "originalRequest": {
                                "method": "GET",
                                "header": [],
                                "url": {
                                    "raw": "{{base_url}}get_events.php"
                                },
                                "description": "Approved events that haven't ended, soonest first (up to 100), with their ticket categories.\n\n**Notes**\n\n- Use the event `id` and a tier `id` in Purchase Ticket.\n"
                            },
                            "status": "OK",
                            "code": 200,
                            "_postman_previewlanguage": "json",
                            "header": [
                                {
                                    "key": "Content-Type",
                                    "value": "application/json"
                                }
                            ],
                            "body": "{\n    \"responseCode\": \"200\",\n    \"status\": \"Successful\",\n    \"events\": [\n        {\n            \"id\": \"JENT1791065965412\",\n            \"name\": \"Lagos Jazz Night\",\n            \"venue\": \"Eko Hall, VI\",\n            \"date\": \"2026-11-14 18:00:00\",\n            \"edate\": \"2026-11-14 23:00:00\",\n            \"description\": \"Live jazz.\",\n            \"picture\": \"https://res.cloudinary.com/.../event.jpg\",\n            \"organizer\": \"Ola Events\",\n            \"tiers\": [\n                {\n                    \"id\": \"31\",\n                    \"category\": \"Regular\",\n                    \"price\": \"3000.00\"\n                },\n                {\n                    \"id\": \"32\",\n                    \"category\": \"VIP\",\n                    \"price\": \"20000.00\"\n                }\n            ]\n        }\n    ]\n}"
                        }
                    ]
                },
                {
                    "name": "Purchase Ticket",
                    "request": {
                        "method": "POST",
                        "header": [
                            {
                                "key": "Content-Type",
                                "value": "application/json"
                            }
                        ],
                        "url": {
                            "raw": "{{base_url}}purchase_ticket.php"
                        },
                        "description": "Buy tickets for your customer from your wallet, at the full ticket price.\n\n**Body (JSON)**\n\n| Field | Required | Description |\n|---|---|---|\n| `event_id` (string) | Yes | From Get Events. |\n| `tier_id` (number) | Yes | A ticket category `id` of that event. |\n| `quantity` (number) | Yes | 1 to 10. |\n| `customer_id` (string) | Yes | Your unique reference -- see Customer ID. Sending the same one again returns the original tickets; nothing is bought twice. Reusing it for a DIFFERENT order (other event, tier, quantity or holder) is refused with 409. |\n| `holder_name` (string) | Yes | Your customer's name -- printed on every ticket and seen by the organizer. |\n| `holder_phone` (string) | Yes | Your customer's phone number. |\n| `holder_email` (string) | Yes | Your customer's email. |\n| `attendees` (array) | No | Optional: `[{name, phone, email}, ...]` with exactly one entry per ticket, to put a different person on each ticket (then holder_* can be left out). |\n\n**Common errors**\n\n- `JO102` Missing or invalid field (holder details, attendees count, quantity)\n- `JO104` customer_id format\n- `105` Event or ticket category not found\n- `JO101` Event not open for sales, or already ended\n- `110` Insufficient balance\n- `JO121` Negative wallet balance\n- `1015` Account not eligible, or it is your own event\n- `409` This customer_id is still processing -- check it with Get Ticket\n\n**Notes**\n\n- Failures charge nothing. Your account is recorded as the buyer who paid; the holder is your customer.\n- Send your customer the `ticket_url` (or the code / barcode) -- it is checked at the gate.\n",
                        "body": {
                            "mode": "raw",
                            "raw": "{\n    \"event_id\": \"JENT1791065965412\",\n    \"tier_id\": 31,\n    \"quantity\": 2,\n    \"customer_id\": \"2026100114305581234\",\n    \"holder_name\": \"Ada Obi\",\n    \"holder_phone\": \"08031234567\",\n    \"holder_email\": \"ada@example.com\"\n}",
                            "options": {
                                "raw": {
                                    "language": "json"
                                }
                            }
                        }
                    },
                    "response": [
                        {
                            "name": "Successful (200)",
                            "originalRequest": {
                                "method": "POST",
                                "header": [
                                    {
                                        "key": "Content-Type",
                                        "value": "application/json"
                                    }
                                ],
                                "url": {
                                    "raw": "{{base_url}}purchase_ticket.php"
                                },
                                "description": "Buy tickets for your customer from your wallet, at the full ticket price.\n\n**Body (JSON)**\n\n| Field | Required | Description |\n|---|---|---|\n| `event_id` (string) | Yes | From Get Events. |\n| `tier_id` (number) | Yes | A ticket category `id` of that event. |\n| `quantity` (number) | Yes | 1 to 10. |\n| `customer_id` (string) | Yes | Your unique reference -- see Customer ID. Sending the same one again returns the original tickets; nothing is bought twice. Reusing it for a DIFFERENT order (other event, tier, quantity or holder) is refused with 409. |\n| `holder_name` (string) | Yes | Your customer's name -- printed on every ticket and seen by the organizer. |\n| `holder_phone` (string) | Yes | Your customer's phone number. |\n| `holder_email` (string) | Yes | Your customer's email. |\n| `attendees` (array) | No | Optional: `[{name, phone, email}, ...]` with exactly one entry per ticket, to put a different person on each ticket (then holder_* can be left out). |\n\n**Common errors**\n\n- `JO102` Missing or invalid field (holder details, attendees count, quantity)\n- `JO104` customer_id format\n- `105` Event or ticket category not found\n- `JO101` Event not open for sales, or already ended\n- `110` Insufficient balance\n- `JO121` Negative wallet balance\n- `1015` Account not eligible, or it is your own event\n- `409` This customer_id is still processing -- check it with Get Ticket\n\n**Notes**\n\n- Failures charge nothing. Your account is recorded as the buyer who paid; the holder is your customer.\n- Send your customer the `ticket_url` (or the code / barcode) -- it is checked at the gate.\n",
                                "body": {
                                    "mode": "raw",
                                    "raw": "{\n    \"event_id\": \"JENT1791065965412\",\n    \"tier_id\": 31,\n    \"quantity\": 2,\n    \"customer_id\": \"2026100114305581234\",\n    \"holder_name\": \"Ada Obi\",\n    \"holder_phone\": \"08031234567\",\n    \"holder_email\": \"ada@example.com\"\n}",
                                    "options": {
                                        "raw": {
                                            "language": "json"
                                        }
                                    }
                                }
                            },
                            "status": "OK",
                            "code": 200,
                            "_postman_previewlanguage": "json",
                            "header": [
                                {
                                    "key": "Content-Type",
                                    "value": "application/json"
                                }
                            ],
                            "body": "{\n    \"responseCode\": \"200\",\n    \"status\": \"Successful\",\n    \"message\": \"Ticket purchase successful.\",\n    \"event_name\": \"Lagos Jazz Night\",\n    \"quantity\": 2,\n    \"amountcharged\": 6000,\n    \"balance\": \"44000.00\",\n    \"chargeMethod\": \"Wallet\",\n    \"channel\": \"API\",\n    \"customer_id\": \"2026100114305581234\",\n    \"tickets\": [\n        {\n            \"ticket_code\": \"TKT9F2C41A7B0\",\n            \"status\": \"valid\",\n            \"category\": \"Regular\",\n            \"price\": \"3000.00\",\n            \"holder_name\": \"Ada Obi\",\n            \"holder_phone\": \"08031234567\",\n            \"holder_email\": \"ada@example.com\",\n            \"event_id\": \"JENT1791065965412\",\n            \"event_name\": \"Lagos Jazz Night\",\n            \"venue\": \"Eko Hall, VI\",\n            \"date\": \"2026-11-14 18:00:00\",\n            \"edate\": \"2026-11-14 23:00:00\",\n            \"purchased_at\": \"2026-10-01 14:30:57\",\n            \"barcode_url\": \"https://jonet.com.ng/barcode.php?codetype=code128&print=true&text=TKT9F2C41A7B0\",\n            \"ticket_url\": \"https://jonet.com.ng/guest_ticket_reprint.php?code=TKT9F2C41A7B0\"\n        }\n    ],\n    \"createdOn\": \"2026-10-01 14:30:57\"\n}"
                        },
                        {
                            "name": "Rejected (example)",
                            "originalRequest": {
                                "method": "POST",
                                "header": [
                                    {
                                        "key": "Content-Type",
                                        "value": "application/json"
                                    }
                                ],
                                "url": {
                                    "raw": "{{base_url}}purchase_ticket.php"
                                },
                                "description": "Buy tickets for your customer from your wallet, at the full ticket price.\n\n**Body (JSON)**\n\n| Field | Required | Description |\n|---|---|---|\n| `event_id` (string) | Yes | From Get Events. |\n| `tier_id` (number) | Yes | A ticket category `id` of that event. |\n| `quantity` (number) | Yes | 1 to 10. |\n| `customer_id` (string) | Yes | Your unique reference -- see Customer ID. Sending the same one again returns the original tickets; nothing is bought twice. Reusing it for a DIFFERENT order (other event, tier, quantity or holder) is refused with 409. |\n| `holder_name` (string) | Yes | Your customer's name -- printed on every ticket and seen by the organizer. |\n| `holder_phone` (string) | Yes | Your customer's phone number. |\n| `holder_email` (string) | Yes | Your customer's email. |\n| `attendees` (array) | No | Optional: `[{name, phone, email}, ...]` with exactly one entry per ticket, to put a different person on each ticket (then holder_* can be left out). |\n\n**Common errors**\n\n- `JO102` Missing or invalid field (holder details, attendees count, quantity)\n- `JO104` customer_id format\n- `105` Event or ticket category not found\n- `JO101` Event not open for sales, or already ended\n- `110` Insufficient balance\n- `JO121` Negative wallet balance\n- `1015` Account not eligible, or it is your own event\n- `409` This customer_id is still processing -- check it with Get Ticket\n\n**Notes**\n\n- Failures charge nothing. Your account is recorded as the buyer who paid; the holder is your customer.\n- Send your customer the `ticket_url` (or the code / barcode) -- it is checked at the gate.\n",
                                "body": {
                                    "mode": "raw",
                                    "raw": "{\n    \"event_id\": \"JENT1791065965412\",\n    \"tier_id\": 31,\n    \"quantity\": 2,\n    \"customer_id\": \"2026100114305581234\",\n    \"holder_name\": \"Ada Obi\",\n    \"holder_phone\": \"08031234567\",\n    \"holder_email\": \"ada@example.com\"\n}",
                                    "options": {
                                        "raw": {
                                            "language": "json"
                                        }
                                    }
                                }
                            },
                            "status": "OK",
                            "code": 200,
                            "_postman_previewlanguage": "json",
                            "header": [
                                {
                                    "key": "Content-Type",
                                    "value": "application/json"
                                }
                            ],
                            "body": "{\n    \"message\": \"Insufficient wallet balance for this purchase.\",\n    \"responseCode\": \"110\",\n    \"status\": \"Failed\"\n}"
                        }
                    ]
                },
                {
                    "name": "Get Ticket",
                    "request": {
                        "method": "GET",
                        "header": [],
                        "url": {
                            "raw": "{{base_url}}get_ticket.php?customer_id=2026100114305581234&ticket_code=",
                            "query": [
                                {
                                    "key": "customer_id",
                                    "value": "2026100114305581234",
                                    "description": "The order's customer_id -- returns its tickets and the order status.",
                                    "disabled": true
                                },
                                {
                                    "key": "ticket_code",
                                    "value": "",
                                    "description": "One code, or several separated by commas (max 50). Send this or customer_id.",
                                    "disabled": true
                                }
                            ]
                        },
                        "description": "Look up tickets by your customer_id, or by ticket code. Shows whether a ticket is valid, used or refunded.\n\n**Query parameters**\n\n| Field | Required | Description |\n|---|---|---|\n| `customer_id` (string) | No | The order's customer_id -- returns its tickets and the order status. |\n| `ticket_code` (string) | No | One code, or several separated by commas (max 50). Send this or customer_id. |\n\n**Common errors**\n\n- `JO102` Send customer_id or ticket_code\n- `JO110` Not found, or not yours\n- `JO119` The order is still processing\n\n**Notes**\n\n- You can see tickets you bought, and every ticket of an event you organize. A Failed order charged nothing. Ticket entries carry the same fields as in Purchase Ticket.\n"
                    },
                    "response": [
                        {
                            "name": "By customer_id",
                            "originalRequest": {
                                "method": "GET",
                                "header": [],
                                "url": {
                                    "raw": "{{base_url}}get_ticket.php?customer_id=2026100114305581234&ticket_code=",
                                    "query": [
                                        {
                                            "key": "customer_id",
                                            "value": "2026100114305581234",
                                            "description": "The order's customer_id -- returns its tickets and the order status.",
                                            "disabled": true
                                        },
                                        {
                                            "key": "ticket_code",
                                            "value": "",
                                            "description": "One code, or several separated by commas (max 50). Send this or customer_id.",
                                            "disabled": true
                                        }
                                    ]
                                },
                                "description": "Look up tickets by your customer_id, or by ticket code. Shows whether a ticket is valid, used or refunded.\n\n**Query parameters**\n\n| Field | Required | Description |\n|---|---|---|\n| `customer_id` (string) | No | The order's customer_id -- returns its tickets and the order status. |\n| `ticket_code` (string) | No | One code, or several separated by commas (max 50). Send this or customer_id. |\n\n**Common errors**\n\n- `JO102` Send customer_id or ticket_code\n- `JO110` Not found, or not yours\n- `JO119` The order is still processing\n\n**Notes**\n\n- You can see tickets you bought, and every ticket of an event you organize. A Failed order charged nothing. Ticket entries carry the same fields as in Purchase Ticket.\n"
                            },
                            "status": "OK",
                            "code": 200,
                            "_postman_previewlanguage": "json",
                            "header": [
                                {
                                    "key": "Content-Type",
                                    "value": "application/json"
                                }
                            ],
                            "body": "{\n    \"responseCode\": \"200\",\n    \"status\": \"Successful\",\n    \"order\": {\n        \"customer_id\": \"2026100114305581234\",\n        \"status\": \"Successful\",\n        \"message\": \"Ticket purchase successful.\"\n    },\n    \"tickets\": [\n        {\n            \"ticket_code\": \"TKT9F2C41A7B0\",\n            \"status\": \"valid\",\n            \"category\": \"Regular\",\n            \"price\": \"3000.00\",\n            \"holder_name\": \"Ada Obi\",\n            \"event_name\": \"Lagos Jazz Night\"\n        }\n    ]\n}"
                        },
                        {
                            "name": "Not found",
                            "originalRequest": {
                                "method": "GET",
                                "header": [],
                                "url": {
                                    "raw": "{{base_url}}get_ticket.php?customer_id=2026100114305581234&ticket_code=",
                                    "query": [
                                        {
                                            "key": "customer_id",
                                            "value": "2026100114305581234",
                                            "description": "The order's customer_id -- returns its tickets and the order status.",
                                            "disabled": true
                                        },
                                        {
                                            "key": "ticket_code",
                                            "value": "",
                                            "description": "One code, or several separated by commas (max 50). Send this or customer_id.",
                                            "disabled": true
                                        }
                                    ]
                                },
                                "description": "Look up tickets by your customer_id, or by ticket code. Shows whether a ticket is valid, used or refunded.\n\n**Query parameters**\n\n| Field | Required | Description |\n|---|---|---|\n| `customer_id` (string) | No | The order's customer_id -- returns its tickets and the order status. |\n| `ticket_code` (string) | No | One code, or several separated by commas (max 50). Send this or customer_id. |\n\n**Common errors**\n\n- `JO102` Send customer_id or ticket_code\n- `JO110` Not found, or not yours\n- `JO119` The order is still processing\n\n**Notes**\n\n- You can see tickets you bought, and every ticket of an event you organize. A Failed order charged nothing. Ticket entries carry the same fields as in Purchase Ticket.\n"
                            },
                            "status": "OK",
                            "code": 200,
                            "_postman_previewlanguage": "json",
                            "header": [
                                {
                                    "key": "Content-Type",
                                    "value": "application/json"
                                }
                            ],
                            "body": "{\n    \"message\": \"Transaction not found\",\n    \"responseCode\": \"JO110\",\n    \"status\": \"Failed\"\n}"
                        }
                    ]
                },
                {
                    "name": "Get Event Fees",
                    "request": {
                        "method": "GET",
                        "header": [],
                        "url": {
                            "raw": "{{base_url}}get_event_fees.php"
                        },
                        "description": "JoNet's current fees for events you list.\n\n**Notes**\n\n- Paid tickets: JoNet keeps `paid_ticket_percent` of each sale; you receive the rest (the buyer pays the ticket price).\n- Free events (every category free): one flat `free_event_fee` per event, taken from your wallet when you submit it and refunded if it isn't approved. Attendees pay nothing.\n- The rates in force when you submit an event stay with that event. 0 = no fee.\n"
                    },
                    "response": [
                        {
                            "name": "Successful",
                            "originalRequest": {
                                "method": "GET",
                                "header": [],
                                "url": {
                                    "raw": "{{base_url}}get_event_fees.php"
                                },
                                "description": "JoNet's current fees for events you list.\n\n**Notes**\n\n- Paid tickets: JoNet keeps `paid_ticket_percent` of each sale; you receive the rest (the buyer pays the ticket price).\n- Free events (every category free): one flat `free_event_fee` per event, taken from your wallet when you submit it and refunded if it isn't approved. Attendees pay nothing.\n- The rates in force when you submit an event stay with that event. 0 = no fee.\n"
                            },
                            "status": "OK",
                            "code": 200,
                            "_postman_previewlanguage": "json",
                            "header": [
                                {
                                    "key": "Content-Type",
                                    "value": "application/json"
                                }
                            ],
                            "body": "{\n    \"responseCode\": \"200\",\n    \"status\": \"Successful\",\n    \"paid_ticket_percent\": 5,\n    \"free_event_fee\": 500,\n    \"terms\": \"Paid tickets: JoNet keeps 5% of each ticket sold; you receive the rest. Free events (every ticket free): a one-off listing fee of NGN 500.00 is taken from your wallet when you submit the event, and refunded if the event is not approved. Attendees pay nothing.\"\n}"
                        }
                    ]
                },
                {
                    "name": "Create Event",
                    "request": {
                        "method": "POST",
                        "header": [],
                        "url": {
                            "raw": "{{base_url}}create_event.php"
                        },
                        "description": "Submit your own event for sale. It starts pending and is sold once JoNet approves it.\n\n**Body (JSON)**\n\n| Field | Required | Description |\n|---|---|---|\n| `name, venue, description` (string) | Yes | Event details. |\n| `start_date, end_date` (string) | Yes | `YYYY-MM-DD`. |\n| `start_time, end_time` (string) | Yes | `HH:MM` (24-hour). |\n| `category[], price[]` (array) | Yes | One pair per ticket category; a blank or 0 price = free. |\n| `picture` (file) | Yes | JPEG, PNG, GIF or WEBP, up to 5 MB. |\n| `idempotency_key` (string) | No | Your unique reference for this submission. Sending the same one again (e.g. after a lost reply) returns the first result -- no second event or listing fee. Reusing it for a different event is refused. |\n\n**Common errors**\n\n- `JO102` Missing or invalid field or picture\n- `110` Not enough balance for a free event's listing fee\n- `1015` Account not eligible\n- `500` Try again\n\n**Notes**\n\n- Send as `multipart/form-data` (not JSON), up to 11 MB. 20 events per account per hour.\n- `listing_fee` = what was taken now (free events only); `fee_percent` = JoNet's share of each paid ticket for this event. See Get Event Fees.\n"
                    },
                    "response": [
                        {
                            "name": "Successful",
                            "originalRequest": {
                                "method": "POST",
                                "header": [],
                                "url": {
                                    "raw": "{{base_url}}create_event.php"
                                },
                                "description": "Submit your own event for sale. It starts pending and is sold once JoNet approves it.\n\n**Body (JSON)**\n\n| Field | Required | Description |\n|---|---|---|\n| `name, venue, description` (string) | Yes | Event details. |\n| `start_date, end_date` (string) | Yes | `YYYY-MM-DD`. |\n| `start_time, end_time` (string) | Yes | `HH:MM` (24-hour). |\n| `category[], price[]` (array) | Yes | One pair per ticket category; a blank or 0 price = free. |\n| `picture` (file) | Yes | JPEG, PNG, GIF or WEBP, up to 5 MB. |\n| `idempotency_key` (string) | No | Your unique reference for this submission. Sending the same one again (e.g. after a lost reply) returns the first result -- no second event or listing fee. Reusing it for a different event is refused. |\n\n**Common errors**\n\n- `JO102` Missing or invalid field or picture\n- `110` Not enough balance for a free event's listing fee\n- `1015` Account not eligible\n- `500` Try again\n\n**Notes**\n\n- Send as `multipart/form-data` (not JSON), up to 11 MB. 20 events per account per hour.\n- `listing_fee` = what was taken now (free events only); `fee_percent` = JoNet's share of each paid ticket for this event. See Get Event Fees.\n"
                            },
                            "status": "OK",
                            "code": 200,
                            "_postman_previewlanguage": "json",
                            "header": [
                                {
                                    "key": "Content-Type",
                                    "value": "application/json"
                                }
                            ],
                            "body": "{\n    \"responseCode\": \"200\",\n    \"status\": \"Successful\",\n    \"message\": \"Event submitted for approval.\",\n    \"event_id\": \"JENT1791065965412\",\n    \"listing_fee\": 0,\n    \"fee_percent\": 5\n}"
                        }
                    ]
                },
                {
                    "name": "My Events",
                    "request": {
                        "method": "GET",
                        "header": [],
                        "url": {
                            "raw": "{{base_url}}my_events.php?event_id=&page=&limit=",
                            "query": [
                                {
                                    "key": "event_id",
                                    "value": "",
                                    "description": "One of your events, to list its tickets.",
                                    "disabled": true
                                },
                                {
                                    "key": "page",
                                    "value": "",
                                    "description": "Page number, from 1 (default 1).",
                                    "disabled": true
                                },
                                {
                                    "key": "limit",
                                    "value": "",
                                    "description": "Rows per page (default 100, max 500).",
                                    "disabled": true
                                }
                            ]
                        },
                        "description": "Events you organize with their status and tickets sold -- or, with event_id, the tickets sold for that event. Newest first, one page at a time.\n\n**Query parameters**\n\n| Field | Required | Description |\n|---|---|---|\n| `event_id` (string) | No | One of your events, to list its tickets. |\n| `page` (integer) | No | Page number, from 1 (default 1). |\n| `limit` (integer) | No | Rows per page (default 100, max 500). |\n\n**Common errors**\n\n- `JO110` Not your event\n\n**Notes**\n\n- status: pending (awaiting approval), approved (on sale), banned, closed.\n- has_more: true means there are more rows -- request the same URL with page + 1.\n"
                    },
                    "response": [
                        {
                            "name": "Your events",
                            "originalRequest": {
                                "method": "GET",
                                "header": [],
                                "url": {
                                    "raw": "{{base_url}}my_events.php?event_id=&page=&limit=",
                                    "query": [
                                        {
                                            "key": "event_id",
                                            "value": "",
                                            "description": "One of your events, to list its tickets.",
                                            "disabled": true
                                        },
                                        {
                                            "key": "page",
                                            "value": "",
                                            "description": "Page number, from 1 (default 1).",
                                            "disabled": true
                                        },
                                        {
                                            "key": "limit",
                                            "value": "",
                                            "description": "Rows per page (default 100, max 500).",
                                            "disabled": true
                                        }
                                    ]
                                },
                                "description": "Events you organize with their status and tickets sold -- or, with event_id, the tickets sold for that event. Newest first, one page at a time.\n\n**Query parameters**\n\n| Field | Required | Description |\n|---|---|---|\n| `event_id` (string) | No | One of your events, to list its tickets. |\n| `page` (integer) | No | Page number, from 1 (default 1). |\n| `limit` (integer) | No | Rows per page (default 100, max 500). |\n\n**Common errors**\n\n- `JO110` Not your event\n\n**Notes**\n\n- status: pending (awaiting approval), approved (on sale), banned, closed.\n- has_more: true means there are more rows -- request the same URL with page + 1.\n"
                            },
                            "status": "OK",
                            "code": 200,
                            "_postman_previewlanguage": "json",
                            "header": [
                                {
                                    "key": "Content-Type",
                                    "value": "application/json"
                                }
                            ],
                            "body": "{\n    \"responseCode\": \"200\",\n    \"status\": \"Successful\",\n    \"events\": [\n        {\n            \"id\": \"JENT1791065965412\",\n            \"name\": \"Lagos Jazz Night\",\n            \"venue\": \"Eko Hall, VI\",\n            \"date\": \"2026-11-14 18:00:00\",\n            \"edate\": \"2026-11-14 23:00:00\",\n            \"picture\": \"https://res.cloudinary.com/.../event.jpg\",\n            \"status\": \"approved\",\n            \"tickets_sold\": \"42\",\n            \"fee_percent\": \"5.00\",\n            \"listing_fee\": \"0.00\"\n        }\n    ],\n    \"page\": 1,\n    \"limit\": 100,\n    \"has_more\": false\n}"
                        },
                        {
                            "name": "One event's tickets",
                            "originalRequest": {
                                "method": "GET",
                                "header": [],
                                "url": {
                                    "raw": "{{base_url}}my_events.php?event_id=&page=&limit=",
                                    "query": [
                                        {
                                            "key": "event_id",
                                            "value": "",
                                            "description": "One of your events, to list its tickets.",
                                            "disabled": true
                                        },
                                        {
                                            "key": "page",
                                            "value": "",
                                            "description": "Page number, from 1 (default 1).",
                                            "disabled": true
                                        },
                                        {
                                            "key": "limit",
                                            "value": "",
                                            "description": "Rows per page (default 100, max 500).",
                                            "disabled": true
                                        }
                                    ]
                                },
                                "description": "Events you organize with their status and tickets sold -- or, with event_id, the tickets sold for that event. Newest first, one page at a time.\n\n**Query parameters**\n\n| Field | Required | Description |\n|---|---|---|\n| `event_id` (string) | No | One of your events, to list its tickets. |\n| `page` (integer) | No | Page number, from 1 (default 1). |\n| `limit` (integer) | No | Rows per page (default 100, max 500). |\n\n**Common errors**\n\n- `JO110` Not your event\n\n**Notes**\n\n- status: pending (awaiting approval), approved (on sale), banned, closed.\n- has_more: true means there are more rows -- request the same URL with page + 1.\n"
                            },
                            "status": "OK",
                            "code": 200,
                            "_postman_previewlanguage": "json",
                            "header": [
                                {
                                    "key": "Content-Type",
                                    "value": "application/json"
                                }
                            ],
                            "body": "{\n    \"responseCode\": \"200\",\n    \"status\": \"Successful\",\n    \"event_id\": \"JENT1791065965412\",\n    \"tickets\": [\n        {\n            \"ticket_code\": \"TKT9F2C41A7B0\",\n            \"holder_name\": \"Ada Obi\",\n            \"holder_phone\": \"08031234567\",\n            \"holder_email\": \"ada@example.com\",\n            \"buyer_name\": \"Part Ner\",\n            \"category\": \"Regular\",\n            \"price\": \"3000.00\",\n            \"status\": \"valid\",\n            \"purchased_at\": \"2026-10-01 14:30:57\"\n        }\n    ],\n    \"page\": 1,\n    \"limit\": 100,\n    \"has_more\": false\n}"
                        }
                    ]
                }
            ]
        },
        {
            "name": "Requery & Webhook",
            "description": "Check an order's final status, or ask for its webhook again.",
            "item": [
                {
                    "name": "Requery",
                    "request": {
                        "method": "GET",
                        "header": [],
                        "url": {
                            "raw": "{{base_url}}requery.php?customer_id=2026100114305581234",
                            "query": [
                                {
                                    "key": "customer_id",
                                    "value": "2026100114305581234",
                                    "description": "The customer_id you sent with the purchase.",
                                    "disabled": false
                                }
                            ]
                        },
                        "description": "The current status of an order, by your customer_id. Use it after any Processing / unclear reply, or a timeout.\n\n**Query parameters**\n\n| Field | Required | Description |\n|---|---|---|\n| `customer_id` (string) | Yes | The customer_id you sent with the purchase. |\n\n**Common errors**\n\n- `JO102` Missing customer_id\n- `JO110` No order with that customer_id on your account\n\n**Notes**\n\n- `responseCode` is `200` whenever the order is found. The order's real state is in `status` (Successful, Failed, Pending, Processing).\n- The Data/Airtime reply spells the payment field `chargeMothed` (long-standing; the other services use `chargeMethod`).\n"
                    },
                    "response": [
                        {
                            "name": "Data / Airtime",
                            "originalRequest": {
                                "method": "GET",
                                "header": [],
                                "url": {
                                    "raw": "{{base_url}}requery.php?customer_id=2026100114305581234",
                                    "query": [
                                        {
                                            "key": "customer_id",
                                            "value": "2026100114305581234",
                                            "description": "The customer_id you sent with the purchase.",
                                            "disabled": false
                                        }
                                    ]
                                },
                                "description": "The current status of an order, by your customer_id. Use it after any Processing / unclear reply, or a timeout.\n\n**Query parameters**\n\n| Field | Required | Description |\n|---|---|---|\n| `customer_id` (string) | Yes | The customer_id you sent with the purchase. |\n\n**Common errors**\n\n- `JO102` Missing customer_id\n- `JO110` No order with that customer_id on your account\n\n**Notes**\n\n- `responseCode` is `200` whenever the order is found. The order's real state is in `status` (Successful, Failed, Pending, Processing).\n- The Data/Airtime reply spells the payment field `chargeMothed` (long-standing; the other services use `chargeMethod`).\n"
                            },
                            "status": "OK",
                            "code": 200,
                            "_postman_previewlanguage": "json",
                            "header": [
                                {
                                    "key": "Content-Type",
                                    "value": "application/json"
                                }
                            ],
                            "body": "{\n    \"responseCode\": \"200\",\n    \"status\": \"Successful\",\n    \"recharge_type\": \"Data\",\n    \"receipent\": \"08031234567\",\n    \"email\": \"partner@example.com\",\n    \"amountcharged\": \"228\",\n    \"commissionGiven\": \"12\",\n    \"balance\": \"8600\",\n    \"chargeMothed\": \"Wallet\",\n    \"channel\": \"API\",\n    \"customer_id\": \"2026100114305581234\",\n    \"vendor_id\": \"13397889\",\n    \"server_response\": \"Dear Customer, You have successfully shared 1GB Data to 2348031234567.\",\n    \"createdOn\": \"2026-10-01 14:30:55\"\n}"
                        },
                        {
                            "name": "Electricity",
                            "originalRequest": {
                                "method": "GET",
                                "header": [],
                                "url": {
                                    "raw": "{{base_url}}requery.php?customer_id=2026100114305581234",
                                    "query": [
                                        {
                                            "key": "customer_id",
                                            "value": "2026100114305581234",
                                            "description": "The customer_id you sent with the purchase.",
                                            "disabled": false
                                        }
                                    ]
                                },
                                "description": "The current status of an order, by your customer_id. Use it after any Processing / unclear reply, or a timeout.\n\n**Query parameters**\n\n| Field | Required | Description |\n|---|---|---|\n| `customer_id` (string) | Yes | The customer_id you sent with the purchase. |\n\n**Common errors**\n\n- `JO102` Missing customer_id\n- `JO110` No order with that customer_id on your account\n\n**Notes**\n\n- `responseCode` is `200` whenever the order is found. The order's real state is in `status` (Successful, Failed, Pending, Processing).\n- The Data/Airtime reply spells the payment field `chargeMothed` (long-standing; the other services use `chargeMethod`).\n"
                            },
                            "status": "OK",
                            "code": 200,
                            "_postman_previewlanguage": "json",
                            "header": [
                                {
                                    "key": "Content-Type",
                                    "value": "application/json"
                                }
                            ],
                            "body": "{\n    \"responseCode\": \"200\",\n    \"status\": \"Successful\",\n    \"recharge_type\": \"ENERGY BILL\",\n    \"receipent\": \"08031234567\",\n    \"email\": \"partner@example.com\",\n    \"amountcharged\": \"988\",\n    \"commissionGiven\": \"12\",\n    \"balance\": \"34012\",\n    \"chargeMethod\": \"Wallet\",\n    \"channel\": \"API\",\n    \"service_type\": \"ikeja_electric_prepaid\",\n    \"user_details\": \"ADA OBI\",\n    \"meter_token\": \"3515-3990-0297-6774-2452\",\n    \"unit\": \"14.6\",\n    \"customer_id\": \"2026100114505512390\",\n    \"createdOn\": \"2026-10-01 14:50:59\"\n}"
                        },
                        {
                            "name": "Cable TV",
                            "originalRequest": {
                                "method": "GET",
                                "header": [],
                                "url": {
                                    "raw": "{{base_url}}requery.php?customer_id=2026100114305581234",
                                    "query": [
                                        {
                                            "key": "customer_id",
                                            "value": "2026100114305581234",
                                            "description": "The customer_id you sent with the purchase.",
                                            "disabled": false
                                        }
                                    ]
                                },
                                "description": "The current status of an order, by your customer_id. Use it after any Processing / unclear reply, or a timeout.\n\n**Query parameters**\n\n| Field | Required | Description |\n|---|---|---|\n| `customer_id` (string) | Yes | The customer_id you sent with the purchase. |\n\n**Common errors**\n\n- `JO102` Missing customer_id\n- `JO110` No order with that customer_id on your account\n\n**Notes**\n\n- `responseCode` is `200` whenever the order is found. The order's real state is in `status` (Successful, Failed, Pending, Processing).\n- The Data/Airtime reply spells the payment field `chargeMothed` (long-standing; the other services use `chargeMethod`).\n"
                            },
                            "status": "OK",
                            "code": 200,
                            "_postman_previewlanguage": "json",
                            "header": [
                                {
                                    "key": "Content-Type",
                                    "value": "application/json"
                                }
                            ],
                            "body": "{\n    \"responseCode\": \"200\",\n    \"status\": \"Successful\",\n    \"recharge_type\": \"Digital tv\",\n    \"phone\": \"08031234567\",\n    \"email\": \"partner@example.com\",\n    \"commissionGiven\": \"63\",\n    \"balance\": \"35142\",\n    \"Service_type\": \"dstv\",\n    \"SmartCard_no\": \"7040373739\",\n    \"amountcharged\": \"4137\",\n    \"months_paidfor\": \"1\",\n    \"chargeMethod\": \"Wallet\",\n    \"channel\": \"API\",\n    \"customer_id\": \"2026100114405590213\",\n    \"createdOn\": \"2026-10-01 14:40:59\"\n}"
                        },
                        {
                            "name": "E-Pin -- pins filled once Successful",
                            "originalRequest": {
                                "method": "GET",
                                "header": [],
                                "url": {
                                    "raw": "{{base_url}}requery.php?customer_id=2026100114305581234",
                                    "query": [
                                        {
                                            "key": "customer_id",
                                            "value": "2026100114305581234",
                                            "description": "The customer_id you sent with the purchase.",
                                            "disabled": false
                                        }
                                    ]
                                },
                                "description": "The current status of an order, by your customer_id. Use it after any Processing / unclear reply, or a timeout.\n\n**Query parameters**\n\n| Field | Required | Description |\n|---|---|---|\n| `customer_id` (string) | Yes | The customer_id you sent with the purchase. |\n\n**Common errors**\n\n- `JO102` Missing customer_id\n- `JO110` No order with that customer_id on your account\n\n**Notes**\n\n- `responseCode` is `200` whenever the order is found. The order's real state is in `status` (Successful, Failed, Pending, Processing).\n- The Data/Airtime reply spells the payment field `chargeMothed` (long-standing; the other services use `chargeMethod`).\n"
                            },
                            "status": "OK",
                            "code": 200,
                            "_postman_previewlanguage": "json",
                            "header": [
                                {
                                    "key": "Content-Type",
                                    "value": "application/json"
                                }
                            ],
                            "body": "{\n    \"responseCode\": \"200\",\n    \"status\": \"Successful\",\n    \"recharge_type\": \"E-Pin\",\n    \"plan\": \"MTN 100\",\n    \"network\": \"MTN\",\n    \"receipent\": \"08031234567\",\n    \"email\": \"partner@example.com\",\n    \"pins\": [\n        \"1234-5678-9012\"\n    ],\n    \"serials\": [\n        \"SN0001\"\n    ],\n    \"amountcharged\": \"98\",\n    \"commissionGiven\": \"2\",\n    \"balance\": \"5000\",\n    \"chargeMethod\": \"Wallet\",\n    \"channel\": \"API\",\n    \"customer_id\": \"2026100115005512345\",\n    \"vendor_id\": \"\",\n    \"createdOn\": \"2026-10-01 15:00:59\"\n}"
                        },
                        {
                            "name": "Not found",
                            "originalRequest": {
                                "method": "GET",
                                "header": [],
                                "url": {
                                    "raw": "{{base_url}}requery.php?customer_id=2026100114305581234",
                                    "query": [
                                        {
                                            "key": "customer_id",
                                            "value": "2026100114305581234",
                                            "description": "The customer_id you sent with the purchase.",
                                            "disabled": false
                                        }
                                    ]
                                },
                                "description": "The current status of an order, by your customer_id. Use it after any Processing / unclear reply, or a timeout.\n\n**Query parameters**\n\n| Field | Required | Description |\n|---|---|---|\n| `customer_id` (string) | Yes | The customer_id you sent with the purchase. |\n\n**Common errors**\n\n- `JO102` Missing customer_id\n- `JO110` No order with that customer_id on your account\n\n**Notes**\n\n- `responseCode` is `200` whenever the order is found. The order's real state is in `status` (Successful, Failed, Pending, Processing).\n- The Data/Airtime reply spells the payment field `chargeMothed` (long-standing; the other services use `chargeMethod`).\n"
                            },
                            "status": "OK",
                            "code": 200,
                            "_postman_previewlanguage": "json",
                            "header": [
                                {
                                    "key": "Content-Type",
                                    "value": "application/json"
                                }
                            ],
                            "body": "{\n    \"message\": \"Transaction not found\",\n    \"responseCode\": \"JO110\",\n    \"status\": \"Failed\"\n}"
                        }
                    ]
                },
                {
                    "name": "Resend Webhook",
                    "request": {
                        "method": "POST",
                        "header": [
                            {
                                "key": "Content-Type",
                                "value": "application/json"
                            }
                        ],
                        "url": {
                            "raw": "{{base_url}}resend_webhook.php"
                        },
                        "description": "Sends a finished Data or Airtime order's webhook to your URL again.\n\n**Body (JSON)**\n\n| Field | Required | Description |\n|---|---|---|\n| `customer_id` (string) | Yes | The customer_id of the order. |\n\n**Common errors**\n\n- `JO102` Missing customer_id\n- `JO110` Order not found\n- `JO119` Order not finished yet\n- `JO109` No webhook URL set\n",
                        "body": {
                            "mode": "raw",
                            "raw": "{\n    \"customer_id\": \"2026100114305581234\"\n}",
                            "options": {
                                "raw": {
                                    "language": "json"
                                }
                            }
                        }
                    },
                    "response": [
                        {
                            "name": "Successful",
                            "originalRequest": {
                                "method": "POST",
                                "header": [
                                    {
                                        "key": "Content-Type",
                                        "value": "application/json"
                                    }
                                ],
                                "url": {
                                    "raw": "{{base_url}}resend_webhook.php"
                                },
                                "description": "Sends a finished Data or Airtime order's webhook to your URL again.\n\n**Body (JSON)**\n\n| Field | Required | Description |\n|---|---|---|\n| `customer_id` (string) | Yes | The customer_id of the order. |\n\n**Common errors**\n\n- `JO102` Missing customer_id\n- `JO110` Order not found\n- `JO119` Order not finished yet\n- `JO109` No webhook URL set\n",
                                "body": {
                                    "mode": "raw",
                                    "raw": "{\n    \"customer_id\": \"2026100114305581234\"\n}",
                                    "options": {
                                        "raw": {
                                            "language": "json"
                                        }
                                    }
                                }
                            },
                            "status": "OK",
                            "code": 200,
                            "_postman_previewlanguage": "json",
                            "header": [
                                {
                                    "key": "Content-Type",
                                    "value": "application/json"
                                }
                            ],
                            "body": "{\n    \"responseCode\": \"200\",\n    \"status\": \"Successful\",\n    \"message\": \"Webhook successfully resent\"\n}"
                        }
                    ]
                }
            ]
        }
    ]
}