Kavopay API

API Reference

Query wallet data from your own app or server using a personal API key. All requests are made over HTTPS to the base URL below.

Base URLhttps://api.kavopaywalletz.com
AuthPublic key + secret key
Formatapplication/json

Authentication

Every request needs two headers: X-Public-Key identifies you as a known API caller, and the Authorization bearer token is your secret key that authorizes access to your account's data. Both come from the Developer tab in your dashboard and must belong to the same account.

X-Public-Key: kavo_pub_xxxxxxxxxxxxxxxx
Authorization: Bearer kavo_live_xxxxxxxxxxxxxxxx
Skip the X-Public-Key and it's not just rejected. Your IP gets blocked from calling this API for 30 minutes, so check that header first before you look anywhere else.
Your account needs at least Tier 1 verification to use the API. Keys on unverified or Tier 0 accounts are rejected.

Errors

StatusMeaning
400Missing or unrecognized public key. Your IP is temporarily blocked
401Missing, invalid, or revoked secret key
403Account below Tier 1 verification
404Unknown endpoint, or payment reference not found
405Wrong HTTP method for this endpoint
429Too many requests, slow down and retry
502The payment provider rejected the request, try again

Rate limits

60 requests per minute per IP address. Requests over the limit get a 429 with a short cooldown message.

Get wallet balance

GET /v1/balance

Returns the current wallet balance for the account that owns the key.

cURL
JavaScript
Node
curl https://api.kavopaywalletz.com/v1/balance \
  -H "X-Public-Key: kavo_pub_xxxxxxxxxxxxxxxx" \
  -H "Authorization: Bearer kavo_live_xxxxxxxxxxxxxxxx"
const res = await fetch("https://api.kavopaywalletz.com/v1/balance", {
  headers: {
    "X-Public-Key": "kavo_pub_xxxxxxxxxxxxxxxx",
    Authorization: "Bearer kavo_live_xxxxxxxxxxxxxxxx"
  }
});
const data = await res.json();
console.log(data.balance);
const https = require("https");

https.get("https://api.kavopaywalletz.com/v1/balance", {
  headers: {
    "X-Public-Key": "kavo_pub_xxxxxxxxxxxxxxxx",
    Authorization: "Bearer kavo_live_xxxxxxxxxxxxxxxx"
  }
}, res => {
  let body = "";
  res.on("data", chunk => body += chunk);
  res.on("end", () => console.log(JSON.parse(body)));
});

Response

HTTP/1.1 200 OK

{
  "ok": true,
  "balance": 42500.00,
  "currency": "NGN"
}

Initiate a payment

POST /v1/payments

Starts a payment. Once it's paid, the amount is credited straight to your Kavopay wallet, same as it always has, withdrawable anytime from the Kavopay app or website. Currency is always NGN, that's the only currency Kavopay wallets hold.

FieldRequiredNotes
amountAlwaysMinimum ₦100. No upper limit, that only applies to transfers out of your wallet, not deposits into it
methodAlwayscard, opay, ussd, or bank_transfer
redirect_urlcard, opay onlyWhere your customer lands after paying
bank_codeussd onlySee supported banks below

Card

Returns a Flutterwave-hosted checkout link. Your customer enters card details there, never on your own server, keeps you out of PCI-DSS scope entirely.

curl -X POST https://api.kavopaywalletz.com/v1/payments \
  -H "X-Public-Key: kavo_pub_xxxxxxxxxxxxxxxx" \
  -H "Authorization: Bearer kavo_live_xxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"amount":5000,"method":"card","redirect_url":"https://yoursite.com/paid"}'
{
  "ok": true,
  "method": "card",
  "reference": "KAVO-CARD-A1B2C3D4-1736500000000",
  "payment_link": "https://checkout.flutterwave.com/v3/hosted/pay/xxxxxxxxx"
}

OPay

Same shape as card, a redirect link, this time to OPay's own checkout.

curl -X POST https://api.kavopaywalletz.com/v1/payments \
  -H "X-Public-Key: kavo_pub_xxxxxxxxxxxxxxxx" \
  -H "Authorization: Bearer kavo_live_xxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"amount":5000,"method":"opay","redirect_url":"https://yoursite.com/paid"}'
{
  "ok": true,
  "method": "opay",
  "reference": "KAVO-OPAY-A1B2C3D4-1736500000000",
  "payment_link": "https://checkout.flutterwave.com/opay/xxxxxxxxx"
}

USSD

Returns a USSD code your customer dials on their phone to complete payment, no internet needed on their end. Needs a bank_code from the supported list:

BankCode
Access Bank044
GTBank058
UBA033
Zenith Bank057
First Bank011
Fidelity070
Sterling232
Union Bank032
Polaris076
Keystone082
curl -X POST https://api.kavopaywalletz.com/v1/payments \
  -H "X-Public-Key: kavo_pub_xxxxxxxxxxxxxxxx" \
  -H "Authorization: Bearer kavo_live_xxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"amount":5000,"method":"ussd","bank_code":"058"}'
{
  "ok": true,
  "method": "ussd",
  "reference": "KAVO-USSD-A1B2C3D4-1736500000000",
  "ussd_code": "*737*000*5000#",
  "payment_code": "000000",
  "bank_code": "058"
}

Bank transfer

Returns your account's permanent virtual account number, the same one every time. Any transfer into it credits your wallet automatically, no reference, no verify support for this method, just watch for the webhook or check your balance.

curl -X POST https://api.kavopaywalletz.com/v1/payments \
  -H "X-Public-Key: kavo_pub_xxxxxxxxxxxxxxxx" \
  -H "Authorization: Bearer kavo_live_xxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"amount":5000,"method":"bank_transfer"}'
{
  "ok": true,
  "method": "bank_transfer",
  "account_number": "8012345678",
  "bank_name": "Wema Bank",
  "account_name": "Your Registered Name",
  "currency": "NGN",
  "note": "This is your permanent account number, reused for every deposit."
}
No virtual account yet? Complete Tier 1 verification in the Kavopay app first, it's created automatically once your NIN is verified.

Verify a payment

GET /v1/payments/:reference

Re-checks a card, OPay, or USSD payment's status. This never credits your wallet itself, it only reports what's true, your wallet is always credited by Kavopay's own systems, this just tells you where things stand.

curl https://api.kavopaywalletz.com/v1/payments/KAVO-CARD-A1B2C3D4-1736500000000 \
  -H "X-Public-Key: kavo_pub_xxxxxxxxxxxxxxxx" \
  -H "Authorization: Bearer kavo_live_xxxxxxxxxxxxxxxx"
{
  "ok": true,
  "reference": "KAVO-CARD-A1B2C3D4-1736500000000",
  "method": "card",
  "amount": 5000,
  "status": "successful"
}
StatusMeaning
pendingCustomer hasn't completed payment yet
processingPayment confirmed, wallet credit is finalizing
successfulCredited to your wallet
failedPayment failed or was cancelled

Webhooks

Set a webhook URL from the Developer tab in your dashboard, and every successful API-initiated payment posts here automatically, no polling needed.

{
  "event": "payment.successful",
  "reference": "KAVO-CARD-A1B2C3D4-1736500000000",
  "amount": 5000,
  "currency": "NGN",
  "method": "card",
  "status": "successful",
  "timestamp": "2026-09-10T18:53:00.000Z"
}

Every request carries an X-Kavopay-Signature header, an HMAC-SHA256 hex digest of the raw request body, signed with your webhook secret. Recompute it yourself and compare before trusting the payload.