Recent Wallet Activity
Money moving in and out of your float. For what you sold, see Sales History.| Date | Type | Details | Amount | Profit | Notes |
|---|
Sell Airtime
Float will be deducted at your discounted rate.Bulk Airtime
Paste onephone, amount per line. We validate everything and show you the cost before charging anything.
Recent Bulk Jobs
| When | Type | Rows | Progress | Amount | Status |
|---|
Bulk Allocate to Merchants
Move float to several merchants at once. Deducted from your wallet immediately.| Merchant | Phone | Current float | Allocate (KES) |
|---|
Sales History
Every airtime sale. Amount is the airtime the customer received.| Date ↓ | Customer | Amount | Profit | Status | Receipt | Error |
|---|
Top Up Float
Pay via M-Pesa STK push — your float is credited automatically on payment confirmation.Already Paid to Our Till?
Paste the M-Pesa message and your float is credited at your rate.Wallet History
Your float ledger: top-ups in, sales and transfers out. Your discount is applied when you buy float, so a sale costs face value here.| Date | Type | Details | Amount | Profit | Notes |
|---|
My Merchants
Sub-accounts that resell on your behalf. They use your float allocation.| Name | Phone | Discount | Float | Sales | Volume | Last login | Last sale | Status | Actions |
|---|
Tip: click any row to see full details for that merchant.
Merchant Detail
Credentials
—
Webhook
API reference
Base URL https://api.primepayke.com/api/reseller/v1
Authentication
Every request carries three headers.
X-API-Key your API key
X-Timestamp unix milliseconds
X-Signature HMAC-SHA256(secret, timestamp + METHOD + path + body)
- Concatenate the four parts with no separator.
pathbegins at/api/reseller/v1and includes the query string.bodyis the exact JSON sent, or empty for GET.- Timestamps must be within 5 minutes of server time.
- Each signature is accepted once. Re-sign every retry.
- Limit: 120 requests per minute.
Endpoints
/me
Account and float balance.
/sales?days=7
Recent sales. days 1–90.
/airtime/sell
Dispatch airtime.
// request
{ "phone": "0712345678", "amount": 100, "idempotencyKey": "order-1001" }
// response
{ "success": true,
"data": { "movementId": 52, "amount": 100, "cost": 95,
"receiptNo": "R260803.0912.A12345", "newBalance": 905 } }
amount is what the customer receives; cost is what
leaves your float after your discount. Reusing an
idempotencyKey within 5 minutes returns the original result
instead of dispatching again — use it on every retry.
Errors
Failures return { "success": false, "message": "…" } with a
code where applicable.
400 | Invalid input. INVALID_PHONE, AMOUNT_OUT_OF_RANGE (5–10,000), or insufficient float. No float is deducted. |
401 | Bad signature, unknown key, or stale timestamp. |
403 | Airtime not enabled on this account. |
409 | Signature already used. Re-sign with a fresh timestamp. |
429 | Rate limited. |
502 | Dispatch failed upstream. Float is refunded automatically. |
Webhooks
Sent on each completed sale. Verify the signature before trusting the
payload, and respond 200 promptly. Deliveries are not retried —
reconcile against GET /sales.
X-PrimePay-Event airtime.completed
X-PrimePay-Timestamp unix ms
X-PrimePay-Signature HMAC-SHA256(secret, timestamp + rawBody)
{ "event": "airtime.completed",
"data": { "movementId": 52, "phone": "254712345678", "amount": 100,
"cost": 95, "receiptNo": "R260803.0912.A12345", "balance": 905 },
"timestamp": 1785749000000 }
Example
const crypto = require('crypto');
const BASE = 'https://api.primepayke.com';
const PREFIX = '/api/reseller/v1';
async function callApi(method, path, body = null) {
const raw = body ? JSON.stringify(body) : '';
const ts = Date.now();
const sig = crypto.createHmac('sha256', process.env.PRIMEPAY_SECRET)
.update(ts + method.toUpperCase() + PREFIX + path + raw)
.digest('hex');
const res = await fetch(BASE + PREFIX + path, {
method,
headers: {
'Content-Type': 'application/json',
'X-API-Key': process.env.PRIMEPAY_KEY,
'X-Timestamp': String(ts),
'X-Signature': sig,
},
body: raw || undefined,
});
return res.json();
}
Keep the secret server-side, in an environment variable. If it is exposed, generate a new pair above — the previous one stops working immediately.