Quickstart
Accept your first payment in six steps — SDK install (optional), API app, embed, webhooks, and live keys.
Step 0 — Install the SDK (recommended)
The quickest way to integrate is with an official SDK. If you prefer raw HTTP, skip this step — every endpoint includes a cURL example.
npm install @watenga/node
# or
yarn add @watenga/node
// Usage
import Watenga from '@watenga/node';
const watenga = new Watenga('sk_test_your_key');Laravel developers: the PHP SDK works natively in Laravel. See the Laravel integration guide.
Step 1: Create an API App
Watenga uses API apps — each app has its own keys, webhook configuration, and feature toggles (refunds, payment links, payouts).
- Log into your merchant dashboard at dashboard.watenga.africa.
- Go to Developer in the sidebar.
- Click New App and choose Sandbox for testing.
Screenshot
Once created, your Client ID (public key) and Secret Key are shown. Copy the Secret Key immediately — it will never be shown again.
Step 2: Embed Watenga.js
Load the script, add a container element, and mount the widget with your sandbox Client ID.
<script src="https://js.watenga.africa/v1/watenga.js"></script>
<div id="payment-form"></div>
<script>
const w = Watenga('pk_test_your_client_id');
w.mount('#payment-form', {
amount: 25.00,
currency: 'USD',
reference: 'INV-001',
onSuccess: function(txn) { console.log(txn); },
onError: function(err) { console.error(err); }
});
</script>Step 3: Handle onSuccess
onSuccessfires when the customer's payment is confirmed by Watenga on the client. Use it for UI feedback — thank-you screens, redirects, or cart clearing.
Always verify server-side
onSuccess alone. A malicious client could call your callback without paying. Always wait for a signed payment.capture.completed webhook before marking an order paid.// After onSuccess — always verify via webhook before fulfilling
app.post('/webhooks/watenga', express.raw({ type: 'application/json' }), (req, res) => {
// 1. Verify the 'Watenga-Signature' header (see Webhooks docs)
// 2. Parse the event envelope: { id, type, created, data }
// 3. Check event.type === 'payment.capture.completed'
// 4. Match event.data to your order and mark it paid
res.sendStatus(200);
});Step 4: Verify webhook
In Developer Dashboard → API App → Webhooks, add your endpoint URL and select payment.capture.completed. Watenga signs every payload with the Watenga-Signature header (HMAC-SHA256).
const crypto = require('crypto');
// Watenga signs every delivery with the 'Watenga-Signature' header:
// t=<unix-seconds>,v1=<hmac-sha256-hex>
// where v1 = HMAC_SHA256(secret, `${t}.${rawBody}`)
const header = req.headers['watenga-signature'] || '';
const parts = Object.fromEntries(
header.split(',').map((kv) => kv.split('=').map((s) => s.trim())),
);
const timestamp = Number(parts.t);
const signature = parts.v1 || '';
// Reject replays older than 5 minutes (300s tolerance).
if (!Number.isFinite(timestamp) || Math.abs(Date.now() / 1000 - timestamp) > 300) {
throw new Error('Webhook timestamp outside tolerance window');
}
const expected = crypto
.createHmac('sha256', process.env.WATENGA_WEBHOOK_SECRET)
.update(`${timestamp}.${req.rawBody}`, 'utf8')
.digest('hex');
const a = Buffer.from(signature);
const b = Buffer.from(expected);
if (a.length !== b.length || !crypto.timingSafeEqual(a, b)) {
throw new Error('Invalid signature');
}
// Envelope: { id, object: 'event', type, created, data }
const event = JSON.parse(req.rawBody);
if (event.type === 'payment.capture.completed') {
// fulfil the order — event.data holds the transaction
}Step 5: Go live
- □KYC approved (check dashboard status)
- □Create a Live app in Developer Dashboard (https://dashboard.watenga.africa/developer)
- □Replace sandbox keys with live app keys
- □Update webhook URL in the live app's Webhooks tab
- □Test with a real small payment
- □Enable the features you need in the live app settings
