Developers
A payments API with no surprises.
REST and JSON, one secret key per mode, integer amounts, one response envelope, idempotency on every write and webhooks you can verify in a few lines.
curl -X POST https://api.pletopay.com/api/v1/payments \
-H "Authorization: Bearer $PLETOPAY_SECRET_KEY" \
-H "Idempotency-Key: create-payment-ORDER-12345" \
-H "Content-Type: application/json" \
-d '{
"amount": 5000000,
"currency": "NGN",
"reference": "ORDER-12345",
"customer": { "email": "customer@example.com" }
}'Conventions
Learn these once; every endpoint follows them.
- Base URL
https://api.pletopay.com/api/v1One host for test and live; the key you send selects the mode.- Authentication
Authorization: Bearer sk_test_… | sk_live_…One secret key per business per mode. Keep it on your server.- Amounts
Integers in kobo₦50,000.00 is 5000000. No floats.- Responses
{ status, message, data[, meta] }Errors are { status: false, message, error: { type, code, param? }, request_id }.- Idempotency
Idempotency-Key: <your key>Replays return the original response for 24 hours. Required on transfers and refunds.- Identifiers
pay_… va_… cus_… re_… stl_… evt_…Prefixed, sortable ids; your own reference travels alongside.- Versioning
PletoPay-Version: 2026-09-25Dated versions, echoed on every response. Upgrade when you choose.- Rate limits
RateLimit-Limit / -Remaining / -ResetStandard headers on every response and Retry-After on 429.
The integration, end to end
From your first request to a confirmed payment, entirely in test mode.
Create a payment
POST /payments with the amount, your reference and the customer. You get a pending payment with the account to show.
Show the account number
Render the bank_transfer details yourself, redirect to hosted checkout, or open it in the Pletopay popup on your own site.
Pay it in the sandbox
In test mode, POST /sandbox/simulate-transfer. The notification runs through the same pipeline as live money.
Act on the event
Your endpoint gets payment.succeeded with a signature. Verify it, then fulfil the reference once.
{
"status": true,
"message": "Payment created",
"data": {
"id": "pay_01J8Z5X7Q9K2M4N6P8R0S2T4V6",
"object": "payment",
"status": "pending",
"amount": 5000000,
"currency": "NGN",
"reference": "ORDER-12345",
"bank_transfer": {
"account_number": "9000002140",
"account_name": "Ada Stores Ltd",
"expires_at": "2026-09-24T18:30:00.000Z"
}
}
}curl -X POST https://api.pletopay.com/api/v1/sandbox/simulate-transfer \
-H "Authorization: Bearer $PLETOPAY_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{ "account_number": "9000002140", "amount": 5000000 }'Webhooks you can trust
Every delivery is signed. Verify it, act on the reference, and make your handler idempotent.
- Signed with HMAC-SHA256 over the timestamp and the raw body; reject deliveries older than 5 minutes.
- At-least-once delivery with event ids, so handlers should be idempotent on the evt_ id.
- Failed deliveries retry with backoff for up to six hours; an endpoint that keeps failing is paused.
- Replay any event from the dashboard, and send a test event to a new endpoint before you rely on it.
POST /webhooks/pletopay HTTP/1.1
Content-Type: application/json
X-PletoPay-Signature: t=1727200000,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd
X-PletoPay-Timestamp: 1727200000
X-PletoPay-Event-ID: evt_01J8Z5X7Q9K2M4N6P8R0S2T4WB
X-PletoPay-Event-Type: payment.succeededimport crypto from 'node:crypto';
export function verifyPletopaySignature(secret, header, rawBody, toleranceSeconds = 300) {
const parts = Object.fromEntries(header.split(',').map((kv) => kv.split('=', 2)));
const t = Number(parts.t);
if (!t || !parts.v1 || Math.abs(Date.now() / 1000 - t) > toleranceSeconds) return false;
const expected = crypto.createHmac('sha256', secret).update(`${t}.${rawBody}`).digest();
const given = Buffer.from(parts.v1, 'hex');
return given.length === expected.length && crypto.timingSafeEqual(given, expected);
}Go deeper in the documentation
Guides, the generated API reference, every webhook event and every error code, with a Try-It panel for your test key.
The API is plain REST and JSON; the samples cover cURL, Node.js and Python, and the browser popup ships as a small script. There are no server-side libraries yet.
Get a test key and make your first request.
Sign-up takes a minute and gives you a test key straight away.