Webhooks

Payment success webhook

When a payment is verified, TakaPay POSTs to your server URL. Set it in Admin → Stores & API → Webhook URL.

Outbound webhook (TakaPay → your server)

Fired on every payment.verified event. Your endpoint should return 2xx within 8 seconds.

POST → your webhook URL
{
  "event": "payment.verified",
  "paymentId": "987a15a8-c5d6-4e0d-94c6-523f8db581ee",
  "storeId": "store-uuid",
  "amount": 1490,
  "currency": "BDT",
  "provider": "bkash",
  "trxId": "BKH8X2K1M",
  "payerNumber": "01711111111",
  "customerName": "Rafi Hasan",
  "customerPhone": "01711111111",
  "note": "Order #2041",
  "verifiedAt": "2026-08-19T15:00:00.000Z"
}

Verify the signature

Every request includes X-TakaPay-Signature — HMAC-SHA256 of the raw request body using your store's Webhook Secret. Always verify before fulfilling.

Node.js
const crypto = require('crypto');

function verifySignature(rawBody, secret, sig) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(rawBody)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(sig)
  );
}

// Express example
app.post('/webhook/status', express.raw({ type: '*/*' }), (req, res) => {
  const sig = req.headers['x-takapay-signature'];
  if (!verifySignature(req.body, process.env.WEBHOOK_SECRET, sig)) {
    return res.status(401).send('Invalid signature');
  }
  const payload = JSON.parse(req.body.toString());
  if (payload.event === 'payment.verified') {
    // fulfill order using payload.note or payload.paymentId
  }
  res.json({ ok: true });
});
PHP
$rawBody = file_get_contents('php://input');
$sig = $_SERVER['HTTP_X_TAKAPAY_SIGNATURE'] ?? '';
$secret = getenv('WEBHOOK_SECRET');

$expected = hash_hmac('sha256', $rawBody, $secret);
if (!hash_equals($expected, $sig)) {
    http_response_code(401);
    exit('Invalid signature');
}

$payload = json_decode($rawBody, true);
if ($payload['event'] === 'payment.verified') {
    // fulfill order
}
echo json_encode(['ok' => true]);

Inbound webhook (TakaPay Android app → TakaPay server)

The TakaPay Android app reads bKash / Nagad / Rocket SMS receipts and forwards them to TakaPay. This is handled automatically — you don't need to call this.

POST/api/webhooks/takapay

Auth: X-Webhook-Secret (set in Admin → Settings)

payload from Android app
{
  "app": "TakaPay",
  "provider": "bkash",
  "kind": "received",
  "trxId": "BKH8X2K1M",
  "amount": 1490,
  "counterparty": "01711111111",
  "receivedAt": "2026-08-19T15:00:00.000Z",
  "balance": 5000.00,
  "currency": "BDT"
}

Local testing

POST/api/webhooks/simulate

Simulate an SMS receipt from the merchant dashboard (Admin → Webhooks → Simulate).

curl (JWT)
curl http://localhost:4000/api/webhooks/simulate \
  -H "Authorization: Bearer $JWT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "provider": "bkash",
    "trxId": "TEST1234",
    "amount": 1490,
    "sender": "01711111111",
    "type": "in"
  }'