Integration Guide
Everything needed to take payments on your own site, in one page. Pick your platform below, copy the code, paste in your API key, and you are live. The same three things are used by every language: your API key, the endpoint /api/public/v1/payments, and thecheckout_url you redirect the buyer to. No SDK or library is required anywhere.
What you need before you start
- A NaafiPay account with at least one store (brand).
- An API key — create it in the dashboard under Integration.
- A webhook URL on your site, plus its signing secret (also on the Integration page).
- A server that can make outbound HTTPS requests. Shared cPanel hosting is fine.
The flow in five steps
- Create an API key. Generate a key below. Copy it once and store it on your server (environment variable), never in browser code.
- Send a test payment request. Pick your language, paste the snippet, run it. The response contains a checkout_url — open it and you will see your branded checkout.
- Redirect the buyer to checkout_url. Your customer picks bKash, Nagad, Rocket, card or bank there. NaafiPay handles verification automatically.
- Add a webhook so your site knows when money arrives. Register your endpoint URL, copy the signing secret, and verify every payload with HMAC-SHA256 before trusting it.
- Go live. Complete verification, switch your key from test to live, and start collecting real payments.
Authentication
Every request carries your key in the Authorization header. Live keys start with pg_live_ and test keys with pg_test_. Keys are SHA-256 hashed at rest, scoped to a single store, and can be restricted to specific server IPs.
1Authorization: Bearer pg_live_xxxxxxxxxxxxxxxx2Content-Type: application/jsoncheckout_url to the browser.Ready-made plugins (no code)
- WordPress / WooCommerce plugin (naafipay-wordpress.zip) — upload under Plugins → Add New → Upload, activate, paste your API key and webhook secret. Adds a checkout gateway, refunds from the order screen, optional product sync and shortcodes.
- Shopify app package (naafipay-shopify.zip) — follow the included README to install on your store.
Endpoints you will use
GET /api/public/v1/me— verify your API key and see which store it belongs to.POST /api/public/v1/payments— create a payment, returnscheckout_url.GET /api/public/v1/payments/{id}— fetch one payment by id or reference.POST /api/public/v1/payments/{id}/refund— request a refund (full or partial).POST /api/public/v1/verify-payment— confirm a payment server-side.GET /api/public/v1/payments— list payments with paging.POST /api/public/v1/payment-links— create a reusable payment link.POST /api/public/v1/products,PATCH /api/public/v1/products/{id}— catalog sync.POST /api/public/v1/subscriptions,POST /api/public/v1/subscriptions/{id}/cancel— recurring billing.GET /api/public/v1/openapi— OpenAPI spec for Postman and code generators.
Pick your platform
cURL / Terminal
The fastest way to confirm your key works. Run this in any terminal — if you get a checkout_url back, your integration is live.
1. Create a payment
1curl -X POST https://naafipay.com/api/public/v1/payments \2 -H "Authorization: Bearer pg_live_xxxxxxxxxxxxxxxx" \3 -H "Content-Type: application/json" \4 -d '{5 "amount": 1500,6 "currency": "BDT",7 "customer_name": "Tasin Fahim",8 "customer_email": "tasin@example.com",9 "customer_phone": "01700000000",10 "reference_id": "ORD-1001",11 "metadata": { "order_id": "1001" }12 }'2. Verify a payment
1curl -X POST https://naafipay.com/api/public/v1/verify-payment \2 -H "Authorization: Bearer pg_live_xxxxxxxxxxxxxxxx" \3 -H "Content-Type: application/json" \4 -d '{ "invoice_id": "udp_01HZX..." }'3. List payments
1curl "https://naafipay.com/api/public/v1/payments?limit=20" \2 -H "Authorization: Bearer pg_live_xxxxxxxxxxxxxxxx"Webhooks
A webhook is a small POST request NaafiPay sends to your site the moment something happens, so you never have to poll. Add your endpoint URL on the Integration page, copy the signing secret, and verify every request before trusting it.
1x-paygate-signature: sha256=<hex HMAC-SHA256 of the raw body>2x-paygate-signature-v2: t=<unix-seconds>,v1=<hex HMAC-SHA256 of "timestamp.body">3content-type: application/json1{2 "event": "payment.completed",3 "created_at": "2026-01-14T09:20:11.000Z",4 "data": {5 "id": "pay_01HZX...",6 "amount": 1500,7 "currency": "BDT",8 "status": "completed",9 "reference_id": "ORD-1001",10 "payment_method": "bkash",11 "transaction_id": "9F3K21AB",12 "customer_name": "Tasin Fahim",13 "customer_email": "tasin@example.com"14 }15}Events you can subscribe to:
payment.completed— Money received and verified — fulfil the order.payment.failed— The attempt failed. Ask the customer to retry.payment.cancelled— The customer abandoned the checkout.payment.refunded— A refund was issued for this payment.invoice.paid— An invoice you sent has been paid.payment_link.created— A new payment link was created in your account.
Going live checklist
- Identity verification complete in the dashboard.
- At least one payment gateway active under Gateways.
- Live API key stored as a server environment variable, test key removed.
- Webhook endpoint reachable over HTTPS and verifying the signature.
- One real end-to-end payment made and refunded.
Troubleshooting
- 401 unauthorized — the header must be
Authorization: Bearer pg_…, and the key must not be revoked or IP-restricted away from your server. - No checkout_url — the store has no active gateway, or the amount is below the gateway minimum.
- Webhook never arrives — the URL must be public HTTPS; check the delivery log under Webhooks in the dashboard.
- Signature mismatch — hash the raw request body, not a re-serialised JSON object, and keep the
sha256=prefix in the comparison.