Wallet & Keys¶
Your wallet holds the money that purchases draw from. Keys are the credentials that let the API spend it.
Wallet balance¶
Auth: API key or session.
curl https://api.instapaybill.com/api/v1/wallet/manage-wallet-balance \
-H "Authorization: Bearer $IPB_LIVE_KEY" \
-H "User-Agent: my-integration/1.0"
{
"msg": "Wallet balance retrieved successfully",
"data": {
"available": 45000,
"commission": 1250,
"bonus": 0,
"referral": 0,
"pending_deficit": 0
}
}
The response is sent with Cache-Control: no-store — do not cache it.
The four wallet buckets¶
| Bucket | Purpose |
|---|---|
available |
Spendable balance. Purchases draw from here. |
commission |
Commission earned from your own sales. Move to available to spend it. |
bonus |
Promotional bonus. Move to available to spend it. |
referral |
Referral earnings. Move to available to spend it. |
Only available can fund a purchase. A user with ₦0 in available and
₦5,000 in commission cannot buy anything until the commission is moved.
Live vs test wallets¶
The key prefix decides which set of buckets you see:
| Key | Buckets |
|---|---|
sk_live_… |
available, commission, bonus, referral |
sk_test_… |
test_available, test_commission, test_bonus, test_referral |
The response uses the same field names either way — the backend maps them.
The sandbox is different again: it reports a single flat ₦100,000 virtual balance and has no buckets at all.
pending_deficit¶
A non-zero pending_deficit means money was taken from available for
transactions that are still being verified. It is the amount at risk.
Generate a payment reference¶
Auth: API key or session.
curl https://api.instapaybill.com/api/v1/wallet/generate-wallet-reference \
-H "Authorization: Bearer $IPB_LIVE_KEY" \
-H "User-Agent: my-integration/1.0"
Returns a unique reference you can attach to a top-up so the incoming payment is attributed to your account. Used by the funding flows (Paystack, Monnify, Flutterwave).
Wallet history¶
| Method | Path | Access | Description |
|---|---|---|---|
GET |
/api/v1/wallet/ |
App/web | Wallet ledger. Requires a type query parameter. |
GET |
/api/v1/wallet/wallet-data |
App/web | Wallet record |
GET |
/api/v1/wallet/manage-wallet-stat |
App/web | Wallet statistics |
GET |
/api/v1/wallet/manage-wallet-stat-monthly |
App/web | Monthly statistics |
GET |
/api/v1/wallet/manage-wallet-stat-daily |
App/web | Daily statistics |
GET |
/api/v1/wallet/manage-wallet |
App/web | Wallet user record |
PUT |
/api/v1/wallet/manage-wallet |
App/web | Transfer to another user. Requires amount, user, type, pin and a reCAPTCHA token. |
POST |
/api/v1/wallet/manage-wallet-pin |
App/web | Set a wallet PIN |
PUT |
/api/v1/wallet/manage-wallet-pin |
App/web | Change a wallet PIN (also sends oldPin) |
DELETE |
/api/v1/wallet/manage-wallet-pin |
App/web | Disable the wallet PIN |
GET |
/api/v1/wallet/manage-card |
App/web | Saved cards |
GET |
/api/v1/wallet/generate-virtual-account |
App/web | Virtual account |
POST |
/api/v1/wallet/manage-paystack |
App/web | Fund via Paystack (reference) |
POST |
/api/v1/wallet/manage-monnify |
App/web | Fund via Monnify (transactionReference) |
POST |
/api/v1/wallet/manage-flutterwave |
App/web | Fund via Flutterwave (flw_ref, transaction_id, amount) |
PUT |
/api/v1/wallet/manage-commission |
App/web | Move commission to available |
PUT |
/api/v1/wallet/manage-bonus |
App/web | Move bonus to available |
PUT |
/api/v1/wallet/manage-referral |
App/web | Move referral to available |
POST |
/api/v1/wallet/manage-withdrawal |
App/web | Withdraw to a bank account (amount, pin) |
Wallet transfers are app/web only
Moving money between users is deliberately not exposed to the API
channel. The route carries UserNonApiAuth, so an API-key request gets
403 "This service is not available for api channel". The
WhatsApp agent channel blocks it too, with "Use the
app or website for wallet transfers and balance moves".
Buying is the API's job; moving money between users is the app's.
API keys¶
Key management happens in the developer portal,
not over the API. The /api/v1/keys/* routes require a session and are
explicitly blocked for the API channel.
| Method | Path | Access | Description |
|---|---|---|---|
POST |
/api/v1/keys/ |
App/web, agent | Generate sk_test_ and sk_live_ |
GET |
/api/v1/keys/ |
App/web, agent | Fetch the current keys |
POST |
/api/v1/keys/webhook |
App/web, agent | Set the webhook URL (webhook) |
PUT |
/api/v1/keys/webhook |
App/web, agent | Clear the webhook URL |
The service also enforces:
ensureAllowedChannel(userAuth) // 300 if userAuth === 'api'
ensureLiveChannel(userDomain) // 300 if userDomain === 'test'
So even a session with a test key cannot manage production keys.
The portal endpoints¶
The developer portal uses its own SSO-guarded routes:
| Method | Path | Description |
|---|---|---|
GET |
/api/v1/sandbox/keys |
Sandbox key, webhook URL, delivery status and counters |
POST |
/api/v1/sandbox/keys/regenerate |
Rotate the sandbox key |
POST |
/api/v1/sandbox/keys/webhook |
Set the sandbox webhook URL |
GET |
/api/v1/sandbox/live-keys |
Live key and webhook shown in the portal |
POST |
/api/v1/sandbox/live-keys/regenerate |
Generate or rotate the live key |
POST |
/api/v1/sandbox/live-keys/webhook |
Set the production webhook URL |
DELETE |
/api/v1/sandbox/live-keys/webhook |
Clear the production webhook URL |
All of them require the developer session cookie and the exact portal Origin
header.
The portal displays only Sandbox key and Live key. Older integration test credentials remain backend compatibility fields and are not offered in the portal.
Key formats¶
| Key | Format | Scope |
|---|---|---|
| Live | sk_live_ + 24 alphanumeric chars |
Real wallet, real providers |
| Sandbox | sk_test_ + 64 hex chars |
Simulated only, /api/v1/sandbox/* |
Rotating a key is immediate and total
Regenerating invalidates the old key instantly. Any integration still
using it starts getting 403 "Invalid Authentication, Unauthorized
User" on the very next request. Rotate deliberately, and update every
consumer of the key in the same operation.
Current user¶
Auth: API key or session.
curl https://api.instapaybill.com/api/v1/user/ \
-H "Authorization: Bearer $IPB_LIVE_KEY" \
-H "User-Agent: my-integration/1.0"
Returns the identity the key belongs to:
{
"msg": "User retrieved successfully",
"data": {
"email": "[email protected]",
"firstName": "Ada",
"lastName": "Okafor",
"telephone": "08012345678",
"privilege": "agent",
"isEmailVerified": true,
"status": true,
"statusText": "activated"
}
}
Use it as a startup check: if privilege is not agent or status is
false, the key cannot transact.
Notifications¶
| Method | Path | Access | Description |
|---|---|---|---|
GET |
/api/v1/notification/ |
API key | List notifications. Supports pagination and filters. |
PUT |
/api/v1/notification/ |
API key | Mark all as read |
POST |
/api/v1/notification/ |
API key | Create a notification for the user (message) |
PUT |
/api/v1/notification/remove-for-me |
API key | Remove notifications for the current user |
DELETE |
/api/v1/notification/remove-for-me |
API key | Remove notifications for the current user |
Notifications carry the outcome of your transactions, including pending purchase alerts.
Related¶
- Authentication — the full credential model
- Webhooks — how settlement notifications are delivered