> ## Documentation Index
> Fetch the complete documentation index at: https://docs.niobi.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Unified Collections

> One endpoint for all collection methods across all supported markets. Accepts mobile money, bank transfer, virtual accounts, and redirect-based rails through a single unified interface. Each request must carry a freshly generated signature, signatures cannot be reused across requests. Conditional `params` fields vary by payment method and country. See the [Collections Guide](/collecting-payments/basics) and [Payment Methods](/collecting-payments/methods) for the full field matrix per market.

### Integration Quick Reference

| Requirement                                                                                 | Standard               | Rule / Action                                                                                                                                                                                           |
| :------------------------------------------------------------------------------------------ | :--------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| [**Settlement Rule**](/collecting-payments/basics#understanding-payment-steps-payment_step) | `payment_step: 2` only | Never credit goods or user accounts on `payment_step: 1` (initiation). Only credit upon receiving [payment\_step: 2](/collecting-payments/callbacks) with `status: "success"` (`statusCode: "000000"`). |
| [**Signatures**](/authentication/signature-generation)                                      | Fresh per request      | Compute a fresh SHA-256 signature for every API call. Signatures cannot be reused. See [Signature Generation](/authentication/signature-generation).                                                    |
| [**Amount Format**](/collecting-payments/basics#request-parameters)                         | Whole integers         | Pass whole numbers in major currency units (for example, `1000` KES). No decimals allowed.                                                                                                              |
| [**Idempotency**](/idempotency)                                                             | Unique merchant ref    | Pass a distinct `third_party_reference_1` per request to prevent duplicate charges. See the [Idempotency Guide](/idempotency).                                                                          |
| [**Delayed Webhook**](/transaction-status)                                                  | Query status           | If a callback is delayed, query the [Get Transaction Status API](/transaction-status) before taking action.                                                                                             |
| [**Sandbox Testing**](/testing)                                                             | Mapped test MSISDNs    | Use designated [Sandbox Test Numbers](/testing) mapped to outcomes (success, timeout, failed) instead of real phone numbers.                                                                            |
| [**Production Prep**](/go-live-checklist)                                                   | Technical checklist    | Verify public HTTPS `callback_url`, country limits, and credentials in the [Go-Live Checklist](/go-live-checklist#technical-checklist).                                                                 |

## List of Supported Countries

<div className="payment-link-countries-table">
  | Country Id | Country                                   | Code | Currency | Payment Methods                | Status |
  | ---------- | ----------------------------------------- | ---- | -------- | ------------------------------ | ------ |
  | 1          | [Kenya](/countries/kenya)                 | 254  | KES      | send money, Airtel             | Active |
  | 2          | [Benin](/countries/benin)                 | 229  | XOF      | Mtn, Moov                      | Active |
  | 3          | [Cote D'Ivoire](/countries/cote-d-ivoire) | 225  | XOF      | Mtn,Orange, Moov, Wave         | Active |
  | 4          | [Cameroon](/countries/cameroon)           | 237  | XAF      | Mtn, Orange                    | Active |
  | 5          | [DRC](/countries/drc)                     | 243  | CDF      | Airtel, Orange, Vodacom        | Active |
  | 8          | [Rwanda](/countries/rwanda)               | 250  | RWF      | Mtn, Airtel                    | Active |
  | 9          | [Senegal](/countries/senegal)             | 221  | XOF      | Orange, Free, Wave             | Active |
  | 10         | [Tanzania](/countries/tanzania)           | 255  | TZS      | Airtel, Halotel, Tigo, Vodacom | Active |
  | 11         | [Uganda](/countries/uganda)               | 256  | UGX      | Mtn, Airtel                    | Active |
  | 12         | [Zambia](/countries/zambia)               | 260  | ZMW      | Mtn, Zamtel, Airtel            | Active |
  | 13         | [Sierra Leone](/countries/sierra-leone)   | 232  | SLE      | Orange                         | Active |
  | 15         | [South Africa](/countries/south-africa)   | 27   | ZAR      | bank\_eft, capitec             | Active |
  | 16         | [Ghana](/countries/ghana)                 | 233  | GHS      | Mtn, At(AirtelTigo), Vodafone  | Active |
  | 17         | [Nigeria](/countries/nigeria)             | 234  | NGN      | virtual\_account               | Active |
  | 19         | [Burkina Faso](/countries/burkina-faso)   | 226  | XOF      | Orange, Moov                   | Active |
  | 18         | [Mali](/countries/mali)                   | 223  | XOF      | Orange, Moov                   | Active |
  | 20         | [Togo](/countries/togo)                   | 228  | XOF      | moov, tmoney                   | Active |
</div>

**Coming Soon**

| Country                             | Code | Currency | Payment Methods         |
| ----------------------------------- | ---- | -------- | ----------------------- |
| [Ethiopia](/countries/ethiopia)     | 251  | ETB      | teleBirr, mBirr         |
| [Malawi](/countries/malawi)         | 265  | MWK      | Airtel, tnm             |
| [Egypt](/countries/egypt)           | 20   | EGP      | Vodafone, Orange        |
| [Mozambique](/countries/mozambique) | 258  | MZN      | Vodacom, Movitel, Tmcel |

<Note>
  For NGN bank and virtual account deposits, the expected amount is processed and any overpayment is automatically reversed to the customer on successful deposit. Send exact amounts to prevent unnecessary reversals.
</Note>

### NGN Virtual Account - Supported Bank Codes

Pass one of the following codes as `bank_code` in your request to select the bank that will issue the virtual account.

| Bank Code | Bank Name                  |
| --------- | -------------------------- |
| 17001     | 78 Finance Company Limited |
| 17002     | Fidelity Bank Limited      |
| 17003     | Globus Bank Limited        |

<Note>
  For Senegal Orange deposits, the end user receives an SMS with a shortcode after the deposit is initiated. They dial the shortcode, triggering a USSD prompt where they input their PIN to approve the transaction.
</Note>

### Special Collection Flows

Some corridors don't follow the standard STK-push flow above: they require redirect URLs, customer national ID numbers, dynamic virtual bank accounts, or a secondary OTP verification step.

For complete architectural walkthroughs, UX screenshots, and lifecycle diagrams, see:

* [**Collection Methods Guide**](/collecting-payments/methods): Step-by-step guides for all payment collection channels.
* [**Country Guides Index**](/supported-countries): Country-specific corridors, telco channel rules, and test MSISDNs.

<Note>
  There is no `"eft"` payment method value. South African EFT collections use `payment_method_type: "bank_eft"`, shown below.
</Note>

<Tabs>
  <Tab title="Bank EFT (South Africa)">
    `payment_method_type`: `"bank_eft"`

    Returns an `authorization_url` where the customer approves the payment directly with their bank (ABSA, FNB, Standard Bank, Nedbank, Investec, Bidvest, TymeBank).

    **Documentation & Guides:**

    * [Collection Methods: South Africa Bank EFT](/collecting-payments/methods#3-south-africa-bank-transfers--capitec-zar)
    * [South Africa Country Guide: Bank EFT Flow](/countries/south-africa#1-eft-bank-collections-payment_method_type-bank_eft)

    ```json theme={null}
    {
      "client_id": "YOUR_CLIENT_ID",
      "sender": "YOUR_INTEGRATION_NAME",
      "timestamp": 1724835600,
      "salt": "random_salt_12345",
      "signature": "c6b98e1f5d6a7890bc4e123456789abcdef0123456789abcdef0123456789abc",
      "params": {
        "amount": 500,
        "currency": "ZAR",
        "country_id": 15,
        "mobile": "2763456789",
        "name": "John Doe",
        "bank_code": "0001",
        "payment_method_type": "bank_eft",
        "successful_url": "https://yourdomain.com/payment-success",
        "failure_url": "https://yourdomain.com/payment-failed",
        "callback_url": "https://yourdomain.com/niobi/callback",
        "third_party_reference_1": "ZAR-DEPOSIT-01"
      }
    }
    ```

    **Initial Response:** Returns `"authorization_url": "https://..."` and `"payment_step": 1`. Redirect the customer to this URL. For a full walkthrough of redirect handling and bank selection, see the [South Africa Country Guide](/countries/south-africa).
  </Tab>

  <Tab title="Capitec Collections (South Africa)">
    `payment_method_type`: `"capitec"`

    Capitec Bank collections authenticate directly against the payer's national identity. You must pass the customer's full 13-digit South African ID number in `params.id_number` (e.g. `"9001015800083"`) for the request to be valid.

    **Documentation & Guides:**

    * [Collection Methods: Capitec Collections](/collecting-payments/methods#3-south-africa-bank-transfers--capitec-zar)
    * [South Africa Country Guide: Capitec Pay](/countries/south-africa#2-capitec-collections-payment_method_type-capitec)

    ```json theme={null}
    {
      "client_id": "YOUR_CLIENT_ID",
      "sender": "YOUR_INTEGRATION_NAME",
      "timestamp": 1724835600,
      "salt": "random_salt_12345",
      "signature": "c6b98e1f5d6a7890bc4e123456789abcdef0123456789abcdef0123456789abc",
      "params": {
        "amount": 500,
        "currency": "ZAR",
        "country_id": 15,
        "mobile": "2763456789",
        "name": "John Doe",
        "id_number": "9001015800083",
        "payment_method_type": "capitec",
        "successful_url": "https://yourdomain.com/payment-success",
        "failure_url": "https://yourdomain.com/payment-failed",
        "callback_url": "https://yourdomain.com/niobi/callback",
        "third_party_reference_1": "ZAR-CAPITEC-01"
      }
    }
    ```
  </Tab>

  <Tab title="Wave (Senegal & Côte d'Ivoire)">
    `payment_method_type`: `"Wave"`

    Wave uses a redirect-based browser authorization flow, not a USSD push. You must include `successful_url` and `failure_url`. After initiating the collection, redirect the customer to the returned `authorization_url` to complete payment.

    **Documentation & Guides:**

    * [Collection Methods: Wave Flow & UI Walkthrough](/collecting-payments/methods#4-wave-collections-senegal--cote-divoire)
    * [Senegal Country Guide: Wave Checkout](/countries/senegal#2-wave-redirect-flow-payment_method_type-wave)
    * [Côte d'Ivoire Country Guide: Wave Collections](/countries/cote-d-ivoire#2-wave-redirect-flow-payment_method_type-wave)

    ```json theme={null}
    {
      "client_id": "YOUR_CLIENT_ID",
      "sender": "YOUR_INTEGRATION_NAME",
      "timestamp": 1724835600,
      "salt": "random_salt_12345",
      "signature": "c6b98e1f5d6a7890bc4e123456789abcdef0123456789abcdef0123456789abc",
      "params": {
        "amount": 5000,
        "currency": "XOF",
        "country_id": 9,
        "mobile": "221763456789",
        "payment_method_type": "Wave",
        "successful_url": "https://yourdomain.com/checkout/success",
        "failure_url": "https://yourdomain.com/checkout/cancel",
        "callback_url": "https://yourdomain.com/niobi/callback",
        "third_party_reference_1": "WAVE-SN-001"
      }
    }
    ```
  </Tab>

  <Tab title="OTP-Verified (Côte d'Ivoire Orange)">
    `payment_method_type`: `"Orange"`

    Orange payins in Côte d'Ivoire require a two-step OTP process instead of a single request.

    **Documentation & Guides:**

    * [Collection Methods: OTP-Verified Payins](/collecting-payments/methods#5-otp-verified-payins-cote-divoire-orange)
    * [Côte d'Ivoire Country Guide: Orange Money OTP](/countries/cote-d-ivoire#3-orange-money-otp-flow-payment_method_type-orange)

    **Step 1: Initiate.** Submit the collection request as usual. The customer receives an SMS OTP, and the response returns a `payment_token` instead of a terminal status:

    ```json theme={null}
    {
      "success": true,
      "message": "We've sent a verification prompt to your phone. Please approve it to complete your payment.",
      "data": {
        "status": "success",
        "amount": 2000,
        "currency": "XOF",
        "country_id": 3,
        "payment_token": "NIO-S0000001",
        "payment_step": 1
      },
      "status_code": "000000"
    }
    ```

    **Step 2: Verify.** Collect the OTP from the customer and send a signed request to [`POST /api/v4/niobi-unified-process-transaction`](/api-reference/collections/verify-otp):

    ```json theme={null}
    {
      "client_id": "YOUR_CLIENT_ID",
      "sender": "YOUR_INTEGRATION_NAME",
      "timestamp": 1724835600,
      "salt": "random_salt_12345",
      "signature": "3a3cf7f2e3ff8d4ee991d7e1323312887dfda8536b8c2e197d0d4ef764013658",
      "params": {
        "otp": "000000",
        "payment_token": "NIO-S0000001"
      }
    }
    ```

    In production, the OTP is valid for 2 minutes. In sandbox, use OTP `000000` to simulate successful verification.
  </Tab>

  <Tab title="Virtual Account (Nigeria)">
    `payment_method_type`: `"virtual_account"`

    Generates a dedicated NGN virtual account for the customer to pay into. `account_name` is required. Pass a `bank_code` from the [NGN Virtual Account bank codes](#ngn-virtual-account---supported-bank-codes) above to choose the issuing bank; `first_name` and `last_name` are optional customer details.

    **Documentation & Guides:**

    * [Collection Methods: Dynamic Virtual Accounts](/collecting-payments/methods#2-dynamic-virtual-accounts-nigeria---ngn)
    * [Nigeria Country Guide: Dynamic Virtual Accounts](/countries/nigeria#deposits-collections-via-dynamic-virtual-accounts)

    ```json theme={null}
    {
      "client_id": "YOUR_CLIENT_ID",
      "params": {
        "account_name": "John Doe",
        "amount": 10000,
        "bank_code": "17001",
        "callback_url": "https://example.com/callback",
        "country_id": 17,
        "currency": "NGN",
        "first_name": "John",
        "last_name": "Doe",
        "mobile": "2349034567899",
        "payment_method_type": "virtual_account",
        "third_party_reference_1": "TX-COLL-1001",
        "third_party_reference_2": "CUST-501"
      },
      "salt": "random_salt_12345",
      "sender": "YOUR_INTEGRATION_NAME",
      "timestamp": 1724835600,
      "signature": "a1b2c3d4e5f60718293a4b5c6d7e8f90123456789abcdef0123456789abcdef0"
    }
    ```

    **Response:** Returns `account_number` and `bank_name` for the generated virtual account, plus `"payment_step": 1`. Display these to the customer, this is the initial acknowledgement, not confirmation of payment. Await the terminal callback (`payment_step: 2`). See the full walkthrough in the [Nigeria Country Guide](/countries/nigeria).
  </Tab>
</Tabs>


## OpenAPI

````yaml post /api/v4/niobi-unified-collections
openapi: 3.0.0
info:
  title: Niobi API
  description: >-
    REST API for collecting payments, sending payouts, and managing
    multi-currency wallets across Africa and global corridors. All requests
    require IP whitelisting and a unique per-request HMAC SHA-256 signature.
  version: 4.0.0
servers:
  - url: https://sandbox.users.niobi.co
    description: Sandbox, Development and Testing
security: []
tags:
  - name: Niobi
    description: API Endpoints of Niobi
paths:
  /api/v4/niobi-unified-collections:
    post:
      tags:
        - payment
      summary: Unified Collections
      description: >-
        One endpoint for all collection methods across all supported markets.
        Accepts mobile money, bank transfer, virtual accounts, and
        redirect-based rails through a single unified interface. Each request
        must carry a freshly generated signature, signatures cannot be reused
        across requests. Conditional `params` fields vary by payment method and
        country. See the [Collections Guide](/collecting-payments/basics) and
        [Payment Methods](/collecting-payments/methods) for the full field
        matrix per market.
      operationId: cdaf7e420aeb10d8093a03185cc4b37e
      requestBody:
        description: >-
          Signed request envelope. All root fields except params are
          authentication fields.
        required: true
        content:
          application/json:
            schema:
              required:
                - client_id
                - sender
                - timestamp
                - salt
                - signature
                - params
              properties:
                client_id:
                  description: >-
                    Your Client ID from the Niobi Dashboard under Workspace >
                    Integrations.
                  type: string
                sender:
                  description: >-
                    The exact title of your integration as registered in the
                    Dashboard. Case-sensitive.
                  type: string
                timestamp:
                  description: >-
                    Unix timestamp in seconds at the time of signing. Must match
                    the value used to generate the signature.
                  type: integer
                salt:
                  description: >-
                    A unique random string you generate per request. Must be the
                    same value used when generating the signature.
                  type: string
                signature:
                  description: >-
                    SHA-256 signature computed from this payload. Generate via
                    the [Signature
                    endpoint](/api-reference/authentication/generate-signature)
                    or your own backend.
                  type: string
                params:
                  required:
                    - amount
                    - mobile
                    - country_id
                    - currency
                    - payment_method_type
                    - first_name*
                    - last_name*
                    - account_name*
                    - bank_code*
                    - successful_url*
                    - failure_url*
                    - id_number*
                  properties:
                    amount:
                      description: >-
                        Amount to collect in the smallest currency unit (e.g.
                        cents for ZAR, kobo for NGN).
                      type: integer
                    mobile:
                      description: >-
                        Customer mobile number in international format without
                        leading + (e.g. 254161166649).
                      type: string
                    country_id:
                      description: >-
                        Niobi country identifier for the collection market. See
                        the [Countries guide](/supported-countries) for the full
                        list.
                      type: integer
                      format: country_id
                    currency:
                      description: >-
                        ISO 4217 currency code for the collection (e.g. KES,
                        NGN, GHS).
                      type: string
                      format: currency
                    payment_method_type:
                      description: >-
                        Payment rail to use. Accepted values vary by country.
                        See the [Collections
                        guide](/collecting-payments/methods) for valid values
                        per market.
                      type: string
                      format: string
                    callback_url:
                      description: >-
                        URL Niobi posts the final transaction status to. Must
                        not be URL-encoded in the signature string.
                      type: string
                      format: uri
                    third_party_reference_1:
                      description: >-
                        Your internal reference for this transaction. Returned
                        in callbacks for reconciliation.
                      type: string
                      format: string
                    third_party_reference_2:
                      description: >-
                        Secondary reference field. Use for external or
                        customer-facing identifiers.
                      type: string
                      format: string
                    sub_merchant_id:
                      description: >-
                        The sub-merchant's ID. Required only if your integration
                        is configured for sub-merchant routing; not applicable
                        otherwise. See [Sub-Merchant
                        Management](/submerchant/sub-merchant-management).
                      type: string
                      format: uuid
                    first_name:
                      description: >-
                        Customer first name. Required for NGN bank and virtual
                        account collections only.
                      type: string
                      format: string
                    last_name:
                      description: >-
                        Customer last name. Required for NGN bank and virtual
                        account collections only.
                      type: string
                      format: string
                    account_name:
                      description: >-
                        Customer bank account name for reconciliation. Required
                        for NGN bank and virtual account collections only.
                      type: string
                      format: string
                    bank_code:
                      description: >-
                        Bank code for virtual account issuance. Required for NGN
                        collections only. Supported: 17001 (78 Finance), 17002
                        (Fidelity Bank), 17003 (Globus Bank).
                      type: string
                      format: string
                    successful_url:
                      description: >-
                        Redirect URL on successful payment. Required for ZAR
                        bank_eft, Capitec, and Wave collections (Senegal, Ivory
                        Coast).
                      type: string
                      format: uri
                    failure_url:
                      description: >-
                        Redirect URL on failed payment. Required for ZAR
                        bank_eft, Capitec, and Wave collections (Senegal, Ivory
                        Coast).
                      type: string
                      format: uri
                    id_number:
                      description: >-
                        Customer South African ID number. Required for ZAR
                        Capitec collections only.
                      type: string
                      format: string
                  type: object
              type: object
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                properties:
                  success:
                    type: boolean
                    example: true
                  message:
                    description: >-
                      Explains the action payers need to take to complete the
                      transaction. Wording varies by currency: NGN returns
                      bank-transfer instructions, ZAR returns a payment link
                      prompt, and every other currency returns the
                      phone-approval prompt.
                    type: string
                    example: >-
                      We've sent a verification prompt to your phone. Please
                      approve it to complete your payment. / Please use the
                      following bank details for making a deposit via your
                      preferred banking application (NGN) / Please use the link
                      provided to finish your payment (ZAR)
                  data:
                    type: object
                    properties:
                      account_name:
                        type: string
                        example: Test Account
                        description: Account holder name
                      amount:
                        type: number
                        example: 500
                        description: Collection transaction amount
                      callback_url:
                        type: string
                        example: https://example.com/callback
                        description: >-
                          Webhook listener URL for asynchronous status
                          notifications
                      country_id:
                        type: integer
                        example: 1
                        description: Niobi Country ID (e.g. 1 for Kenya)
                      currency:
                        type: string
                        example: KES
                        description: 3-letter ISO-4217 currency code
                      mobile:
                        type: string
                        example: '254161166649'
                        description: >-
                          Customer phone number in international format without
                          leading +
                      name:
                        type: string
                        example: John Doe
                        description: Customer full name
                      payment_method_type:
                        type: string
                        example: send money
                        description: >-
                          Channel payment method type (e.g. send money, bank,
                          etc.)
                      third_party_reference_1:
                        type: string
                        example: REF-001
                        description: Unique client reference 1
                      third_party_reference_2:
                        type: string
                        example: REF-002
                        description: Unique client reference 2
                      MerchantRequestID:
                        type: string
                        example: NIO-S0000001
                        description: Niobi transaction tracking ID for status query
                      depositId:
                        type: string
                        example: NIO-S0000001
                        description: Niobi internal deposit ID
                      account_number:
                        type: string
                        nullable: true
                        example: null
                        description: >-
                          Virtual account number if virtual account collection
                          rail
                      bank_name:
                        type: string
                        nullable: true
                        example: null
                        description: Bank name if dynamic bank collection rail
                      bank_code:
                        type: string
                        nullable: true
                        example: null
                        description: Bank code if dynamic bank collection rail
                      status:
                        type: string
                        example: success
                        description: Initial request acknowledgment status
                      payment_token:
                        type: string
                        nullable: true
                        example: null
                        description: Payment token if authorization redirect required
                  status_code:
                    type: string
                    example: '000000'
                type: object
                example:
                  success: true
                  message: >-
                    We've sent a verification prompt to your phone. Please
                    approve it to complete your payment.
                  data:
                    amount: 10
                    callback_url: https://example.com
                    country_id: 1
                    currency: KES
                    mobile: '254161166649'
                    payment_method_type: send money
                    third_party_reference_1: ''
                    third_party_reference_2: ''
                    status: success
                    payment_step: 1
                    payment_token: null
                  status_code: '000000'
              example:
                success: true
                message: >-
                  We've sent a verification prompt to your phone. Please approve
                  it to complete your payment.
                data:
                  account_name: Test Account
                  amount: 500
                  callback_url: https://example.com/callback
                  country_id: 1
                  currency: KES
                  mobile: '254161166649'
                  name: John Doe
                  payment_method_type: send money
                  third_party_reference_1: REF-001
                  third_party_reference_2: REF-002
                  MerchantRequestID: NIO-S0000001
                  depositId: NIO-S0000001
                  account_number: null
                  bank_name: null
                  bank_code: null
                  status: success
                  payment_token: null
                status_code: '000000'
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                properties:
                  success:
                    type: boolean
                    example: false
                  message:
                    type: string
                    example: >-
                      Niobi user not found or Country was not found or
                      Transaction was not created!
                type: object
        '403':
          description: Forbidden
          content:
            application/json:
              schema:
                properties:
                  success:
                    type: boolean
                    example: false
                  message:
                    type: string
                    example: >-
                      Entity integration record not found or Client id not
                      matched or Request was not verified.
                type: object
        '404':
          description: Bad Request
          content:
            application/json:
              schema:
                properties:
                  success:
                    type: boolean
                    example: false
                  message:
                    type: string
                    example: User not found!
                type: object

````