Developers · REST API
One API.
We find the route.
Quote, then send. Payve picks the best rail, signs every webhook and keeps a balanced ledger. You get four statuses and a spec that matches the server.
1curl https://api…/v1/quotes \2 -H "Authorization: Bearer $KEY" \3 -d sourceCurrency=NGN \4 -d destinationCurrency=KES \5 -d amount=5000000 \6 -d transactionType=payout78{ "id": "qte_8xk2…",9 "rate": "0.0836",10 "destinationAmount": "418000",11 "feeAmount": "5000",12 "expiresAt": "…T14:36:12Z" }
1curl https://api…/v1/payouts \2 -H "Authorization: Bearer $KEY" \3 -H "Idempotency-Key: pay-0142" \4 -d quoteId=qte_8xk2… \5 -d method=mobile_money \6 -d country=KE \7 -d "beneficiary[mobileNumber]=…" \8 -d "beneficiary[holderName]=Amina" \9 -d merchantReference=PAY-01421011{ "id": "pyt_2m9q…",12 "status": "pending" }
Host and values illustrative. Amounts in minor units.
The whole API on one screen
Six resources. One header for auth, one for idempotency. Nothing you have to install.
- QuotesPOST /v1/quotes — rate, margin, fee and the amount the recipient gets, held for five minutes by default.
- PayoutsPOST /v1/payouts and /v1/payouts/bulk — bank or mobile money in five currencies. GET …/banks, …/operators and the two name-check validators.
- CollectionsPOST /v1/payins — bank transfer, virtual account or card in NGN, GHS and KES; mobile money rolling out. Or create a payment link and share a URL.
- ConversionsPOST /v1/conversions with a quoteId — a quote converts once; the second attempt is refused.
- WalletsPOST /v1/wallets per currency; GET /v1/wallets for available and on-hold balances backed by ledger entries.
- WebhooksSeven events, one signature scheme, redelivered with backoff. Redeliver any event from the dashboard or POST /v1/webhooks/events/{id}/retry.
Auth: x-api-key: sk_test_… (or x-api-key). Sandbox keys start with sk_test_. No SDK yet — the OpenAPI spec is the contract, and it's generated from the running server.
Webhooks
You learn a payment arrived from us, not from polling.
- payout.successful
- payout.failed
- payin.successful
- payin.failed
- payin.expired
- conversion.successful
- conversion.failed
Deliveries that don’t get a 2xx are redelivered with backoff. Every attempt is visible in the dashboard with the response you returned, and any event can be resent.
1POST https://you.example/payve/webhooks2X-Payve-Event: payout.successful3X-Payve-Timestamp: 17899941724X-Payve-Signature: t=1789994172,v1=3f9a…c256{ "event": "payout.successful",7 "data": { "id": "pyt_2m9q…", "status": "successful",8 "merchantReference": "PAYROLL-SEP-0142",9 "destinationAmount": "418000" } }
1const [t, v1] = sig.split(",").map((p) => p.slice(p.indexOf("=") + 1));2const expected = createHmac("sha256", secret)3 .update(`${t}.${rawBody}`)4 .digest("hex");5ok = timingSafeEqual(Buffer.from(v1), Buffer.from(expected))6 && Math.abs(Date.now() / 1000 - Number(t)) < 300;
Why builders trust it
Three properties you can build on. All three are enforced server-side.
Same Idempotency-Key, same result. Never a second debit.
Send the header on anything that moves money. A retry inside 24 hours returns the original response — the money-path is safe to retry by construction, not by luck.
Every webhook carries an HMAC you can verify in six lines.
X-Payve-Signature is t=<unix>,v1=<hmac-sha256 of "t.body">. Reject anything older than five minutes or with a bad digest. The secret is yours to rotate.
Four statuses. The same four everywhere.
pending · processing · successful · failed — in the API, the dashboard, the webhooks and the app. Internally the engine tracks much more; you never have to.
A sandbox you control
Same endpoints, same statuses, same webhooks. The only difference is that the money isn’t real — and the rails do what you tell them.
- Same contractsk_test_ keys hit the same paths and get the same shapes back. Move to live by swapping the key.
- Rails you controlTell the sandbox rail to answer late or decline a share of payouts, and watch the reroute and the webhooks you’ll see in production.
- Real ledgerSandbox wallets keep a balanced ledger too. Reconcile against it before you go live.
Quote. Send. Get the webhook.
Sandbox keys on signup. No SDK to install. No setup fee.