BDT only. Create a key in Admin → API keys. Send the customer to pay_url.
Required on every /v1/invoices call.
Authorization: Bearer YOUR_API_KEY
Create a pending invoice. Wallets rotate on their own. Pass merchant_id only if you need one wallet.
POST https://bkash-pay.espaybd.com/v1/invoices
{
"method": "bkash",
"amount": "100",
"note": "order-2041",
"callback_url": "https://yoursite.com/pay/return",
"ttl_minutes": 10
}
| Field | Required | |
|---|---|---|
method | Yes | bkash or banglaqr |
amount | Yes | Whole BDT, minimum 1 |
note | No | Shown on Bangla QR, max 25 chars |
callback_url | No | We POST JSON there on paid/expired, and send the customer back after 5s |
ttl_minutes | No | Defaults to the admin payment window |
merchant_id | No | Pin a wallet. Leave out to rotate |
If that wallet already has a pending invoice for the same amount, due_amount is +1 (100 → 101 → 102). Ask the customer to pay due_amount.
{
"id": "INV…",
"method": "bkash",
"requested_amount": "100",
"due_amount": "100",
"currency": "BDT",
"status": "pending",
"wallet": "01XXXXXXXXX",
"pay_url": "https://bkash-pay.espaybd.com/pay/INV…",
"qr_url": "https://bkash-pay.espaybd.com/pay/INV…/qr.png",
"expires_at": "…"
}
Read status. pending, paid, or expired. Credit only when paid. A TrxID cannot be used twice.
GET https://bkash-pay.espaybd.com/v1/invoices/INV…
Looks up the TrxID on the assigned wallet. Marks paid if it is Completed and the amount matches.
POST https://bkash-pay.espaybd.com/v1/invoices/INV…/verify
{ "trx_id": "DI617DIPCV" }
bKash can POST completed payments to a secret URL. That URL is only in Admin → Settings. Do not put it in your app or on the pay page.
bKash Search needs a TrxID. There is no official list of recent payments. Until IPN is on, poll GET or have the customer submit TrxID.
Set callback_url when you create the invoice. We POST this JSON when the invoice is paid, cancelled, or expired:
{
"event": "invoice.paid",
"id": "INV…",
"status": "paid",
"method": "bkash",
"due_amount": "13",
"trx_id": "DI66880Y8I"
}
The pay page then sends the customer to that URL after 5 seconds, with status, invoice_id, amount and trx_id in the query string. Respond 200 to the POST. A failed webhook does not undo the payment.