POST
https://api.nagorikpay.com/api/payment/create-request
Compatibility alias: /api/payment/create-reqeust. Send the brand API key in the API-KEY header. The API never redirects the customer to a payment page.
Access: এই endpoint admin-এর অনুমোদন সাপেক্ষে। আপনার account-এ create-request access চালু না থাকলে valid API key দিয়েও payment request তৈরি হবে না — সাথে সাথে 403 এবং create-request is not enabled for this account. Please contact support. ফেরত আসবে। চালু করতে support-এ যোগাযোগ করুন।
Sandbox: use https://sandbox-api.nagorikpay.com/ with sandbox API keys and the sandbox database. Sandbox-ও admin-এর অনুমোদন সাপেক্ষে — অনুমোদন ছাড়া brand edit page থেকে sandbox key তৈরি করা যায় না, আর আগে তৈরি করা key-ও সাথে সাথে অচল হয়ে যায়। Never send production API keys or live customer payments to the sandbox domain.
Request example
curl -X POST 'https://api.nagorikpay.com/api/payment/create-request' \
-H 'API-KEY: YOUR_BRAND_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"amount": "500",
"payment_method": "bkash",
"account_type": "personal",
"cus_name": "Customer Name",
"cus_phone": "01700000000",
"webhook_url": "https://merchant.example.com/nagorikpay-webhook",
"metadata": {"order_id": "ORDER-10025"}
}'
Success response
{
"status": "success",
"payment_id": "NP202609130001",
"payment_method": "bkash",
"account_type": "personal",
"payment_number": "017XXXXXXXX",
"amount": "500.00",
"charge": "10.00",
"total_amount": "510.00",
"pay_amount": "510.00",
"breakdown": {
"amount": "500.00",
"charge": "10.00",
"total_payable": "510.00"
},
"currency": "BDT",
"expires_at": "2026-09-13 13:00:00"
}
Customer-কে payment_number, pay_amount (= total_amount, অর্থাৎ amount + charge) এবং payment_id দেখাবেন। শুধু amount দেখালে customer কম টাকা পাঠাবে এবং payment কখনো verify হবে না — যে টাকা gateway-র নিজের checkout page-এ "Total Payable" লেখা থাকে, customer-কে ঠিক সেই টাকাই পাঠাতে হবে। Request ৩০ মিনিট পর expire হবে।
POST
https://api.nagorikpay.com/api/payment-submit-transaction
Request example
curl -X POST 'https://api.nagorikpay.com/api/payment-submit-transaction' \
-H 'API-KEY: YOUR_BRAND_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"payment_id": "NP202609130001",
"transaction_id": "ABC123XYZ"
}'
Server stored SMS/provider data-এর সঙ্গে TrxID মিলিয়ে exact amount check করবে। Duplicate TrxID reject হবে এবং client পাঠানো amount কখনো trust করা হবে না।
| Status | Meaning |
paid | Transaction matched and payment completed. |
pending | Accepted for review or provider verification is not complete yet. |
failed | Transaction ID, amount or request could not be verified. |
expired | The 30-minute payment request expired. |
Response fields can include payment_id, transaction_id, amount, pay_amount, charge, status, message and the original verification details.
Every submit response — paid, pending, failed or expired — carries amount, charge, total_amount and pay_amount together, so the create response and the submit response never disagree about the money.
amount is always the merchant-requested amount, never the payable one — show pay_amount to the customer. When an amount mismatch is detected, expected_amount (what the request needs) and received_amount (what the provider SMS says arrived) are returned as well, so the difference can be shown without any guessing.
If webhook_url was supplied, the same payment status notifications are delivered to it. Existing form fields remain unchanged for compatibility. New headers are added:
Webhook headers
Content-Type: application/x-www-form-urlencoded
X-NagorikPay-Timestamp: 1789290000
X-NagorikPay-Event: auto-completed
X-NagorikPay-Signature: sha256=HEX_SIGNATURE
The signing key is your brand's Webhook Secret if you have generated one (merchant panel → Brands → edit brand → Webhook Secret), and your brand API key if you have not. The Webhook Secret is the recommended setup: it is a separate value, so a leaked API key can no longer be used to forge webhooks.
Signing formula
timestamp + "." + raw_form_body
HMAC-SHA256(message, webhook_secret_or_api_key)
Webhook delivery attempts, response code, response body and payload are recorded in the merchant Webhook Logs page.
Backward compatibility: every webhook already carries this signature and the form fields are unchanged, so existing integrations keep working untouched — X-NagorikPay-Signature is an extra header, not a replacement. If you verify with the brand API key today, that continues to work; generating a Webhook Secret is an upgrade you can make whenever you are ready, and you update your verifier in the same step.
Read the raw request body — not a re-encoded array, and never a parsed-then-rebuilt string, since the signature covers the exact bytes that were sent. Reject requests with a timestamp older than five minutes, then compare the signature with a constant-time comparison.
PHP verification example
$timestamp = $_SERVER['HTTP_X_NAGORIKPAY_TIMESTAMP'] ?? '';
$given = $_SERVER['HTTP_X_NAGORIKPAY_SIGNATURE'] ?? '';
$rawBody = file_get_contents('php://input');
$expected = 'sha256=' . hash_hmac(
'sha256',
$timestamp . '.' . $rawBody,
'YOUR_WEBHOOK_SECRET_OR_API_KEY'
);
// A signature is always sent — a missing one means the request is not ours.
if ($given === '' || abs(time() - (int) $timestamp) > 300 || !hash_equals($expected, $given)) {
http_response_code(401);
exit('Invalid signature');
}
parse_str($rawBody, $payload);
// Process payment only after the signature check.
Replay protection: store the payment ID/event combination after processing and ignore the same completed event twice.