Payments
Accept mobile money and cards with a single integration.
Create the payment from your server: Wajub picks the connection, takes the request to the operator and notifies you of the result. If a mobile money connection is down, Wajub tries the next one within the same request.
- Signed webhooks
- Built-in idempotency
They get paid with Wajub
Why Wajub Payments
Everything collecting payments takes, already built.
Routing, failover, webhooks and refunds: Wajub handles them, and every step shows on the payment's page in the Dashboard.
No provider in your code
You create the payment, and Wajub picks the connection once the customer's number is known. The API has no provider field: add, remove or reorder your connections in the Dashboard, without redeploying.
An outage doesn't cost the sale
If a mobile money connection is down, Wajub tries the next one within the same request: your customer doesn't start over. If a connection receives the request and then goes silent, the payment stays pending so it can't be charged twice.
The result reaches your server
Every payment event goes out as a webhook signed with HMAC-SHA256. If your server returns an error or doesn't answer, Wajub retries at growing intervals for 72 hours, and every delivery shows on the payment's page.
Refund without leaving the Dashboard
Full or partial refunds, from the payment's page or through the API. You choose who pays the fees, and the customer is notified.
Coverage
69 payment channels in 24 countries.
Your app starts the payment on the operator your customer picks. Every channel listed here is available in the API, with the connections able to carry it.
Benin
MTN MoMo, Moov Money
Burkina Faso
Orange Money, Moov Money, Wave
Cameroon
MTN MoMo, Orange Money, Wave, Express Union
Congo - Brazzaville
MTN MoMo, Airtel Money
Congo - Kinshasa
MTN MoMo, Orange Money, Airtel Money, M-Pesa, Africell Money, Vodacom M-Pesa
Côte d’Ivoire
MTN MoMo, Orange Money, Moov Money, Wave, Djamo
Gabon
Airtel Money, Moov Money
Ghana
MTN MoMo, Telecel Cash, AirtelTigo Money
Guinea
MTN MoMo, Orange Money
Kenya
Airtel Money, M-Pesa
Liberia
MTN MoMo
Malawi
Airtel Money, TNM Mpamba
Mali
Orange Money, Moov Money
Mozambique
M-Pesa
Niger
Airtel Money, Moov Money
Nigeria
MTN MoMo, Bank account debit, Bank transfer, Transfer to a dedicated account, USSD
Rwanda
MTN MoMo, Airtel Money
Senegal
Orange Money, Wave, Djamo, Free Money
Sierra Leone
Orange Money
South Africa
Capitec Pay, EFT, QR
Tanzania
Airtel Money, M-Pesa, HaloPesa, Tigo Pesa, Vodacom M-Pesa, Zantel
Togo
Moov Money, T-Money, Togocel
Uganda
MTN MoMo, Airtel Money, Wave
Zambia
MTN MoMo, Airtel Money, Zamtel Money
For developers
Two calls to get paid, one webhook to confirm it.
Your server creates the payment, then starts it on your customer's number. Wajub sends you a signed webhook as soon as the payment succeeds. In sandbox, the last six digits of the test number decide the outcome.
POST /paymentsCreate the payment- Amount, currency, a customer contact (email, phone or customer ID) and your reference. An idempotency key prevents a duplicate if the call is replayed.
POST /payments/{id}Start the payment- Pass the channel and the customer's number. Wajub picks the connection that carries this channel, and the response holds the message to show your customer while they confirm.
payment.succeededReceive the webhook- A signed event reaches your server as soon as the payment succeeds. If it is not received, Wajub retries for 72 hours.
GET /payments/{id}Read the payment back- Before you deliver, read the payment by its ID: its status is the one that counts.
import { Wajub } from '@wajub/node'
const wajub = new Wajub({ secretKey: process.env.WAJUB_SECRET_KEY! })
const payment = await wajub.payments.create(
{
amount: 15000,
currency: 'XAF',
phone: '+237677123456',
reference: 'order-4172',
},
{ idempotencyKey: 'order-4172' },
)
await wajub.payments.process(
payment.id,
{ channel: 'cm.mtn', data: { phone: '+237677123456' } },
{ idempotencyKey: 'charge-order-4172-1' },
)
// Webhook
const event = wajub.webhooks.constructEvent(rawBody, signature, timestamp)
const paid = await wajub.payments.retrieve(String(event.data.id))
if (paid.status === 'succeeded') await fulfil(paid.reference)Response202 Accepted
{"code": 202,"status": "Accepted","message": "Confirm the transaction on your phone.","transaction": {"id": "trx_7Hq2LmX9pR4tVb8KcN3w","status": "processing","channel": "cm.mtn"}}
WebhookX-Wajub-Signature
{"event": "payment.succeeded","data": {"id": "trx_7Hq2LmX9pR4tVb8KcN3w","reference": "order-4172","amount": 15000,"currency": "XAF","status": "succeeded"},"livemode": true}
Response202 Accepted
{"code": 202,"status": "Accepted","message": "Confirm the transaction on your phone.","transaction": {"id": "trx_7Hq2LmX9pR4tVb8KcN3w","status": "processing","channel": "cm.mtn"}}
WebhookX-Wajub-Signature
{"event": "payment.succeeded","data": {"id": "trx_7Hq2LmX9pR4tVb8KcN3w","reference": "order-4172","amount": 15000,"currency": "XAF","status": "succeeded"},"livemode": true}
Pricing
No subscription to start, payments included in every plan.
Pay as you go has no subscription and no setup fee. Payments through your own connections are included up to your plan's quota, then billed per payment. On the Wajub rail, a commission applies depending on the plan.
| Feature | Pay as you go$0You only pay for usage beyond the quota | GrowthRecommended$17/ monthBilled monthly, no commitment | Scale$52/ monthBilled monthly, no commitment | EnterpriseCustom |
|---|---|---|---|---|
| Payments included per month | 200 | 1,000 | 5,000 | Unlimited |
| Per payment beyond | $0.23 | $0.17 | $0.11 | $0.09 |
| Connections | 2 | 6 | Unlimited | Unlimited |
| API rate limit | 120 / min | 360 / min | 720 / min | Unlimited |
| Wajub rail commission | from 2% | from 1.7% | from 1.5% | from 1.2% |
Pay as you go
$0
You only pay for usage beyond the quota
- Payments included per month
- 200
- Per payment beyond
- $0.23
- Connections
- 2
- API rate limit
- 120 / min
- Wajub rail commission
- from 2%
Growth
Recommended
$17
/ month
Billed monthly, no commitment
- Payments included per month
- 1,000
- Per payment beyond
- $0.17
- Connections
- 6
- API rate limit
- 360 / min
- Wajub rail commission
- from 1.7%
Scale
$52
/ month
Billed monthly, no commitment
- Payments included per month
- 5,000
- Per payment beyond
- $0.11
- Connections
- Unlimited
- API rate limit
- 720 / min
- Wajub rail commission
- from 1.5%
Enterprise
Custom
- Payments included per month
- Unlimited
- Per payment beyond
- $0.09
- Connections
- Unlimited
- API rate limit
- Unlimited
- Wajub rail commission
- from 1.2%
Subscriptions and add-ons are billed in CFA francs, or in euros by card at the fixed rate of 655.957 CFA francs. Amounts in your currency are indicative, at today's rate.
Other ways to get paid
Get paid at checkout and by link too.
Checkout and Link open the same payment methods and report to the same Dashboard as your API payments.
Checkout
Payment page hosted by Wajub, with your logo and colours.
- Mobile money and cards
- French and English
Link
Get paid with a simple link: product, event, fundraising, donation.
- 25 links included, no subscription
- Mobile money and cards
Frequently asked questions
Another question? Talk to the team
- How long does a Wajub Payments integration take?
- Two calls and a webhook: you create the payment, start it on the customer's number, then verify the webhook. The direct API guide walks through it in sandbox, end to end.
- What are the transaction fees?
- On the Wajub rail, a fee applies to each payment depending on your plan. With your own connections, your provider bills you under your contract, and Wajub bills the subscription and orchestration usage beyond the included quota. Details are on the Pricing page.
- Which currencies can I accept?
- A currency can be accepted as soon as one of your connections carries a channel in it: XAF on MTN MoMo in Cameroon, XOF on Wave in Senegal, for example. The exchange rate is locked when the payment starts.
- How do I confirm a payment really succeeded?
- Server-side, with GET /payments/{id} or the payment.succeeded webhook. The customer's return to your site is for display, not fulfilment: a return URL can be edited by hand.
- Can I use my secret key in a web app?
- No, it stays on your server. A secret key used from a browser is refused, and its owner is notified by email.
Take your first payment today.
Create your account, run your first payments in sandbox with test numbers, then go live with your live keys.








