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

# Momo, XOF and ZAR Collections

> This guide explains how to collect payments directly from your customers' Mobile Money accounts using Payaza — covering MoMo (GHS, KES, UGX, TZS, LRD, XAF), XOF (Côte d'Ivoire and Benin), and ZAR EFT and Capitec (South Africa).

## Key Requirements

<Info>
  Retrieve your API keys from your dashboard by following the steps on our
  [Authentication](/guides/authentication) page. Use your **public API key** for
  all collection requests.
</Info>

Set the following headers on every request:

```json theme={null}
{
  "Authorization": "Payaza <Your public API key encoded in base 64>",
  "X-TenantID": "test",
  "X-ProductID": "app"
}
```

<Note>
  Set `X-TenantID` to `test` while developing and `live` when processing real
  payments. `X-ProductID` defaults to `"app"` for all requests.
</Note>

<Warning>
  Collections to countries other than Nigeria are **available on request only**.
  Send an email to [support@payaza.africa](mailto:support@payaza.africa) to
  request access. You will be granted access once the team reviews and approves
  your request.
</Warning>

Make sure your webhook URL is saved on the dashboard and configured to accept `POST` requests. See our [Webhooks guide](/guides/webhooks) for setup instructions.

## Supported currencies and countries

| Currency | Country            | Network(s)                           |
| -------- | ------------------ | ------------------------------------ |
| GHS      | Ghana 🇬🇭         | MTN, Vodafone, AirtelTigo            |
| KES      | Kenya 🇰🇪         | Safaricom (M-Pesa), Airtel           |
| UGX      | Uganda 🇺🇬        | MTN, Airtel                          |
| TZS      | Tanzania 🇹🇿      | Vodacom, Airtel, Tigo, Halopesa      |
| XAF      | Cameroon 🇨🇲      | MTN, Orange                          |
| XOF      | Côte d'Ivoire 🇨🇮 | MTN, Orange, Wave, Moov              |
| XOF      | Benin 🇧🇯         | MTN, Moov                            |
| ZAR      | South Africa 🇿🇦  | EFT (bank-to-bank redirect), Capitec |
| SLE      | Sierra Leone 🇸🇱  | Afrimoney, Orange Money              |
| LRD      | Liberia 🇱🇷       | Orange Money, MTN                    |

<Note>
  <p className="mb-1">
    Bank codes (`customer_bank_code`) differ per currency and country.
  </p>

  <p>
    The full list of Payaza MoMo collection codes is available{" "}

    <a href="https://docs.google.com/spreadsheets/d/1BOGf_mSLS6rGNm1vn3cO4A2vW9oqZVGI_PxxxXnMK9o/edit?usp=sharing" target="_blank" rel="noopener noreferrer">
      here.
    </a>
  </p>
</Note>

## Phone number format

The `customer_number` field requires the phone number in international format (country code + number, no `+` or spaces).

| Currency / Region            | Format                     | Digits                              | Example          |
| ---------------------------- | -------------------------- | ----------------------------------- | ---------------- |
| GHS, KES, UGX, TZS, XAF, LRD | `{country_code}{number}`   | 12 digits total                     | `233201234567`   |
| XOF — Côte d'Ivoire          | `{country_code}{number}`   | 13 digits total                     | `2250047680712`  |
| XOF — Benin                  | `{country_code}01{number}` | 13 digits total (extra `01` prefix) | `22901789431245` |
| SLE - Sierra Leone           | `{country_code}{number}`   | 11 digits total                     | `23278943124`    |

<Warning>
  Passing a phone number in the wrong format would result in a transaction
  error. Double-check the digit count before sending the request.
</Warning>

## How collections work

Mobile Money collections follow a different flow from card payments because the customer must approve the payment on their own phone.

The flow varies slightly depending on the collection type:

<AccordionGroup>
  <Accordion title="Standard MoMo flow (GHS, KES, UGX, TZS, XAF, LRD)">
    <ol className="list-decimal pl-5 space-y-2 mt-2">
      <li>
        Your server calls <strong>Process Collection</strong> with the customer's
        phone number and amount.
      </li>

      <li>
        Payaza instructs the telecom network to send a{" "}
        <strong>USSD prompt</strong> to the customer's phone.
      </li>

      <li>
        The customer sees a message like{" "}
        <em>"Approve payment of GHS 50 to Business X?"</em> and enters their MoMo
        PIN.
      </li>

      <li>
        Your server uses the <strong>Transaction Status Query API</strong> or
        listens for a <strong>webhook</strong> to confirm success or failure.
      </li>
    </ol>
  </Accordion>

  <Accordion title="XOF flow — Côte d'Ivoire and Benin (OTP is only required for Orange CIV XOF Collections)">
    <ol className="list-decimal pl-5 space-y-3 mt-2">
      <li>
        Your server calls <strong>Process Collection</strong>.
      </li>

      <li>
        Check the <code>requires\_otp</code> field in the response:

        <ul className="list-disc pl-5 space-y-2 mt-2">
          <li>
            If <code>false</code> — the customer is prompted directly on their
            phone. Check for the status.
          </li>

          <li>
            If <code>true</code> — the customer receives an OTP via SMS. Your UI
            must collect the OTP and submit it via{" "}
            <strong>XOF Process OTP API</strong> before the payment can proceed.
          </li>
        </ul>
      </li>

      <li>
        After the OTP is submitted{" "}
        <strong>(Required for Orange CIV XOF Collections)</strong>, use the{" "}
        <strong>Transaction Status Query</strong> or listen for a webhook.
      </li>
    </ol>
  </Accordion>

  <Accordion title="ZAR EFT and Capitec flow — South Africa">
    <ol className="list-decimal pl-5 space-y-3 mt-2">
      <li>
        Your server calls <strong>Process Collection</strong> with{" "}
        <code>currency\_code: "ZAR"</code>.
      </li>

      <li>
        The response includes a <code>payment\_completion\_url</code>.{" "}
        <strong>Redirect the customer to this URL</strong> to complete their EFT
        or Capitec payment.
      </li>

      <li>
        After the customer completes the bank redirect, Use the{" "}
        <strong>Transaction Status Query API</strong> or listen for a webhook.
      </li>
    </ol>
  </Accordion>

  <Accordion title="SLE flow — Sierra Leone (Afrimoney, Orange Money)">
    <ol className="list-decimal pl-5 space-y-2 mt-2">
      <li>
        Your server calls <strong>Process Collection</strong> with{" "}
        <code>currency\_code: "SLE"</code> and the customer's Sierra Leone mobile
        money number.
      </li>

      <li>
        Payaza instructs the mobile money network (Afrimoney or Orange Money) to
        send a <strong>payment prompt</strong> to the customer's phone.
      </li>

      <li>The customer approves the payment on their device.</li>

      <li>
        Use the <strong>Transaction Status Query API</strong> or listen for a
        webhook to confirm the final outcome.
      </li>
    </ol>
  </Accordion>
</AccordionGroup>

***

## Step 1 — Process Collection

Initiate a collection from the customer's Mobile Money wallet.

<CodeGroup>
  ```bash cURL — MoMo (GHS / KES / UGX / TZS / XAF) theme={null}
  curl --request POST \
    --url https://api.payaza.africa/live/subsidiary/collections/v1/process-collection \
    --header 'Authorization: Payaza <Your public API key encoded in base 64>' \
    --header 'Content-Type: application/json' \
    --data '
  {
    "amount": 200,
    "customer_number": "233123456789",
    "transaction_reference": "UDHJQ012340",
    "transaction_description": "Test Payment",
    "customer_bank_code": "SAFKEN",
    "currency_code": "KES",
    "customer_email": "bigmaitre@blondmail.com",
    "customer_first_name": "Robert",
    "customer_last_name": "Stones",
    "customer_phone_number": "012345678901",
    "country_code": "KE"
  }
  '
  ```

  ```bash cURL — XOF (Côte d'Ivoire) theme={null}
  curl --request POST \
    --url https://api.payaza.africa/live/subsidiary/collections/v1/process-collection \
    --header 'Authorization: Payaza <Your public API key encoded in base 64>' \
    --header 'Content-Type: application/json' \
    --header 'X-TenantID: test' \
    --header 'X-ProductID: app' \
    --data '{
      "amount": 2000,
      "customer_number": "2250047680712",
      "transaction_reference": "COL-REF-20240501-002",
      "transaction_description": "Payment for order #5678",
      "customer_bank_code": "MOMCIV",
      "currency_code": "XOF",
      "customer_email": "customer@example.com",
      "customer_first_name": "Adjoua",
      "customer_last_name": "Kouakou",
      "customer_phone_number": "2250047680712",
      "country_code": "CI",
      "redirect_url": "{{redirecturl}}"// For Wave Payments
    }'
  ```

  ```bash cURL — ZAR (South Africa EFT) theme={null}
  curl --request POST \
    --url https://api.payaza.africa/live/subsidiary/collections/v1/process-collection \
    --header 'Authorization: Payaza <Your public API key encoded in base 64>' \
    --header 'Content-Type: application/json' \
    --header 'X-TenantID: test' \
    --header 'X-ProductID: app' \
    --data ' {
    "amount": 100,
    "transaction_reference": "tran2232",
    "transaction_description": "Test Payment",
    "customer_bank_code": "EFTZAR",
    "currency_code": "ZAR",
    "customer_email": "johndoe@gmail.com",
    "customer_first_name": "Tshabalala",
    "customer_last_name": "Doe",
    "redirect_url": "https://redirecturl.com",
    "customer_phone_number": "27113785456",
    "country_code": "ZA"
  }'
  ```

  ```bash cURL — ZAR (South Africa Capitec) theme={null}
  curl --request POST \
    --url https://api.payaza.africa/live/subsidiary/collections/v1/process-collection \
    --header 'Authorization: Payaza <Your public API key encoded in base 64>' \
    --header 'Content-Type: application/json' \
    --header 'X-TenantID: test' \
    --header 'X-ProductID: app' \
    --data ' {
    "amount": 100,
    "transaction_reference": "tran2232",
    "transaction_description": "Test Payment",
    "customer_bank_code": "CPZZAR",
    "currency_code": "ZAR",
    "customer_email": "johndoe@gmail.com",
    "customer_first_name": "Tshabalala",
    "customer_last_name": "Doe",
    "redirect_url": "https://www.zar.com/",
    "id_number": "940109044508390",
    "customer_phone_number": "08166750025",
    "country_code": "ZA"
  }'
  ```

  ```bash cURL — SLE (Sierra Leone) theme={null}
  curl --request POST \
    --url https://api.payaza.africa/live/subsidiary/collections/v1/process-collection \
    --header 'Authorization: Payaza <Your public API key encoded in base 64>' \
    --header 'Content-Type: application/json' \
    --header 'X-TenantID: test' \
    --header 'X-ProductID: app' \
    --data '{
    "amount": 50,
    "customer_number": "23278943124",
    "transaction_reference": "SLE-REF-20240501-001",
    "transaction_description": "Test Payment",
    "customer_bank_code": "AFMSLE",
    "currency_code": "SLE",
    "customer_email": "johndoe@gmail.com",
    "customer_first_name": "John",
    "customer_last_name": "Doe",
    "customer_phone_number": "23278943124",
    "country_code": "SL"
  }'
  ```
</CodeGroup>

**Sample response — Standard MoMo (no OTP)**

```json theme={null}
{
  "response_code": "09",
  "response_message": "PENDING",
  "transaction_reference": "UDH012345",
  "redirect_customer_to_url_processing": false
}
```

**Sample response XOF with OTP required(For Orange CIV Only)**

```json theme={null}
{
  "response_code": "09",
  "response_message": "PENDING",
  "requires_otp": true,
  "otp_length": 4,
  "before_payment_instruction": "1/ Générer un code provisoire en ouvrant l'application Orange Money Afrique et en sélectionnant \\\"Mon Compte\\\", ou en composant le #144*82# et en effectuant l'appel.\\r\\n---\\r\\n2/ Entrez votre code secret et confirmez.\\r\\n---\\r\\n3/Copiez le code que vous avez reçu par SMS et collez-le dans le champ prévu à cet effet.",
  "after_payment_instruction": "Merci de confirmer le paiement en suivant les directives fournies dans le SMS que vous avez reçu.",
  "payment_token": "fcda6596-c7ec-4adb-8030-b8725dbfc66c",
  "payee": "+2251114462945",
  "transaction_channel": "MOMCIV",
  "transaction_reference": "MOCIV0009383"
}
```

**Sample response — XOF with No OTP required**

```json theme={null}
{
  "response_code": "09",
  "response_message": "PENDING",
  "requires_otp": false,
  "otp_length": 0,
  "before_payment_instruction": "Assurez-vous de disposer de fonds suffisants sur votre compte mobile money pour réaliser ce paiement.",
  "after_payment_instruction": "Merci de confirmer le paiement en suivant les directives fournies dans le SMS que vous avez reçu.",
  "payment_token": "e20467b2-d53d-484e-8fd5-a57fcb428d33",
  "payee": "+2250004768076",
  "payment_method": "MTN_CI",
  "transaction_channel": "MOMCIV",
  "transaction_reference": "MOCIV0009384"
}
```

**Sample response — ZAR EFT (redirect required)**

```json theme={null}
{
  "response_code": "09",
  "response_message": "PENDING",
  "before_payment_instruction": "",
  "after_payment_instruction": "",
  "payment_token": "175084951464066",
  "payee": "",
  "payment_method": "EFTZAR",
  "transaction_channel": "EFTZAR",
  "transaction_reference": "tran2232",
  "redirect_customer_to_url_processing": true,
  "payment_completion_url": "https://zar-checkout.payaza.africa/pay/hosted?payment_key=35f558e534a4800a099485a43f8279d6&payment_type=eft"
}
```

**Sample response — ZAR Capitec (redirect required)**

```json theme={null}
{
  "response_code": "09",
  "response_message": "Deposit request sent successfully",
  "payment_token": "39d8cce9-a199-4dfc-bb8e-347318523121",
  "transaction_reference": "refexamplef",
  "redirect_customer_to_url_processing": true,
  "payment_completion_url": "https://secure.peachpayments.com/checkout?plugin=session&checkoutId=6339c805733e49e592052f92d0vdabf"
}
```

<Warning>
  A `response_code: "09"` and `response_message: "PENDING"` is the **expected
  successful response** from this endpoint. It does not mean the collection
  succeeded — it means the prompt has been sent or the redirect URL is ready.
  Always confirm the final outcome via Step 3 (Status Query) or a webhook.
</Warning>

**API reference:** [Momo, XOF and ZAR Process Collection](/api-reference/momo-and-zar-collections/momo-xof-and-zar-process-collection)

## Step 2 — XOF Process OTP *(XOF only)*

<Note>
  This step only applies to **XOF collections** where the initial Process
  Collection response returned `requires_otp: true`. This applies to all Orange
  CIV Money transactions. Skip to Step 3 for all other currencies.
</Note>

When `requires_otp` is `true`, the customer receives an OTP on their phone. Your UI must collect this code from the customer and submit it before the payment can be authorised.

Use the `payment_token`, `payee`, `payment_method`, and `transaction_channel` values directly from the Process Collection response.

<CodeGroup>
  ```bash cURL theme={null}
  curl --request POST \
    --url https://api.payaza.africa/live/subsidiary/collections/v1/process-otp \
    --header 'Authorization: Payaza <Your public API key encoded in base 64>' \
    --header 'Content-Type: application/json' \
    --header 'X-ProductID: app' \
    --header 'X-TenantID: test' \
    --data '
  {
    "payment_token": "45c3d124-7831-4f97-8844-581bf497a20b",
    "otp_code": "4567",
    "payee": "+2251114462945",
    "payment_method": "ORANGE_CI",
    "transaction_reference": "MOCIV0009383",
    "transaction_channel": "MOMCIV",
    "country_code": "CI"
  }
  '
  ```
</CodeGroup>

**Sample response**

```json theme={null}
{
  "response_code": "09",
  "response_message": "PENDING",
  "redirect_customer_to_url_processing": false
}
```

<Note>
  **Test credentials for XOF:**
  <li>Phone number (no OTP required): `225000476807`</li>
  <li>Phone number (OTP required): `2251114462945` - Test OTP value: `4567`</li>
</Note>

**API reference:** [XOF Process OTP](/api-reference/momo-and-zar-collections/xof-process-otp)

## Step 3 — Transaction Status Query

Check the final status of a collection. Use this endpoint to confirm whether the payment was successful, failed, or is still pending.

**When to use it:** Use this endpoint after initiating a collection (and after submitting the OTP for XOF), or use it as a fallback if a webhook is not received.

<CodeGroup>
  ```bash cURL theme={null}
  curl --request GET \
    --url 'https://api.payaza.africa/live/subsidiary/collections/v1/check-status?transaction_reference=COL-REF-20240501-001&country_code=GH' \
    --header 'Authorization: Payaza <Your public API key encoded in base 64>' \
    --header 'X-TenantID: test' \
    --header 'X-ProductID: app'
  ```
</CodeGroup>

**Sample response — pending (customer has not yet approved)**

```json theme={null}
{
  "response_code": "09",
  "transaction_reference": "UDH012345",
  "transaction_amount": 200.27,
  "transaction_fee": 0,
  "transaction_status": "Initialized",
  "payer_name": "Robert Stones",
  "payer_account_number": "233123456789",
  "start_date": "2024-05-21T20:14:01.254748",
  "end_date": "null",
  "currency": "GHS"
}
```

**Sample response — successful**

```json theme={null}
{
  "response_code": "00",
  "transaction_reference": "UDH012345",
  "transaction_amount": 200.27,
  "transaction_fee": 0,
  "transaction_status": "Completed",
  "payer_name": "Robert Stones",
  "payer_account_number": "233123456789",
  "start_date": "2024-05-21T20:14:01.254748",
  "end_date": "2024-05-21T20:14:29.889059",
  "currency": "GHS"
}
```

<Warning>
  Never assume a MoMo collection was successful just because the initial request
  went through. A customer can ignore the USSD prompt, cancel it, or have
  insufficient funds. Always confirm the final status via this endpoint or a
  webhook before fulfilling an order.
</Warning>

**API reference:** [Transaction Status Query](/api-reference/momo-and-zar-collections/transaction-status-query)

## Webhooks

Payaza sends webhook events for both successful and failed collections. Webhooks are the recommended way to receive the final status rather than continuous polling.

| Event                   | When it fires                                             |
| ----------------------- | --------------------------------------------------------- |
| `Successful Collection` | The customer approved the payment and funds were received |
| `Failed Collection`     | The payment was declined, cancelled, or timed out         |

**Sample `Successful Collection` payload**

```json theme={null}
{
  "transaction_reference": "P-C-20260221-PLVOF13731",
  "transaction_status": "Funds Received",
  "transaction_fee": "3",
  "amount_received": "140",
  "initiated_date": "2026-02-21 10:38:25",
  "received_from": {
    "account_name": "John Doe",
    "account_number": "233123456789",
    "bank_name": "N/A"
  },
  "merchant_reference": "testpayment",
  "status": "Completed",
  "session_id": "P-C-20260221-PLVOF13731",
  "channel": "GH_MOBILEMONEY",
  "branch": false,
  "currency_code": "GHS",
  "payaza_account_reference": "",
  "narration": "",
  "business_fk": 100,
  "customer": {
    "email_address": "johndoe@email.com",
    "first_name": "John",
    "last_name": "Doe",
    "mobile_number": "233123456789"
  },
  "request_amount": 140,
  "amount_validation": "EXACT"
}
```

**Sample `Failed Collection` payload**

```json theme={null}
{
  "transaction_reference": "P-C-20260121-PLVOF19731",
  "transaction_status": "Transaction Failed",
  "transaction_fee": "3",
  "amount_received": "140",
  "initiated_date": "2026-01-21 10:38:25",
  "received_from": {
    "account_name": "John Doe",
    "account_number": "233123456789",
    "bank_name": "N/A"
  },
  "merchant_reference": "testpayment",
  "status": "Failed",
  "session_id": "P-C-2026121-PLVOF19731",
  "channel": "GH_MOBILEMONEY",
  "branch": false,
  "currency_code": "GHS",
  "payaza_account_reference": "",
  "narration": "",
  "business_fk": 100,
  "customer": {
    "email_address": "johndoe@email.com",
    "first_name": "John",
    "last_name": "Doe",
    "mobile_number": "233123456789"
  },
  "request_amount": 140,
  "amount_validation": "EXACT"
}
```

<Note>
  Always verify the webhook signature before processing the payload. See the
  [Webhooks guide](/guides/webhooks) for verification steps.
</Note>

## Response Codes

| Code    | Meaning | What to do                    |
| ------- | ------- | ----------------------------- |
| `00`    | SUCCESS | The transaction is successful |
| `06/96` | FAILED  | The transaction has failed.   |
| `09`    | PENDING | The transaction is pending    |

## Developer notes

* Always generate a unique `transaction_reference` per collection to avoid duplicate errors.
* A `response_code: "09"` on Process Collection is normal — it means the prompt was sent, not that the collection succeeded.
* For XOF, check `requires_otp` in the Process Collection response before deciding whether to show an OTP input field in your UI.
* For ZAR, check `redirect_customer_to_url_processing` and redirect the customer to `payment_completion_url` to complete payment via their bank.
* Webhooks are sent for both successful and failed collections. Use Transaction Status Query as a fallback when a webhook is not received within your expected timeout.
* Collections are **not retried** automatically. If a collection fails or times out, your application must handle the retry logic and generate a new `transaction_reference`.
* Use the bank code that matches both the **currency** and the **telecom network** of the customer's MoMo account. Mismatched bank codes will fail silently on some networks.
