Quickstart
Process your first payment end-to-end — account creation, API keys, verification, and your first webhook — in under five minutes.
This guide takes you from an empty account to a verified payment with a working webhook. You'll need a Wajub account (free) and a few minutes.
1. Create your account and get your keys
Create an account on the Dashboard. Once logged in, open Developers → API Keys. Each account has two sets of keys:
pk_test.… / sk_test.…sandboxoptionalpk.… / sk.…productionoptionalKeep your private keys server-side
The public key (pk./pk_test.) initializes payments client-side. The private key
(sk./sk_test.) authorizes sensitive operations (refunds, transfers) and must never be
exposed in a browser or mobile app.
2. Install the SDK for your language
npm install @wajub/nodeFor a detailed SDK reference — configuration, all resources, webhooks — see the SDK guides.
3. Initialize a payment
Server-side, create a payment. Wajub returns an id and a hosted authorization_url
to redirect your customer to.
Which key to use here?
Payment initialization uses the public key (pk_test.…) — it is the one client-safe
operation. All other operations (refunds, transfers, balance reads) require the private key
(sk_test.…). The SDK examples below use the private key because SDKs are always used server-side
and handle all operations. See Key Concepts → API keys for the
full breakdown.
curl https://api.wajub.com/payments \
-H "Authorization: pk_test.8f2b91c4d7e6a0f3" \
-H "Content-Type: application/json" \
-d '{
"amount": 5000,
"currency": "XAF",
"email": "client@example.com",
"callback": "https://example.com/return"
}'Official server SDKs are available for Node.js, Python, PHP, Go, Ruby, Java, and C# — see Server SDKs.
4. Test with sandbox Mobile Money numbers
On the payment page (in test mode), use a test number to simulate each outcome:
The outcome is controlled by the number's last 6 digits, not the country — the same suffixes work for every operator:
| Suffix | Result |
|---|---|
000000 | Payment succeeded |
000001 | Insufficient funds |
000002 | Failure — operator declined |
000003 | Timeout |
000004 | Pending → cancelled |
000009 | Payment succeeds, a later refund on it fails |
Example numbers by country/operator:
| Country / Operator | Prefix | Example (success) |
|---|---|---|
| Cameroon — MTN | +23767 | +237670000000 |
| Cameroon — Orange | +23769 | +237690000000 |
| Côte d'Ivoire — MTN | +22505 | +225050000000 |
| Côte d'Ivoire — Orange | +22507 | +225070000000 |
| Côte d'Ivoire — Wave | +22503 | +225030000000 |
| Senegal — Orange | +22177 | +221770000000 |
| Ghana — MTN | +23324 | +233240000000 |
| Nigeria — MTN | +2348 | +2348000000000 |
| Kenya — M-Pesa | +25470 | +254700000000 |
| Uganda — MTN | +25677 | +256770000000 |
Use any PIN when prompted on the sandbox payment page.
5. Verify the payment server-side
Never rely solely on the browser return: verify the status server-side before fulfilling the order.
https://api.wajub.com/payments/{id}curl https://api.wajub.com/payments/trx_01JXXXXXXXXXXXXX \
-H "Authorization: pk_test.8f2b91c4d7e6a0f3"{
"status": "OK",
"code": 200,
"transaction": {
"id": "trx_01JXXXXXXXXXXXXX",
"status": "succeeded",
"amount": 5000,
"currency": "XAF",
"channel": "cm.mtn"
}
}Track the transaction in Konsole
Open Konsole → API Logs to see the exact request/response Wajub recorded, or Routing Log to see which provider was chosen and why.
6. Set up a webhook endpoint
The browser return URL is not reliable — the customer can close the tab. Webhooks are the source of truth for payment status. Set one up now, before going further.
First, initialize the SDK with your private key and webhook secret:
import { Wajub } from '@wajub/node';
export const wajub = new Wajub({
privateKey: process.env.WAJUB_SECRET_KEY!,
// webhookSecret is used by webhooks.constructEvent() to verify signatures
});app.post('/webhooks/wajub', express.raw({ type: '*/*' }), async (req, res) => {
// Step 1: verify the signature (required in production)
// webhookSecret is configured at construction: new Wajub({ webhookSecret: process.env.WAJUB_WEBHOOK_SECRET })
const event = wajub.webhooks.constructEvent(
req.body,
req.headers['x-wajub-signature'],
req.headers['x-wajub-timestamp'],
);
// Step 2: acknowledge immediately (before processing)
res.sendStatus(200);
// Step 3: act on the event
if (event.event === 'payment.succeeded') {
await fulfillOrder(event.data.id); // your logic here
}
});Register your endpoint URL in Konsole → Webhooks → Endpoints (or Developers → Webhooks in the Dashboard):
- Click Add Endpoint.
- Enter your public URL (e.g.
https://yourapp.com/webhooks/wajub). - Select the events to receive (start with
payment.*for all payment events). - Save and copy the Signing Secret (
whsec_…) — add it to your environment asWAJUB_WEBHOOK_SECRET.
To test locally without deploying, use the CLI tunnel:
npm install -g @wajub/cli
wajub listen --forward-to localhost:3000/webhooks/wajubThis creates a secure tunnel and forwards all sandbox events to your local server. See the CLI listen command for all options.
Complete webhook guide
Signature verification, retry policy, event catalog, and idempotency are all covered in the Webhooks section.
What's next?
Related pages
Integration checklist
0/4Was this page helpful?