Skip to main content
A mobile money collection asks one payer for one payment. You send the amount and the payer’s phone number. The payer gets a prompt on their phone, in Kenya on M-Pesa or in Uganda on MTN or Airtel, and once they approve it, Bitnob credits your company’s KES or UGX balance. The collection then closes. Collections don’t have their own endpoints. A collection is a virtual account created with rail: "mobile_money", so you create, fetch, list and test it with the virtual account endpoints.

How it works

1

Create the collection

Send the amount, network and payer’s phone number to Create virtual account with rail: "mobile_money". No customer or KYC is needed.
2

The payer approves the prompt

The payer’s phone shows a prompt for the exact amount. Nothing more is needed from you while the collection waits.
3

Your balance is credited

When the payer approves, Bitnob credits your KES or UGX balance, closes the collection and sends virtual_account.deposit.success.
4

Or the collection ends unpaid

If the payer doesn’t complete the payment, or doesn’t respond within about an hour, the collection closes unpaid and Bitnob sends virtual_account.collection.failed.

Networks and limits

List supported currencies returns the same details for each currency, including networks, phone_pattern, min_amount and max_amount, so you can validate input before you call the API. amount is an integer in base units, where 100 is 1 KES or 1 UGX. To collect KES 1,500, send 150000. UGX uses the same rule even though it has no minor unit in everyday use: UGX 20,000 is 2000000.

Create a collection

The response returns the collection with status: "active" while it waits for the payer:
Store id against your order. It’s the virtual_account_id on the deposit webhook, and the ID you pass to Get virtual account to check the collection. On a collection, some fields mean something different from an NGN bank account:

Rules for a collection

  • One payment. A collection takes one payment and then closes. Create a new collection for the next payment.
  • The exact amount. The payer must pay exactly the amount requested.
  • About an hour to pay. A collection that isn’t paid by expires_at closes unpaid, with failure_reason set and a virtual_account.collection.failed webhook.
  • No cancel. There is no endpoint to cancel a collection. An unpaid one ends on its own when it expires.

Collection statuses

Retries and references

reference is your idempotency key. Sending the same reference again while the collection is still active returns the original collection with 201, and the payer is not prompted again. Retry a timed-out create with the same reference, never a new one, or the payer can get two prompts. Once a collection has closed or failed, its reference can’t be used again. Sending it returns 409 DUPLICATE_REFERENCE. Use a new reference to ask the same payer again.

Test in sandbox

In sandbox no prompt reaches a phone. Finish the collection yourself with Simulate deposit, choosing how the payer answers with outcome:
A collection can only be simulated once, while it’s active. Simulating one that has already finished returns 400. Collections have no hourly simulation cap.

Getting access

Collections are switched on per company, and per currency. Until they’re enabled for you, a create returns 403 FEATURE_NOT_ENABLED. Contact Bitnob to have KES or UGX collections enabled.

When something fails

Collections, or collections in that currency, aren’t enabled on your account. The detail names which, for example The UGX mobile money collections feature is currently not available.
A required collection field is missing or empty. amount, network and account_number are all required when rail is mobile_money.
amount is outside the limits for the currency. The message gives the range in major and base units, for example amount must be between 20 and 145000 KES (base units 2000 to 14500000).
The network isn’t one the currency takes. Use MPESA for KES, and MTN or AIRTEL for UGX.
The phone number doesn’t match the country’s format. Check it against phone_pattern from List supported currencies.
NGN is only available as a bank account. Leave rail out to create an NGN virtual account.
The reference belongs to a collection that has already closed or failed, or to an NGN bank account. Use a new reference.
The prompt couldn’t be sent and the collection is left failed. Retry with a new reference.