bKash Payment API Documentation
Integrate bdQuickPay into your application to accept bKash payments instantly. Our REST API is simple, secure, and developer-friendly.
All API requests must be made over HTTPS. Requests over plain HTTP will be rejected.
Authentication
All requests must include your bKash merchant credentials as request headers. You can find these in your merchant dashboard under API Credentials.
X-App-Key: your_app_key_here X-Secret-Key: your_secret_key_here
Never expose your App Key or Secret Key in client-side code or public repositories. Always make API calls server-side.
Base URL
All API endpoints are relative to the following base URL:
https://bdquickpay.com/api/bkash/v1
Create Payment
Creates a new bKash payment session and returns a unique payment URL. Redirect your customer to this URL to complete payment.
Creates a new bKash payment and returns a redirect URL for the customer.
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| amount | number | Required | Payment amount in BDT (e.g. 500) |
| customer_reference | string | Required | Your customer's unique identifier or order ID |
| success_url | string | Required | URL to redirect after successful payment. Payment details appended as query params automatically. |
| cancel_url | string | Required | URL to redirect if payment is cancelled or fails |
| webhook_url | string | Optional | URL to receive bKash payment event notifications via POST |
| metadata | object | Optional | Custom key-value data to attach to the payment (e.g. order ID, product name) |
Code Examples
curl --location 'https://bdquickpay.com/api/bkash/v1/payment/create' \ --header 'X-App-Key: your_app_key_here' \ --header 'X-Secret-Key: your_secret_key_here' \ --header 'Content-Type: application/json' \ --data '{ "amount": 500, "customer_reference": "ORDER-001", "success_url": "https://yoursite.com/success", "cancel_url": "https://yoursite.com/cancel", "webhook_url": "https://yoursite.com/webhook", "metadata": { "order_id": "ORD-1001", "product": "Premium Package" } }'
<?php $appKey = 'your_app_key_here'; $secretKey = 'your_secret_key_here'; $url = 'https://bdquickpay.com/api/bkash/v1/payment/create'; $payload = [ 'amount' => 500, 'customer_reference' => 'ORDER-001', 'success_url' => 'https://yoursite.com/success', 'cancel_url' => 'https://yoursite.com/cancel', 'webhook_url' => 'https://yoursite.com/webhook', 'metadata' => ['order_id' => 'ORD-1001'], ]; $ch = curl_init($url); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => json_encode($payload), CURLOPT_HTTPHEADER => [ 'X-App-Key: ' . $appKey, 'X-Secret-Key: ' . $secretKey, 'Content-Type: application/json', ], ]); $data = json_decode(curl_exec($ch), true); curl_close($ch); if ($data['status']) { header('Location: ' . $data['payment_url']); exit; }
const response = await fetch('https://bdquickpay.com/api/bkash/v1/payment/create', { method: 'POST', headers: { 'X-App-Key': 'your_app_key_here', 'X-Secret-Key': 'your_secret_key_here', 'Content-Type': 'application/json', }, body: JSON.stringify({ amount: 500, customer_reference: 'ORDER-001', success_url: 'https://yoursite.com/success', cancel_url: 'https://yoursite.com/cancel', webhook_url: 'https://yoursite.com/webhook', }), }); const data = await response.json(); if (data.status) { window.location.href = data.payment_url; }
import requests url = "https://bdquickpay.com/api/bkash/v1/payment/create" app_key = "your_app_key_here" secret_key = "your_secret_key_here" payload = { "amount": 500, "customer_reference": "ORDER-001", "success_url": "https://yoursite.com/success", "cancel_url": "https://yoursite.com/cancel", "webhook_url": "https://yoursite.com/webhook", } headers = { "X-App-Key": app_key, "X-Secret-Key": secret_key, "Content-Type": "application/json", } data = requests.post(url, json=payload, headers=headers).json() if data["status"]: print("Redirect to:", data["payment_url"])
Responses
{
"status": true,
"invoice_id": "GALQYVTGASTRGOISR1FO",
"amount": 500,
"customer_reference": "ORDER-001",
"payment_url": "https://bdquickpay.com/pay/bkash/TOKEN",
"expires_at": "2026-03-21T10:30:00+00:00"
}
{
"status": false,
"message": "Unauthorized. Invalid App Key or Secret Key."
}
{
"status": false,
"message": "Validation error",
"errors": {
"amount": ["The amount field is required."],
"success_url": ["The success url must be a valid URL."]
}
}
Verify Payment
Use this endpoint to check the current status of a bKash payment using its invoice_id. Always verify server-side after the customer returns to your success_url.
Never trust the success_url redirect alone — always verify payment status server-side using this endpoint.
Verify a bKash payment by invoice ID. Returns full payment and transaction details.
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| invoice_id | string | Required | The invoice ID returned when the payment was created |
Code Examples
curl --location 'https://bdquickpay.com/api/bkash/v1/payment/verify' \ --header 'X-App-Key: your_app_key_here' \ --header 'X-Secret-Key: your_secret_key_here' \ --header 'Content-Type: application/json' \ --data '{"invoice_id": "GALQYVTGASTRGOISR1FO"}'
<?php $appKey = 'your_app_key_here'; $secretKey = 'your_secret_key_here'; $url = 'https://bdquickpay.com/api/bkash/v1/payment/verify'; $invoiceId = 'GALQYVTGASTRGOISR1FO'; $ch = curl_init($url); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => json_encode(['invoice_id' => $invoiceId]), CURLOPT_HTTPHEADER => [ 'X-App-Key: ' . $appKey, 'X-Secret-Key: ' . $secretKey, 'Content-Type: application/json', ], ]); $data = json_decode(curl_exec($ch), true); curl_close($ch); if ($data['status'] && $data['data']['status'] === 'completed') { $trxId = $data['data']['transaction']['trx_id']; // fulfilOrder($invoiceId, $trxId); }
use Illuminate\Support\Facades\Http; $response = Http::withHeaders([ 'X-App-Key': config('services.bkash.app_key'), 'X-Secret-Key': config('services.bkash.secret_key'), ])->post('https://bdquickpay.com/api/bkash/v1/payment/verify', [ 'invoice_id' => $invoiceId, ]); $data = $response->json(); if ($data['status'] && $data['data']['status'] === 'completed') { $trxId = $data['data']['transaction']['trx_id']; $verifiedAt = $data['data']['transaction']['verified_at']; // fulfilOrder($invoiceId, $trxId); }
const response = await fetch('https://bdquickpay.com/api/bkash/v1/payment/verify', { method: 'POST', headers: { 'X-App-Key': 'your_app_key_here', 'X-Secret-Key': 'your_secret_key_here', 'Content-Type': 'application/json', }, body: JSON.stringify({ invoice_id: 'GALQYVTGASTRGOISR1FO' }), }); const data = await response.json(); if (data.status && data.data.status === 'completed') { const { trx_id, verified_at } = data.data.transaction; console.log(`Verified — Trx: ${trx_id}`); }
Responses
{
"status": true,
"message": "Payment retrieved successfully.",
"data": {
"invoice_id": "GALQYVTGASTRGOISR1FO",
"customer_reference": "ORDER-001",
"amount": 500,
"status": "completed",
"created_at": "2026-03-21T10:00:00+00:00",
"expires_at": "2026-03-21T10:30:00+00:00",
"transaction": {
"trx_id": "8HJ2XKPQ91",
"payment_method": "bkash",
"amount": 500,
"status": "completed",
"verified_at": "2026-03-21T10:22:14+00:00"
}
}
}
{
"status": true,
"message": "Payment retrieved successfully.",
"data": {
"invoice_id": "GALQYVTGASTRGOISR1FO",
"amount": 500,
"status": "pending",
"transaction": null
}
}
{
"status": false,
"message": "Unauthorized. Invalid App Key or Secret Key."
}
Webhooks
If you provide a webhook_url, bdQuickPay will send a POST request to that URL when a payment event occurs. Your server must respond with HTTP 2xx within 10 seconds, otherwise delivery is marked failed and retried automatically.
Verify the X-App-Key header in your webhook handler to confirm the request genuinely came from bdQuickPay.
Webhook Payload
webhook_url
{
"event": "payment.completed",
"invoice_id": "GALQYVTGASTRGOISR1FO",
"payment_id": 42,
"customer_reference": "ORDER-001",
"amount": 500,
"payment_method": "bkash",
"status": "completed",
"timestamp": "2026-03-21T10:22:14+00:00"
}
| Field | Type | Description |
|---|---|---|
| event | string | payment.completed or payment.failed |
| invoice_id | string | Unique invoice ID of the payment |
| payment_id | integer | Internal numeric ID of the payment record |
| customer_reference | string | Your customer reference submitted at creation |
| amount | number | Payment amount in BDT |
| payment_method | string | Always bkash |
| status | string | completed or failed |
| timestamp | string | ISO 8601 timestamp when the event fired |
Webhook Events
| Event | Trigger |
|---|---|
| payment.completed | Fired when bKash payment is verified and marked completed |
| payment.failed | Fired when payment fails due to timeout or amount mismatch |
The X-App-Key header is sent with every webhook request using your bKash merchant App Key. Always validate it on your server before processing.
Example Webhook Handler
<?php $payload = json_decode(file_get_contents('php://input'), true); $event = $payload['event'] ?? ''; $invoiceId = $payload['invoice_id'] ?? ''; $amount = $payload['amount'] ?? 0; $custRef = $payload['customer_reference'] ?? ''; $method = $payload['payment_method'] ?? ''; // always "bkash" if ($event === 'payment.completed') { // markOrderPaid($invoiceId, $amount); } elseif ($event === 'payment.failed') { // markOrderFailed($invoiceId); } http_response_code(200); echo json_encode(['received' => true]);
// routes/api.php Route::post('/webhook/bkash', [BkashWebhookController::class, 'handle']) ->withoutMiddleware(VerifyCsrfToken::class); // app/Http/Controllers/BkashWebhookController.php public function handle(Request $request) { $event = $request->input('event'); $invoiceId = $request->input('invoice_id'); $amount = $request->input('amount'); $custRef = $request->input('customer_reference'); match($event) { 'payment.completed' => Order::markPaid($invoiceId, $amount), 'payment.failed' => Order::markFailed($invoiceId), default => Log::info('Unknown bKash webhook: ' . $event), }; return response()->json(['received' => true]); }
const express = require('express'); const app = express(); app.use(express.json()); app.post('/webhook/bkash', (req, res) => { const { event, invoice_id, amount, customer_reference } = req.body; if (event === 'payment.completed') { console.log(`bKash payment done: ${invoice_id} — ৳${amount}`); // await markOrderPaid(invoice_id, amount); } else if (event === 'payment.failed') { console.log(`bKash payment failed: ${invoice_id}`); // await markOrderFailed(invoice_id); } res.status(200).json({ received: true }); });
Retry Policy
If your server does not respond with 2xx within 10 seconds, the webhook is marked failed and retried after 5 minutes. Failed webhooks can also be manually retried from the admin panel under bKash Webhook Logs.
Payment Statuses
A bKash payment can be in one of the following states:
Error Codes
The API uses standard HTTP status codes. All error responses return a JSON body.
| HTTP Code | Meaning | Description |
|---|---|---|
| 200 | OK | Request successful |
| 401 | Unauthorized | Missing or invalid X-App-Key or X-Secret-Key |
| 422 | Unprocessable Entity | Validation failed — check errors in response body |
| 403 | Forbidden | bKash merchant account is inactive |
| 404 | Not Found | Invoice not found for this merchant |
| 500 | Server Error | Unexpected server error — contact support |
Need help? Contact support with your invoice_id for faster resolution.