Payments
The Payments API lets you initiate, query, and refund payments across all supported providers. POPFAB handles routing, failover, and status normalization automatically.
Endpoints
POST
/v1/paymentsGET
/v1/paymentsGET
/v1/payments/:idPOST
/v1/payments/:id/refundInitiate a Payment
POST
/v1/paymentsCreates a new payment and routes it to the best available provider.
Request headers
| Parameter | Type | Required | Description |
|---|---|---|---|
Authorization | string | Required | Bearer YOUR_API_KEY |
Idempotency-Key | string | Required | A unique key per payment attempt (UUID or your order ID). Prevents duplicate charges if the request is retried. |
Content-Type | string | Required | Must be application/json |
Request body
| Parameter | Type | Required | Description |
|---|---|---|---|
amount | integer | Required | Amount in the smallest currency unit (kobo for NGN, pesewas for GHS, etc.). Must be a positive integer. |
currency | string | Required | ISO 4217 currency code: NGN, GHS, KES, ZAR, UGX, XOF, USD. |
payment_method | string | Required | One of: card, bank_transfer, ussd, mobile_money, qr. |
reference | string | Required | Your unique payment reference. Alphanumeric, hyphens, and underscores only (a–z, A–Z, 0–9, -, _). Max 255 characters. Must be unique per merchant. |
customer | object | Required | Customer object. Must include email. Optionally includes name and phone. |
customer.email | string | Required | Customer's email address. |
customer.name | string | Optional | Customer's full name. |
customer.phone | string | Optional | Customer's phone number. |
routing_override | string | Optional | Force a specific provider, bypassing routing rules: paystack, flutterwave, monnify, squad, interswitch, payaza. |
callback_url | string | Optional | URL to redirect the customer to after payment (for redirect-based flows). Must be a valid HTTPS URL. |
metadata | object | Optional | Up to 20 key-value pairs of string:string. Stored on the payment and returned in webhook events. |
Example requestbash
curl -X POST https://api.popfab.io/v1/payments \
-H "Authorization: Bearer sk_test_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order_abc123_v1" \
-d '{
"amount": 150000,
"currency": "NGN",
"payment_method": "card",
"reference": "MYAPP-ORDER-7890",
"customer": {
"email": "ada@example.com",
"name": "Ada Okafor",
"phone": "+2348012345678"
},
"metadata": {
"order_id": "7890",
"plan": "premium"
}
}'200 OK — Payment objectjson
{
"id": "ppfb_pay_01HX9T2KBQM4Z3YWN5E6R7VP8S",
"reference": "MYAPP-ORDER-7890",
"amount": 150000,
"currency": "NGN",
"payment_method": "card",
"status": "processing",
"provider": "paystack",
"provider_reference": "psk_T8x29kLMqpn",
"customer": {
"email": "ada@example.com",
"name": "Ada Okafor",
"phone": "+2348012345678"
},
"metadata": { "order_id": "7890", "plan": "premium" },
"fees": {
"popfab_fee": 225,
"provider_fee": 375,
"total_fee": 600
},
"routing_context": {
"strategy": "cost_optimizer",
"providers_tried": ["paystack"],
"selected_reason": "lowest_cost"
},
"created_at": "2025-03-19T10:23:45.000Z",
"updated_at": "2025-03-19T10:23:45.000Z"
}List Payments
GET
/v1/paymentsReturns a cursor-paginated list of payments for your merchant account, newest first.
Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
status | string | Optional | Filter by status: pending, processing, success, failed, reversed, pending_confirmation. |
limit | integer | Optional | Number of results per page. Default 20, max 100. |
cursor | string | Optional | Pagination cursor from a previous response next_cursor field. |
List successful paymentsbash
curl "https://api.popfab.io/v1/payments?status=success&limit=50" \
-H "Authorization: Bearer sk_test_YOUR_API_KEY"Responsejson
{
"data": [
{ "id": "ppfb_pay_...", "status": "success", ... },
{ "id": "ppfb_pay_...", "status": "success", ... }
],
"next_cursor": "eyJpZCI6InBwZmJfcGF5XyJ9",
"has_more": true
}Get a Payment
GET
/v1/payments/:idRetrieves the current state of a single payment by its POPFAB ID.
Get payment by IDbash
curl https://api.popfab.io/v1/payments/ppfb_pay_01HX9T2KBQM4Z3YWN5E6R7VP8S \
-H "Authorization: Bearer sk_test_YOUR_API_KEY"Refund a Payment
POST
/v1/payments/:id/refundInitiates a full or partial refund for a payment with status success.
| Parameter | Type | Required | Description |
|---|---|---|---|
amount | integer | Optional | Amount to refund in the smallest currency unit. Omit for a full refund. |
reason | string | Optional | Reason for the refund. Max 500 characters. Stored for audit purposes. |
Partial refund of ₦500 (50000 kobo)bash
curl -X POST https://api.popfab.io/v1/payments/ppfb_pay_01HX9T2K/refund \
-H "Authorization: Bearer sk_test_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"amount": 50000,
"reason": "Customer request — partial return"
}'Payment Statuses
| Status | Description |
|---|---|
| pending | Request received. Awaiting routing and provider processing. |
| processing | Routed to a provider. Awaiting confirmation from the provider. |
| success | Payment confirmed by the provider. Value delivered. |
| failed | Payment was declined or could not be completed by any provider. |
| reversed | A refund or reversal has been successfully processed. |
| pending_confirmation | Provider has accepted the request but final settlement is pending (common for bank transfers). |
Idempotency
The Idempotency-Key header is required on all POST /v1/payments requests. It ensures that retrying a failed network request does not result in a duplicate charge.
ℹ
If you send a second request with the same
Idempotency-Key, POPFAB returns the original payment object without creating a new one. Keys expire after 24 hours. If you receive a 409 IDEMPOTENCY_CONFLICT, the key was used with a different request body — generate a new key.