{
  "info": {
    "name": "BulkClix API",
    "description": "Official BulkClix API collection. Set the api_key variable to one of your keys (BulkClix dashboard → API keys). Full reference: https://bulkclix.com/developers",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "variable": [
    {
      "key": "base_url",
      "value": "https://api.bulkclix.com/api/v1",
      "type": "string"
    },
    {
      "key": "api_key",
      "value": "YOUR_API_KEY",
      "type": "string"
    }
  ],
  "item": [
    {
      "name": "Account",
      "description": "Read the balances that fund your API activity.",
      "item": [
        {
          "name": "Get balance",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "x-api-key",
                "value": "{{api_key}}"
              },
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/account-api/balance",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "account-api",
                "balance"
              ]
            },
            "description": "Returns the wallet balance (GHS) used for payments, airtime and data, and the SMS credit balance used for messaging and OTP. Team member keys read the owning account's balances."
          },
          "response": []
        }
      ]
    },
    {
      "name": "SMS",
      "description": "Send messages from an approved sender ID and read delivery results. Messages are billed in SMS credits: one credit per 160 characters per recipient.",
      "item": [
        {
          "name": "List sender IDs",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "x-api-key",
                "value": "{{api_key}}"
              },
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/sms-api/senderIds",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "sms-api",
                "senderIds"
              ]
            },
            "description": "All sender IDs on your account with their approval status. Use the id of an approved sender when sending messages or OTPs."
          },
          "response": []
        },
        {
          "name": "Request a sender ID",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "x-api-key",
                "value": "{{api_key}}"
              },
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/sms-api/requestSenderId",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "sms-api",
                "requestSenderId"
              ]
            },
            "description": "Submit a new sender ID for approval. Approval is manual and usually completes within one business day; poll the list endpoint for the status.\n\n- Names containing network or mobile money brand words (MTN, Telecel, AirtelTigo, MoMo, BulkClix) are rejected.\n- Limited to 60 requests per hour.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"name\": \"MYBRAND\",\n  \"desc\": \"Order notifications for my online shop\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Send SMS",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "x-api-key",
                "value": "{{api_key}}"
              },
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/sms-api/send",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "sms-api",
                "send"
              ]
            },
            "description": "Send one message to a list of recipients, to whole contact groups, or both. Recipients are de-duplicated and normalised to the 233 format. The response returns a campaign id you can use to fetch per-recipient delivery status.\n\n- Cost is ceil(characters / 160) credits per recipient and is checked before sending.\n- Also accepted as GET with the same fields in the query string, for platforms that cannot POST JSON.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"sender_id\": \"9b1c2a3d-4e5f-4a6b-8c7d-1e2f3a4b5c6d\",\n  \"message\": \"Your order #4521 has shipped and arrives tomorrow.\",\n  \"recipients\": [\n    \"0241234567\",\n    \"0551234567\"\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Send SMS (GET)",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "x-api-key",
                "value": "{{api_key}}"
              },
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/sms-api/send?sender_id=9b1c2a3d-4e5f-4a6b-8c7d-1e2f3a4b5c6d&message=Your%20order%20%234521%20has%20shipped.&recipients[]=0241234567",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "sms-api",
                "send"
              ],
              "query": [
                {
                  "key": "sender_id",
                  "value": "9b1c2a3d-4e5f-4a6b-8c7d-1e2f3a4b5c6d"
                },
                {
                  "key": "message",
                  "value": "Your order #4521 has shipped."
                },
                {
                  "key": "recipients[]",
                  "value": "0241234567"
                }
              ]
            },
            "description": "The same operation as Send SMS for platforms that can only make GET requests, such as USSD gateways and legacy PBX systems. Pass the fields in the query string; repeat recipients[] for each number."
          },
          "response": []
        },
        {
          "name": "Campaign delivery report",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "x-api-key",
                "value": "{{api_key}}"
              },
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/sms-api/campaignMessages/5f0d9c8e-2b1a-4c3d-9e8f-7a6b5c4d3e2f?page_size=50",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "sms-api",
                "campaignMessages",
                "5f0d9c8e-2b1a-4c3d-9e8f-7a6b5c4d3e2f"
              ],
              "query": [
                {
                  "key": "page_size",
                  "value": "50"
                }
              ]
            },
            "description": "Per-recipient messages for a campaign returned by Send SMS, with the current delivery status of each. Paginated."
          },
          "response": []
        }
      ]
    },
    {
      "name": "OTP",
      "description": "Generate and verify one-time passcodes without storing them yourself. Codes are billed as SMS credits.",
      "item": [
        {
          "name": "Send OTP",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "x-api-key",
                "value": "{{api_key}}"
              },
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/sms-api/otp/send",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "sms-api",
                "otp",
                "send"
              ]
            },
            "description": "Generates a code, injects it into your message template at the <%otp_code%> placeholder and sends it. Keep the returned requestId to verify the code later.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"phoneNumber\": \"0241234567\",\n  \"senderId\": \"9b1c2a3d-4e5f-4a6b-8c7d-1e2f3a4b5c6d\",\n  \"message\": \"Your MyShop verification code is <%otp_code%>. It expires in 5 minutes.\",\n  \"length\": 6,\n  \"expiry\": 5\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Verify OTP",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "x-api-key",
                "value": "{{api_key}}"
              },
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/sms-api/otp/verify",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "sms-api",
                "otp",
                "verify"
              ]
            },
            "description": "Checks a code the user typed against the one sent for that requestId and phone number. After five wrong attempts the code is discarded and a new one must be sent.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"requestId\": \"2d7e6f5a-9b8c-4d1e-a2f3-4b5c6d7e8f9a\",\n  \"phoneNumber\": \"0241234567\",\n  \"code\": \"482913\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        }
      ]
    },
    {
      "name": "Contacts",
      "description": "Manage contact groups and the contacts in them, then target a whole group from Send SMS with group_id_list.",
      "item": [
        {
          "name": "List groups",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "x-api-key",
                "value": "{{api_key}}"
              },
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/sms-api/contact/getGroups",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "sms-api",
                "contact",
                "getGroups"
              ]
            },
            "description": "All contact groups on the account with the number of contacts in each."
          },
          "response": []
        },
        {
          "name": "Create group",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "x-api-key",
                "value": "{{api_key}}"
              },
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/sms-api/contact/addGroup",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "sms-api",
                "contact",
                "addGroup"
              ]
            },
            "description": "Creates an empty contact group. Names are unique per account.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"name\": \"VIP customers\",\n  \"group_icon\": \"group_icon_1\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Update group",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "x-api-key",
                "value": "{{api_key}}"
              },
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/sms-api/contact/updateGroup/7a8b9c0d-1e2f-4a3b-8c4d-5e6f7a8b9c0d",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "sms-api",
                "contact",
                "updateGroup",
                "7a8b9c0d-1e2f-4a3b-8c4d-5e6f7a8b9c0d"
              ]
            },
            "description": "Rename a group or change its icon. Only the fields you send are changed.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"name\": \"VIP customers 2026\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Delete group",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "x-api-key",
                "value": "{{api_key}}"
              },
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/sms-api/contact/deleteGroup/7a8b9c0d-1e2f-4a3b-8c4d-5e6f7a8b9c0d",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "sms-api",
                "contact",
                "deleteGroup",
                "7a8b9c0d-1e2f-4a3b-8c4d-5e6f7a8b9c0d"
              ]
            },
            "description": "Deletes a group and the contacts in it."
          },
          "response": []
        },
        {
          "name": "List contacts in a group",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "x-api-key",
                "value": "{{api_key}}"
              },
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/sms-api/contact/getContacts/7a8b9c0d-1e2f-4a3b-8c4d-5e6f7a8b9c0d",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "sms-api",
                "contact",
                "getContacts",
                "7a8b9c0d-1e2f-4a3b-8c4d-5e6f7a8b9c0d"
              ]
            },
            "description": "Contacts in a group, 15 per page. An empty group returns the plain envelope with an empty data array instead of the paginated one."
          },
          "response": []
        },
        {
          "name": "Add a contact",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "x-api-key",
                "value": "{{api_key}}"
              },
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/sms-api/contact/addContact",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "sms-api",
                "contact",
                "addContact"
              ]
            },
            "description": "Adds one contact to a group you own.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"first_name\": \"Ama\",\n  \"last_name\": \"Mensah\",\n  \"phone_number\": \"0241234567\",\n  \"email\": \"ama@example.com\",\n  \"contact_group_id\": \"7a8b9c0d-1e2f-4a3b-8c4d-5e6f7a8b9c0d\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Add contacts in bulk",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "x-api-key",
                "value": "{{api_key}}"
              },
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/sms-api/contact/addBulkContact",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "sms-api",
                "contact",
                "addBulkContact"
              ]
            },
            "description": "Adds many contacts to one group in a single call. All rows are validated before any are inserted.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"contact_group_id\": \"7a8b9c0d-1e2f-4a3b-8c4d-5e6f7a8b9c0d\",\n  \"contacts\": [\n    {\n      \"first_name\": \"Ama\",\n      \"last_name\": \"Mensah\",\n      \"phone_number\": \"0241234567\",\n      \"email\": \"ama@example.com\"\n    },\n    {\n      \"first_name\": \"Kofi\",\n      \"phone_number\": \"0551234567\"\n    }\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Update a contact",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "x-api-key",
                "value": "{{api_key}}"
              },
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/sms-api/contact/updateContact/e1f2a3b4-c5d6-4e7f-8a9b-0c1d2e3f4a5b",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "sms-api",
                "contact",
                "updateContact",
                "e1f2a3b4-c5d6-4e7f-8a9b-0c1d2e3f4a5b"
              ]
            },
            "description": "Change any of a contact's details. Only the fields you send are changed.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"phone_number\": \"0209876543\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Delete a contact",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "x-api-key",
                "value": "{{api_key}}"
              },
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/sms-api/contact/deleteContact/e1f2a3b4-c5d6-4e7f-8a9b-0c1d2e3f4a5b",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "sms-api",
                "contact",
                "deleteContact",
                "e1f2a3b4-c5d6-4e7f-8a9b-0c1d2e3f4a5b"
              ]
            },
            "description": "Removes a contact from its group."
          },
          "response": []
        }
      ]
    },
    {
      "name": "Payments · Collections",
      "description": "Charge a customer's mobile money wallet. The customer approves a prompt on their phone; you learn the outcome through your callback URL or by checking status. Requires collections to be enabled on your account.",
      "item": [
        {
          "name": "Collect mobile money",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "x-api-key",
                "value": "{{api_key}}"
              },
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/payment-api/momopay",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "payment-api",
                "momopay"
              ]
            },
            "description": "Sends a payment prompt to the customer's phone. By default the customer is charged the amount plus our collection fee and your wallet is credited with the amount once they approve. If your account is set to absorb the fee, the customer is charged the amount only and the fee is deducted from what is credited to you.\n\n- The response is only an acknowledgement; the payment is pending until the customer approves the prompt.\n- Idempotent on transaction_id: a repeated reference returns 422.\n- Who pays the fee (fee_bearer: customer or merchant) is an account-level setting — contact support to change it. The response, status checks, history and webhook all report charges and net_amount so you can reconcile either way.\n\n**Webhook** — POSTed to your callback_url when the transaction is final:\n```json\n{\n  \"amount\": \"50.00\",\n  \"charges\": \"0.50\",\n  \"net_amount\": 50,\n  \"fee_bearer\": \"customer\",\n  \"status\": \"success\",\n  \"transaction_id\": \"ORDER-2026-000123\",\n  \"ext_transaction_id\": \"839201746512\",\n  \"phone_number\": \"233241234567\"\n}\n```",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"amount\": 50,\n  \"phone_number\": \"0241234567\",\n  \"network\": \"MTN\",\n  \"transaction_id\": \"ORDER-2026-000123\",\n  \"callback_url\": \"https://example.com/webhooks/bulkclix\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Check collection status",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "x-api-key",
                "value": "{{api_key}}"
              },
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/payment-api/checkstatus/ORDER-2026-000123",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "payment-api",
                "checkstatus",
                "ORDER-2026-000123"
              ]
            },
            "description": "Looks up a collection by the transaction_id you supplied. While pending we re-query the provider, so a success reported here is already credited to your wallet."
          },
          "response": []
        },
        {
          "name": "Collections history",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "x-api-key",
                "value": "{{api_key}}"
              },
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/payment-api/collections/history?status=success&from=2026-09-01&to=2026-09-30&page_size=25",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "payment-api",
                "collections",
                "history"
              ],
              "query": [
                {
                  "key": "status",
                  "value": "success"
                },
                {
                  "key": "from",
                  "value": "2026-09-01"
                },
                {
                  "key": "to",
                  "value": "2026-09-30"
                },
                {
                  "key": "page_size",
                  "value": "25"
                }
              ]
            },
            "description": "Paginated list of collections made through the API, newest first, with optional filters."
          },
          "response": []
        }
      ]
    },
    {
      "name": "Payments · Transfers",
      "description": "Pay out from your wallet to mobile money wallets and bank accounts. Transfer endpoints only accept requests from the IP addresses whitelisted on your account. Your wallet is debited the amount plus the transfer fee and the recipient always receives the full amount; responses and webhooks report the charges so you can reconcile.",
      "item": [
        {
          "name": "Send to mobile money",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "x-api-key",
                "value": "{{api_key}}"
              },
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/payment-api/send/mobilemoney",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "payment-api",
                "send",
                "mobilemoney"
              ]
            },
            "description": "Debits your wallet for the amount plus the transfer fee and submits the payout to the recipient's mobile money wallet. Transfers settle asynchronously: the response confirms the transfer was accepted, and the final outcome is delivered to your callback URL.\n\n- Only whitelisted IPs may call this endpoint (403 otherwise).\n- If the provider rejects the transfer outright the debit is refunded immediately and you receive 400.\n- If the transfer fails after acceptance, the webhook reports status failed and the debit (amount plus fee) is refunded to your wallet.\n\n**Webhook** — POSTed to your callback_url when the transaction is final:\n```json\n{\n  \"amount\": \"120.00\",\n  \"charges\": \"1.20\",\n  \"status\": \"success\",\n  \"transaction_id\": \"ORDER-2026-000123\",\n  \"ext_transaction_id\": \"839201746512\"\n}\n```",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"amount\": 120,\n  \"account_number\": \"0241234567\",\n  \"account_name\": \"Ama Mensah\",\n  \"channel\": \"MTN\",\n  \"client_reference\": \"ORDER-2026-000123\",\n  \"callback_url\": \"https://example.com/webhooks/bulkclix\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "List banks",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "x-api-key",
                "value": "{{api_key}}"
              },
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/payment-api/banks/list",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "payment-api",
                "banks",
                "list"
              ]
            },
            "description": "Supported banks. Use the id as bank_id when resolving an account name or sending to a bank."
          },
          "response": []
        },
        {
          "name": "Resolve bank account name",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "x-api-key",
                "value": "{{api_key}}"
              },
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/payment-api/bankNameQuery?account_number=1021234567890&bank_id=3c4d5e6f-7a8b-4c9d-8e0f-1a2b3c4d5e6f",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "payment-api",
                "bankNameQuery"
              ],
              "query": [
                {
                  "key": "account_number",
                  "value": "1021234567890"
                },
                {
                  "key": "bank_id",
                  "value": "3c4d5e6f-7a8b-4c9d-8e0f-1a2b3c4d5e6f"
                }
              ]
            },
            "description": "Returns the name on a bank account so you can confirm it with the user before sending."
          },
          "response": []
        },
        {
          "name": "Send to bank",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "x-api-key",
                "value": "{{api_key}}"
              },
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/payment-api/send/bank",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "payment-api",
                "send",
                "bank"
              ]
            },
            "description": "Debits your wallet for the amount plus the transfer fee and submits the payout to a bank account. The account name is resolved on our side before the transfer is submitted. Transfers settle asynchronously: the final outcome is delivered to your callback URL.\n\n- Only whitelisted IPs may call this endpoint (403 otherwise).\n- If the transfer fails after acceptance, the webhook reports status failed and the debit (amount plus fee) is refunded to your wallet.\n\n**Webhook** — POSTed to your callback_url when the transaction is final:\n```json\n{\n  \"amount\": \"500.00\",\n  \"charges\": \"5.00\",\n  \"status\": \"success\",\n  \"transaction_id\": \"ORDER-2026-000123\",\n  \"ext_transaction_id\": \"839201746512\"\n}\n```",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"amount\": 500,\n  \"account_number\": \"1021234567890\",\n  \"bank_id\": \"3c4d5e6f-7a8b-4c9d-8e0f-1a2b3c4d5e6f\",\n  \"client_reference\": \"ORDER-2026-000123\",\n  \"callback_url\": \"https://example.com/webhooks/bulkclix\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Transfers history",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "x-api-key",
                "value": "{{api_key}}"
              },
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/payment-api/transfers/history?from=2026-09-01&page_size=25",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "payment-api",
                "transfers",
                "history"
              ],
              "query": [
                {
                  "key": "from",
                  "value": "2026-09-01"
                },
                {
                  "key": "page_size",
                  "value": "25"
                }
              ]
            },
            "description": "Paginated list of mobile money, bank and wallet transfers, newest first, with optional filters. channel is BANK for bank transfers."
          },
          "response": []
        }
      ]
    },
    {
      "name": "KYC",
      "description": "Verify who owns a mobile money number before you pay them or accept a payment.",
      "item": [
        {
          "name": "Resolve mobile money name",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "x-api-key",
                "value": "{{api_key}}"
              },
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/kyc-api/msisdNameQuery?phone_number=0241234567",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "kyc-api",
                "msisdNameQuery"
              ],
              "query": [
                {
                  "key": "phone_number",
                  "value": "0241234567"
                }
              ]
            },
            "description": "Returns the registered name for a mobile money number."
          },
          "response": []
        }
      ]
    },
    {
      "name": "Airtime",
      "description": "Top up any Ghanaian number from your wallet. Your account's airtime commission is deducted from the amount debited.",
      "item": [
        {
          "name": "List networks",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "x-api-key",
                "value": "{{api_key}}"
              },
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/airtime-api/networks",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "airtime-api",
                "networks"
              ]
            },
            "description": "Networks you can send airtime to. Use the id as network_id. This endpoint responds with status 201."
          },
          "response": []
        },
        {
          "name": "Send airtime",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "x-api-key",
                "value": "{{api_key}}"
              },
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/airtime-api/sendAirtime",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "airtime-api",
                "sendAirtime"
              ]
            },
            "description": "Debits your wallet and tops up the number. The transfer starts as submitted; the final state arrives on your callback URL or through Check airtime status.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"phone_number\": \"0241234567\",\n  \"amount\": 10,\n  \"network_id\": \"a1b2c3d4-0000-4000-8000-000000000001\",\n  \"transaction_id\": \"ORDER-2026-000123\",\n  \"callback_url\": \"https://example.com/webhooks/bulkclix\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Buy airtime with mobile money",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "x-api-key",
                "value": "{{api_key}}"
              },
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/airtime-api/buy",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "airtime-api",
                "buy"
              ]
            },
            "description": "Tops up a number and charges a mobile money wallet instead of your BulkClix wallet. The payer receives a prompt to approve; poll Check collection status with the returned transaction_id to learn the outcome. Useful for reseller apps where the end customer pays directly.\n\n- Limited to 60 requests per hour.\n- Requires collections to be enabled on your account.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"destination\": \"0241234567\",\n  \"phoneNumber\": \"0551234567\",\n  \"network\": \"MTN\",\n  \"amount\": 10,\n  \"network_id\": \"a1b2c3d4-0000-4000-8000-000000000001\",\n  \"type\": \"momo\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Check airtime status",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "x-api-key",
                "value": "{{api_key}}"
              },
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/airtime-api/checkstatus/ORDER-2026-000123",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "airtime-api",
                "checkstatus",
                "ORDER-2026-000123"
              ]
            },
            "description": "Looks up a top-up by your transaction_id. A submitted top-up that the provider reports as failed is marked failed and refunded to your wallet during this call. Limited to 60 requests per minute."
          },
          "response": []
        },
        {
          "name": "Airtime history",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "x-api-key",
                "value": "{{api_key}}"
              },
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/airtime-api/history?page_size=25",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "airtime-api",
                "history"
              ],
              "query": [
                {
                  "key": "page_size",
                  "value": "25"
                }
              ]
            },
            "description": "Paginated list of airtime top-ups, newest first."
          },
          "response": []
        }
      ]
    },
    {
      "name": "Data bundles",
      "description": "Send data from your wallet: list the services, fetch the packages the network offers a number, then buy one.",
      "item": [
        {
          "name": "List data services",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "x-api-key",
                "value": "{{api_key}}"
              },
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/databundle-api-v2/services",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "databundle-api-v2",
                "services"
              ]
            },
            "description": "Networks and products that offer selectable packages. Use the id as service_id."
          },
          "response": []
        },
        {
          "name": "List packages for a number",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "x-api-key",
                "value": "{{api_key}}"
              },
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/databundle-api-v2/offers/b2c3d4e5-0000-4000-8000-000000000001/0241234567",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "databundle-api-v2",
                "offers",
                "b2c3d4e5-0000-4000-8000-000000000001",
                "0241234567"
              ]
            },
            "description": "Packages the network currently offers to that number. Each package id is valid for 60 minutes; buy within that window."
          },
          "response": []
        },
        {
          "name": "Buy a package",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "x-api-key",
                "value": "{{api_key}}"
              },
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/databundle-api-v2/buy",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "databundle-api-v2",
                "buy"
              ]
            },
            "description": "Debits your wallet for the package price and sends it to the number. Keep the returned ext_transaction_id to check status.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"phone_number\": \"0241234567\",\n  \"service_id\": \"b2c3d4e5-0000-4000-8000-000000000001\",\n  \"package_id\": \"c9d8e7f6-1111-4000-8000-000000000009\",\n  \"network\": \"MTN\",\n  \"type\": \"e_wallet\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Check package status",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "x-api-key",
                "value": "{{api_key}}"
              },
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/databundle-api-v2/checkstatus/DB7F3A9C2E1B",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "databundle-api-v2",
                "checkstatus",
                "DB7F3A9C2E1B"
              ]
            },
            "description": "Looks up a package purchase by the ext_transaction_id returned by Buy a package. A submitted bundle the provider reports as failed is marked failed and refunded during this call. Limited to 60 requests per minute."
          },
          "response": []
        }
      ]
    }
  ]
}