Wallet top-up (API)
Top up your organisation’s unit wallet from your own system, no dashboard login required. You call one endpoint to generate a Paystack payment link, send your payer to it, and your wallet is credited automatically once the payment succeeds.
How it works
Section titled “How it works”- Initialize:
POST /topup/initializewith a unit count. You get back anauthorization_url(the payment link). - Pay: send your payer to that URL. They complete payment on Paystack.
- Auto-credit: on success, Paystack notifies RandaVerify and your wallet is credited automatically. You do not host a webhook; it’s handled on our side.
You may optionally call POST /topup/verify to confirm a payment immediately instead of waiting for the webhook.
Authentication
Section titled “Authentication”Every call needs an org-admin bearer token from /login. Team-member tokens cannot initiate top-ups.
curl -X POST https://api.randaverify.com/v1/login \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "username=$USERNAME&password=$PASSWORD"# -> { "access_token": "…", "token_type": "bearer" }Step 1: Generate the payment link
Section titled “Step 1: Generate the payment link”POST/topup/initialize
Send the body as application/x-www-form-urlencoded (not JSON).
| Field | Type | Required | Notes |
|---|---|---|---|
units | integer | ✅ | Positive multiple of 100; must meet your plan’s minimum top-up |
curl -X POST https://api.randaverify.com/v1/topup/initialize \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "units=5000"import requests
resp = requests.post( "https://api.randaverify.com/v1/topup/initialize", headers={"Authorization": f"Bearer {token}"}, data={"units": 5000}, # form-encoded timeout=30,)resp.raise_for_status()body = resp.json()payment_link = body["authorization_url"]reference = body["reference"]const res = await fetch('https://api.randaverify.com/v1/topup/initialize', { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/x-www-form-urlencoded', }, body: new URLSearchParams({ units: '5000' }),});if (!res.ok) throw new Error(`Init failed: ${res.status}`);const { authorization_url, reference } = await res.json();Response (200)
Section titled “Response (200)”{ "authorization_url": "https://checkout.paystack.com/xxxxxxxxxx", "reference": "TOP-30-a1b2c3d4e5f6a7b8", "access_code": "xxxxxxxxxx", "base_amount": 400000, "vat_amount": 30000, "service_charge": 6800, "total_amount": 436800, "units": 5000, "unit_cost": 80, "discount": null}authorization_url is the payment link, redirect your payer there or embed it in your checkout. Keep reference; you’ll need it to reconcile the payment.
Step 2: Payer completes payment
Section titled “Step 2: Payer completes payment”Send the payer to authorization_url. Paystack handles card, bank transfer, USSD, QR and mobile-money channels and returns them to your configured Paystack callback when done.
Step 3: Wallet is credited automatically
Section titled “Step 3: Wallet is credited automatically”On a successful charge, Paystack notifies RandaVerify’s webhook and your wallet is credited, idempotently, keyed on reference (a duplicate notification never double-credits). No action or webhook is required on your side.
Optional: confirm immediately
Section titled “Optional: confirm immediately”To update your own UI without waiting for the webhook, verify the reference yourself:
POST/topup/verify
| Field | Type | Required | Notes |
|---|---|---|---|
reference | string | ✅ | The reference from Step 1 |
curl -X POST https://api.randaverify.com/v1/topup/verify \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "reference=TOP-30-a1b2c3d4e5f6a7b8"resp = requests.post( "https://api.randaverify.com/v1/topup/verify", headers={"Authorization": f"Bearer {token}"}, data={"reference": reference}, timeout=30,)resp.raise_for_status()print(resp.json()) # { message, units_added, new_balance, price_paid }const res = await fetch('https://api.randaverify.com/v1/topup/verify', { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/x-www-form-urlencoded', }, body: new URLSearchParams({ reference }),});const result = await res.json(); // { message, units_added, new_balance, price_paid }Response (200)
Section titled “Response (200)”{ "message": "Top-up successful", "units_added": 5000, "new_balance": 5000, "price_paid": 400000}price_paid is the base amount (revenue); VAT and the service charge are pass-through and recorded separately on the transaction. Calling verify after the webhook already credited the reference returns the same success with "message": "Top-up already credited", safe to call either, or both.
Notes & limits
Section titled “Notes & limits”unitsmust be a positive multiple of 100 and meet your plan’s minimum top-up, or you get400.- Org-admin token required: a
403means the calling user isn’t an org admin, or the payment reference belongs to a different organisation. - Idempotent on
reference: the webhook and/topup/verifycredit a given payment exactly once. - See the Error reference for status codes and the Wallet & units page for how units are consumed.