Skip to main content

Key Requirements

Retrieve your API keys from your dashboard by following the steps on our Authentication page. Use your public API key for all collection requests.
Set the following headers on every request:
{
  "Authorization": "Payaza <Your public API key encoded in base 64>",
  "X-TenantID": "test",
  "X-ProductID": "app"
}
Set X-TenantID to test while developing and live when processing real payments. X-ProductID defaults to "app" for all requests.
Collections to countries other than Nigeria are available on request only. Send an email to support@payaza.africa to request access. You will be granted access once the team reviews and approves your request.
Make sure your webhook URL is saved on the dashboard and configured to accept POST requests. See our Webhooks guide for setup instructions.

Supported currencies and countries

CurrencyCountryNetwork(s)
GHSGhana 🇬🇭MTN, Vodafone, AirtelTigo
KESKenya 🇰🇪Safaricom (M-Pesa), Airtel
UGXUganda 🇺🇬MTN, Airtel
TZSTanzania 🇹🇿Vodacom, Airtel, Tigo, Halopesa
XAFCameroon 🇨🇲MTN, Orange
XOFCôte d’Ivoire 🇨🇮MTN, Orange, Wave, Moov
XOFBenin 🇧🇯MTN, Moov
ZARSouth Africa 🇿🇦EFT (bank-to-bank redirect), Capitec
SLESierra Leone 🇸🇱Afrimoney, Orange Money
LRDLiberia 🇱🇷Orange Money, MTN

Bank codes (customer_bank_code) differ per currency and country.

The full list of Payaza MoMo collection codes is availablehere.

Phone number format

The customer_number field requires the phone number in international format (country code + number, no + or spaces).
Currency / RegionFormatDigitsExample
GHS, KES, UGX, TZS, XAF, LRD{country_code}{number}12 digits total233201234567
XOF — Côte d’Ivoire{country_code}{number}13 digits total2250047680712
XOF — Benin{country_code}01{number}13 digits total (extra 01 prefix)22901789431245
SLE - Sierra Leone{country_code}{number}11 digits total23278943124
Passing a phone number in the wrong format would result in a transaction error. Double-check the digit count before sending the request.

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:
  1. Your server calls Process Collection with the customer’s phone number and amount.
  2. Payaza instructs the telecom network to send a USSD prompt to the customer’s phone.
  3. The customer sees a message like “Approve payment of GHS 50 to Business X?” and enters their MoMo PIN.
  4. Your server uses the Transaction Status Query API or listens for a webhook to confirm success or failure.
  1. Your server calls Process Collection.
  2. Check the requires_otp field in the response:
    • If false — the customer is prompted directly on their phone. Check for the status.
    • If true — the customer receives an OTP via SMS. Your UI must collect the OTP and submit it via XOF Process OTP API before the payment can proceed.
  3. After the OTP is submitted (Required for Orange CIV XOF Collections), use the Transaction Status Query or listen for a webhook.
  1. Your server calls Process Collection with currency_code: “ZAR”.
  2. The response includes a payment_completion_url. Redirect the customer to this URL to complete their EFT or Capitec payment.
  3. After the customer completes the bank redirect, Use the Transaction Status Query API or listen for a webhook.
  1. Your server calls Process Collection with currency_code: “SLE” and the customer’s Sierra Leone mobile money number.
  2. Payaza instructs the mobile money network (Afrimoney or Orange Money) to send a payment prompt to the customer’s phone.
  3. The customer approves the payment on their device.
  4. Use the Transaction Status Query API or listen for a webhook to confirm the final outcome.

Step 1 — Process Collection

Initiate a collection from the customer’s Mobile Money wallet.
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"
}
'
Sample response — Standard MoMo (no OTP)
{
  "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)
{
  "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
{
  "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)
{
  "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)
{
  "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"
}
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.
API reference: Momo, XOF and ZAR Process Collection

Step 2 — XOF Process OTP (XOF only)

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.
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.
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"
}
'
Sample response
{
  "response_code": "09",
  "response_message": "PENDING",
  "redirect_customer_to_url_processing": false
}
Test credentials for XOF:
  • Phone number (no OTP required): 225000476807
  • Phone number (OTP required): 2251114462945 - Test OTP value: 4567
  • API reference: 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.
    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'
    
    Sample response — pending (customer has not yet approved)
    {
      "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
    {
      "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"
    }
    
    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.
    API reference: 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.
    EventWhen it fires
    Successful CollectionThe customer approved the payment and funds were received
    Failed CollectionThe payment was declined, cancelled, or timed out
    Sample Successful Collection payload
    {
      "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
    {
      "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"
    }
    
    Always verify the webhook signature before processing the payload. See the Webhooks guide for verification steps.

    Response Codes

    CodeMeaningWhat to do
    00SUCCESSThe transaction is successful
    06/96FAILEDThe transaction has failed.
    09PENDINGThe 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.