BDS Pay Developer Docs Contract updated: 2026-08-18

Use the server-verified BDS Pay payment API to create a hosted checkout and verify the resulting transaction. The browser success/cancel return is navigation only; your server must verify transaction_id before marking an order paid.

REST API Brand-scoped auth Server verification Metadata binding

API Contract

Authentication

Authenticate with your brand API key using one of these supported forms. Prefer the Authorization header for new integrations.

  • Authorization: Bearer YOUR_API_KEY (preferred)
  • API-KEY: YOUR_API_KEY
  • X-API-KEY: YOUR_API_KEY
  • Legacy request field api_key is accepted for backward compatibility.

Use only the API-key authentication forms listed above. Older multi-secret header examples are obsolete and are not part of the current merchant API contract.

Create Payment

POST https://payment.bdscommerce.com/api/payment/create

FieldRequiredContract
amountYesNumeric, greater than 0 and less than or equal to 1,000,000.
success_urlYesValid HTTP/HTTPS URL. Navigation destination only.
cancel_urlYesValid HTTP/HTTPS URL. Navigation destination only.
webhook_urlNoOptional server callback URL; subject to the gateway's outbound endpoint safety policy.
metadataNoJSON object. Use it to bind your own order/invoice identity.
cus_nameNoCustomer name.
cus_emailNoCustomer email.
cus_phoneNoCustomer phone.
return_typeNoGET or POST; invalid values fall back to GET.

Successful intent creation returns transaction_id and a hosted payment_url. Persist the transaction ID against your order before redirecting the customer.

Verify Payment

POST https://payment.bdscommerce.com/api/payment/verify

Request body: {"transaction_id":"YOUR_TRANSACTION_ID"}

Verification is scoped to the authenticated brand. Current status labels are PENDING, COMPLETED, CANCELLED, and ERROR. Treat only COMPLETED as paid.

The response includes amount, transaction_id, metadata, and payment_method. Your application must compare the verified amount and metadata order identity with its own server-side order before fulfillment.

Integration

Create Payment Sample

Persist your own order first, put that order identifier in metadata, create the gateway transaction, then persist the returned transaction_id before redirecting the browser.

<?php$payload = [ 'amount' => 100.00, 'success_url' => 'https://merchant.example/payment/return', 'cancel_url' => 'https://merchant.example/payment/cancel', 'webhook_url' => 'https://merchant.example/webhooks/bds-payment', 'metadata' => ['order_id' => 'ORDER-1001'], 'cus_name' => 'Customer Name', 'cus_email' => 'customer@example.com', 'return_type' => 'GET',];$ch = curl_init('https://payment.bdscommerce.com/api/payment/create');curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_SSL_VERIFYPEER => true, CURLOPT_SSL_VERIFYHOST => 2, CURLOPT_FOLLOWLOCATION => false, CURLOPT_CONNECTTIMEOUT => 5, CURLOPT_TIMEOUT => 15, CURLOPT_HTTPHEADER => [ 'Authorization: Bearer YOUR_API_KEY', 'Content-Type: application/json', ], CURLOPT_POSTFIELDS => json_encode($payload),]);$response = curl_exec($ch);if ($response === false) { throw new RuntimeException(curl_error($ch)); }$data = json_decode($response, true, 512, JSON_THROW_ON_ERROR);curl_close($ch);// Save $data['transaction_id'] against ORDER-1001 before redirecting.// Then redirect the customer to $data['payment_url'].?>

Typical create response

{ "status": 1, "message": "Payment Link", "transaction_id": "...", "payment_url": "https://payment.bdscommerce.com/api/execute/..."}

Verify Payment Sample

Never fulfill from the browser return alone. Verify the transaction from your server and compare status, amount, transaction identity and metadata with the order you previously stored.

<?php$transactionId = 'TRANSACTION_ID_SAVED_ON_YOUR_ORDER';$ch = curl_init('https://payment.bdscommerce.com/api/payment/verify');curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_SSL_VERIFYPEER => true, CURLOPT_SSL_VERIFYHOST => 2, CURLOPT_FOLLOWLOCATION => false, CURLOPT_CONNECTTIMEOUT => 5, CURLOPT_TIMEOUT => 15, CURLOPT_HTTPHEADER => [ 'Authorization: Bearer YOUR_API_KEY', 'Content-Type: application/json', ], CURLOPT_POSTFIELDS => json_encode(['transaction_id' => $transactionId]),]);$response = curl_exec($ch);if ($response === false) { throw new RuntimeException(curl_error($ch)); }$verified = json_decode($response, true, 512, JSON_THROW_ON_ERROR);curl_close($ch);$orderIdMatches = ($verified['metadata']['order_id'] ?? '') === 'ORDER-1001';$amountMatches = abs((float) ($verified['amount'] ?? 0) - 100.00) < 0.01;$transactionMatches = hash_equals($transactionId, (string) ($verified['transaction_id'] ?? ''));if (($verified['status'] ?? '') === 'COMPLETED' && $orderIdMatches && $amountMatches && $transactionMatches) { // Mark ORDER-1001 paid exactly once in your own transaction/idempotency boundary.}?>

Verify response fields

{ "status": "COMPLETED", "success": 1, "cus_name": "Customer Name", "cus_email": "customer@example.com", "amount": 100, "transaction_id": "...", "metadata": {"order_id": "ORDER-1001"}, "payment_method": "bkash"}

Framework & Platform Packages

These packages implement the current server-authoritative contract. Runtime certification still depends on the target platform/version and your application order adapter.

WooCommerce/WHMCS/Laravel/CodeIgniter/SMM packages bind verified status, amount, transaction identity and metadata to the originating application order. Keep an integration disabled until its target-environment E2E is complete.