SmartBanking Public API v1
Base URL: https://bd-prm.q-bdpay.com/public/api/v1
All requests and responses use JSON. Use HTTPS in production.
callback_url.
<?php
// webhook.php
$raw = file_get_contents('php://input');
$data = json_decode($raw, true) ?: [];
// Optional: verify signature header if you enable it
// $sig = $_SERVER['HTTP_X_SIGNATURE'] ?? '';
// Basic validation
if (($data['event'] ?? '') !== 'transaction.updated') {
http_response_code(400);
echo 'invalid event';
exit;
}
// TODO: persist transaction update to your DB
// file_put_contents('webhook.log', $raw."\n", FILE_APPEND);
http_response_code(200);
echo 'ok';
?>
// npm i express body-parser
const express = require('express');
const app = express();
app.use(express.json());
app.post('/webhook', (req, res) => {
const evt = req.body?.event;
if (evt !== 'transaction.updated') return res.status(400).send('invalid event');
// TODO: validate signature header and persist to DB
// console.log('webhook:', req.body);
res.send('ok');
});
app.listen(3000, () => console.log('Webhook listening on :3000'));
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.post('/webhook')
def webhook():
data = request.get_json(silent=True) or {}
if data.get('event') != 'transaction.updated':
return ('invalid event', 400)
# TODO: verify signature and persist
return jsonify({'ok': True})
if __name__ == '__main__':
app.run(port=3000)
- API Key: Each client has an API key stored in the
users.api_keycolumn. - Header: Send
X-API-Key: <your_api_key>with every request. - Rate Limits: Default 60 requests/minute (configurable via
system_configs.key=api_rate_limitJSON). - Billing: Monetary operations (
send_money,cash_in,cash_out) deduct the full requested amount from your API balance at creation time. Non-monetary operations (e.g.,check_balance) deduct the configured per-request cost fromsystem_configs.key=api_request_cost.
curl -X GET \
-H "Content-Type: application/json" \
-H "X-API-Key: <your_api_key>" \
"https://bd-prm.q-bdpay.com/public/api/v1/health"
1) Create Transaction
POST https://bd-prm.q-bdpay.com/public/api/v1/transactions
Creates a new transaction. request_type and transaction_id are required. Optionally, provide success_keyword for SMS parsing. The system will later populate smstranx when an operator SMS/reference ID is detected.
curl -X POST \
-H "Content-Type: application/json" \
-H "X-API-Key: <your_api_key>" \
-d '{
"operator": "bkash",
"request_type": "send_money",
"amount": 1200.50,
"recipient": "01710000000",
"reference": "optional text",
"transaction_id": "client-required-id-001",
"success_keyword": "TrxID",
"callback_url": "https://your.site/webhook" // optional
}' \
"https://bd-prm.q-bdpay.com/public/api/v1/transactions"
// Request JSON
{
"operator": "bkash|nagad|rocket|upay",
"request_type": "send_money|cash_in|check_balance|cash_out",
"amount": 1200.50,
"recipient": "01710000000",
"reference": "optional text",
"transaction_id": "client-required-id-001", // REQUIRED
"success_keyword": "TrxID", // optional; helps parser match success SMS
"callback_url": "https://your.site/webhook" // optional
}
// Response 200
{
"transaction_id": "client-required-id-001",
"operator": "bkash",
"request_type": "send_money",
"recipient": "01710000000",
"status": "pending",
"amount": 1200.50,
"charge_amount": 18.00,
"api_cost": 1218.50,
"prev_balance": 5000.00,
"post_balance": 3781.50,
"created_at": "2026-07-22T12:30:00Z"
}
AMOUNT_BELOW_MIN_LIMIT, and requests exceeding the Maximum limit return error code AMOUNT_EXCEEDS_MAX_LIMIT.
2) Get Transaction Status
GET https://bd-prm.q-bdpay.com/public/api/v1/transactions/{transaction_id}
curl -X GET \
-H "X-API-Key: <your_api_key>" \
"https://bd-prm.q-bdpay.com/public/api/v1/transactions/TXN2025010112300001234"
// Response 200
{
"transaction_id": "TXN2025010112300001234",
"operator": "bkash",
"request_type": "send_money",
"amount": 1200.50,
"api_cost": 1218.50,
"prev_balance": 5000.00,
"post_balance": 3781.50,
"recipient": "01710000000",
"status": "success|failed|pending|processing|cancelled|timeout",
"error_message": null,
"smstranx": "B2C38AXYZ", // operator SMS/reference ID if captured
"created_at": "2026-07-22T12:30:00Z",
"updated_at": "2026-07-22T12:31:15Z",
"completed_at": "2026-07-22T12:31:15Z"
}
3) List Transactions
GET https://bd-prm.q-bdpay.com/public/api/v1/transactions?status=success&page=1&per_page=20
// Response 200
{
"data": [ { /* ... transaction ... */ } ],
"pagination": { "page": 1, "per_page": 20, "total": 142 }
}
4) SIM Pool Balances
GET https://bd-prm.q-bdpay.com/public/api/v1/sims/balances
// Response 200
{
"bkash": 1000.00,
"nagad": 800.00,
"rocket": 500.00,
"upay": 300.00
}
When a transaction reaches a terminal state, we POST a JSON payload to your callback_url if provided.
POST https://merchant.example.com/webhook
{
"event": "transaction.updated",
"transaction_id": "TXN2025010112300001234",
"status": "success",
"amount": 1200.50,
"api_cost": 1218.50,
"prev_balance": 5000.00,
"post_balance": 3781.50,
"operator": "bkash",
"recipient": "01710000000",
"reference": "Invoice #12345",
"smstranx": "B2C38AXYZ",
"timestamp": "2025-01-01T12:31:15Z",
"signature": "hmac-sha256=..." // optional, if signing enabled
}
We recommend validating the source IP and verifying HMAC signatures if enabled.
Standard error format:
// Response 4xx/5xx
{
"error": {
"code": "AMOUNT_EXCEEDS_LIMIT",
"message": "Amount exceeds allowed transaction limit"
}
}
- 400 Validation Error: Invalid or missing fields, or limit validation failures (e.g.,
AMOUNT_EXCEEDS_MAX_LIMIT,AMOUNT_BELOW_MIN_LIMIT,INVALID_REQUEST_TYPE). - 401 Unauthorized: Missing or invalid
X-API-Keyheader. - 429 Rate Limit Exceeded: Too many API requests per minute (exceeded requests per minute quota).
- 404 Not Found: Resource or transaction ID not found.
- 409 Conflict: Duplicate
transaction_idprovided. - 500 Server Error: Internal server exception.
# Create transaction
curl -X POST \
-H "Content-Type: application/json" \
-H "X-API-Key: <API_KEY>" \
-d '{
"operator": "bkash",
"request_type": "cash_in",
"amount": 34.00,
"recipient": "01710000000"
}' \
"https://bd-prm.q-bdpay.com/public/api/v1/transactions"
# Get transaction
curl -H "X-API-Key: <API_KEY>" "https://bd-prm.q-bdpay.com/public/api/v1/transactions/TXN2025010112300001234"
<?php
// composer require guzzlehttp/guzzle
use GuzzleHttp\Client;
$client = new Client(['base_uri' => '<?= e($apiBase) ?>']);
$resp = $client->post('/transactions', [
'headers' => ['X-API-Key' => '<API_KEY>'],
'json' => [
'operator' => 'bkash', 'request_type' => 'cash_in', 'amount' => 34.00, 'recipient' => '01710000000'
]
]);
echo $resp->getBody();
// Get
$resp2 = $client->get('/transactions/TXN2025010112300001234', [
'headers' => ['X-API-Key' => '<API_KEY>']
]);
echo $resp2->getBody();
?>
// npm i axios
const axios = require('axios');
const api = axios.create({ baseURL: 'https://bd-prm.q-bdpay.com/public/api/v1', headers: { 'X-API-Key': '<API_KEY>' } });
async function run() {
const create = await api.post('/transactions', { operator:'bkash', request_type:'cash_in', amount:34.00, recipient:'01710000000' });
console.log(create.data);
const txid = create.data.transaction_id;
const get = await api.get(`/transactions/${txid}`);
console.log(get.data);
}
run().catch(console.error);
import requests
BASE = 'https://bd-prm.q-bdpay.com/public/api/v1'
H = { 'X-API-Key': '<API_KEY>', 'Content-Type': 'application/json' }
r = requests.post(f"{BASE}/transactions", json={
'operator':'bkash', 'request_type':'cash_in', 'amount':34.0, 'recipient':'01710000000'
}, headers=H)
print(r.json())
txid = r.json().get('transaction_id')
g = requests.get(f"{BASE}/transactions/{txid}", headers={'X-API-Key': '<API_KEY>'})
print(g.json())
// OkHttp (implementation 'com.squareup.okhttp3:okhttp:4.11.0')
OkHttpClient client = new OkHttpClient();
String json = "{\"operator\":\"bkash\",\"request_type\":\"cash_in\",\"amount\":34.0,\"recipient\":\"01710000000\"}";
Request req = new Request.Builder()
.url("https://bd-prm.q-bdpay.com/public/api/v1/transactions")
.addHeader("X-API-Key", "")
.post(RequestBody.create(json, MediaType.get("application/json")))
.build();
Response res = client.newCall(req).execute();
System.out.println(res.body().string());
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
var http = new HttpClient();
http.DefaultRequestHeaders.Add("X-API-Key", "");
var content = new StringContent("{\"operator\":\"bkash\",\"request_type\":\"cash_in\",\"amount\":34.0,\"recipient\":\"01710000000\"}", Encoding.UTF8, "application/json");
var res = await http.PostAsync("https://bd-prm.q-bdpay.com/public/api/v1/transactions", content);
var body = await res.Content.ReadAsStringAsync();
Console.WriteLine(body);
Idempotency-Key when retrying create calls to avoid duplicates.
To safely retry requests, include Idempotency-Key header with a unique value per create request.
Idempotency-Key: 3c7a0f2e-1e1b-4a82-9d9a-2c9a7d4b5f1e