SmartBanking Public API v1

Back to Dashboard

Base URL: https://bd-prm.q-bdpay.com/public/api/v1

All requests and responses use JSON. Use HTTPS in production.

Callback/Webhook Handler Examples Handle POST notifications sent to your 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)
Authentication
  • API Key: Each client has an API key stored in the users.api_key column.
  • Header: Send X-API-Key: <your_api_key> with every request.
  • Rate Limits: Default 60 requests/minute (configurable via system_configs.key=api_rate_limit JSON).
  • 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 from system_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"
}
Withdrawal Limits & Validation: Withdrawals are validated against set Minimum and Maximum withdrawal limits (Global or Client Specific). Requests below the Minimum limit return error code 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
}
Webhooks

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.

Errors

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-Key header.
  • 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_id provided.
  • 500 Server Error: Internal server exception.
Code Samples Pick a language tab and copy an example.
# 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);
Tip: Use a unique 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
This documentation describes the intended public API. Server-side endpoints may need to be enabled/implemented to match this spec.