Documentation/Deposit Integration
DEPOSIT API · VERSION 1

Create checkout integration

ProtocolHTTPS
FormatJSON
AuthenticationHMAC-SHA256
CurrencyBDT
01 OVERVIEW

Integration architecture

MERCHANT ACTIVATION

Integration becomes available after merchant configuration

1Create Merchant PanelRegister the website domain and keep the merchant account active.
2Configure credentialsAdd Merchant ID, registered domain, API Key and Secret Key to the server environment.
3Send signed requestInclude the merchant identity and domain in both headers and signature payload.
4Open checkoutThe API returns a checkout URL and displays only admin-enabled payment methods.
BASE URLhttps://www.sendboxpay.cyou
bKashbkash Nagadnagad Rocketrocket
1Create OrderMerchant server sends signed JSON request
2Open CheckoutCustomer is redirected to checkout_url
3Select MethodOnly enabled methods are displayed
4Confirm ResultVerify webhook or query order status
02 API AUTHENTICATION

Sign every API request

Merchant identity and API credentials are available from the Merchant Panel. Every request must include the Merchant ID, the exact registered website domain, API Key, Unix timestamp, unique nonce and an HMAC-SHA256 signature calculated from the complete signature payload.

HeaderDescriptionRequired
Content-TypeMust be application/json.Yes
X-SBP-Merchant-IDThe Merchant ID shown in the Merchant Panel.Yes
X-SBP-Merchant-DomainThe exact registered website domain without protocol or path.Yes
X-SBP-API-KeyYour active merchant API Key.Yes
X-SBP-TimestampCurrent Unix timestamp in seconds. Maximum clock difference is five minutes.Yes
X-SBP-NonceA unique 16–100 character value using letters, numbers, underscore or hyphen.Yes
X-SBP-SignatureLowercase hexadecimal HMAC-SHA256 signature.Yes
SIGNATURE PAYLOAD {merchant_id}\n{merchant_domain}\n{timestamp}\n{nonce}\n{raw_json_body}

signature = HMAC-SHA256(signature payload, API Secret)

PHP signature example

<?php
$payload = [
    'order_id' => 'ORDER-10001',
    'amount' => '500.00',
    'customer_name' => 'Customer Name',
    'customer_email' => 'customer@example.com',
    'customer_phone' => '01712345678',
    'callback_url' => 'https://merchant.example.com/webhooks/sendboxpay',
];

$merchantId = 'SENDBOX123456';
$merchantDomain = 'merchant.example.com';
$body = json_encode($payload, JSON_UNESCAPED_SLASHES);
$timestamp = (string) time();
$nonce = bin2hex(random_bytes(16));
$signature = hash_hmac(
    'sha256',
    $merchantId . "\n" . $merchantDomain . "\n" . $timestamp . "\n" . $nonce . "\n" . $body,
    'YOUR_API_SECRET'
);
03 CREATE PAYMENT

Create a checkout session

POSThttps://www.sendboxpay.cyou/api/v1/payment/create.php

Request body

FieldTypeRequiredDescription
order_idstringYesUnique merchant reference, 6–80 letters, numbers, hyphens or underscores.
amountdecimalYesPayment amount with up to two decimal places.
customer_namestringYesCustomer name, 2–120 characters.
customer_emailstringYesValid customer email address.
customer_phonestringYesBangladeshi mobile number in 01XXXXXXXXX format.
methodstringNobkash, nagad or rocket. When omitted, the customer selects an enabled method on checkout.
callback_urlstringNoHTTPS endpoint for the payment completion webhook. Merchant profile URL is used when omitted.

Request example

{
  "order_id": "ORDER-10001",
  "amount": "500.00",
  "customer_name": "Customer Name",
  "customer_email": "customer@example.com",
  "customer_phone": "01712345678",
  "callback_url": "https://merchant.example.com/webhooks/sendboxpay"
}

Success response · HTTP 201

{
  "success": true,
  "order_id": "ORDER-10001",
  "invoice_id": "DMB-260716-A1B2C3",
  "status": "pending",
  "checkout_url": "https://www.sendboxpay.cyou/change-method.php?token=generated-session-token",
  "message": "Checkout created successfully."
}
05 PAYMENT STATUS

Query an order

POSThttps://www.sendboxpay.cyou/api/v1/payment/status.php

The status endpoint uses the same authentication headers and signature process as the create endpoint.

{
  "order_id": "ORDER-10001"
}
{
  "success": true,
  "payment": {
    "invoice_id": "DMB-260716-A1B2C3",
    "merchant_order_id": "ORDER-10001",
    "amount": "500.00",
    "status": "success",
    "masked_number": "01712345678",
    "transaction_id": "8N7K2P4M5Q",
    "completed_at": "2026-07-16 14:30:25",
    "method": "bkash"
  }
}
StatusMeaningRecommended action
pendingCheckout has not been completed.Keep the order unpaid and query again when needed.
successPayment has been completed.Fulfil once after webhook or verified status query.
failedPayment failed.Allow the customer to create a new order.
cancelledPayment was cancelled.Do not fulfil the order.
06 CALLBACK / WEBHOOK

Verify payment completion events

When a payment is completed, SendboxPay sends a JSON payment.completed event to the configured callback URL. Return any HTTP 2xx response after the signature and order data have been verified.

HeaderDescription
X-SBP-EventWebhook event name, for example payment.completed.
X-SBP-TimestampUnix timestamp used in webhook signature verification.
X-SBP-SignatureHMAC-SHA256 of {timestamp}\n{raw_json_body} using your API Secret.
{
  "event": "payment.completed",
  "sent_at": "2026-07-16T08:30:25+00:00",
  "data": {
    "order_id": "ORDER-10001",
    "invoice_id": "DMB-260716-A1B2C3",
    "status": "success",
    "amount": "500.00",
    "currency": "BDT",
    "method": "bkash",
    "transaction_id": "8N7K2P4M5Q",
    "completed_at": "2026-07-16 14:30:25"
  }
}

PHP webhook verification

<?php
$rawBody = file_get_contents('php://input') ?: '';
$timestamp = $_SERVER['HTTP_X_SBP_TIMESTAMP'] ?? '';
$receivedSignature = strtolower($_SERVER['HTTP_X_SBP_SIGNATURE'] ?? '');
$expectedSignature = hash_hmac(
    'sha256',
    $timestamp . "\n" . $rawBody,
    'YOUR_API_SECRET'
);

if (!ctype_digit($timestamp)
    || abs(time() - (int) $timestamp) > 300
    || !hash_equals($expectedSignature, $receivedSignature)) {
    http_response_code(401);
    exit('Invalid signature');
}

$event = json_decode($rawBody, true, 512, JSON_THROW_ON_ERROR);
if (($event['event'] ?? '') === 'payment.completed'
    && ($event['data']['status'] ?? '') === 'success') {
    // Update the matching order only once.
}

http_response_code(200);
echo 'OK';
07 ERROR HANDLING

HTTP status and error format

HTTPMeaningCommon cause
201CreatedCheckout session created successfully.
401UnauthorizedMissing or disabled merchant credential, expired timestamp or invalid signature.
403Domain not activeThe request domain does not match the domain registered for the Merchant ID.
404Not foundThe requested merchant order does not exist.
405Method not allowedThe endpoint received a request other than POST.
409ConflictDuplicate order ID or duplicate nonce.
422Validation failedInvalid amount, customer details, callback URL or unavailable method.
{
  "success": false,
  "errors": [
    "Invalid customer_email.",
    "Unavailable payment method."
  ]
}
08 SECURITY GUIDELINES

Required integration controls

01

Keep secrets server-side

Store API Secrets in environment variables or a protected secret manager. Never place them in HTML, JavaScript bundles, repositories or mobile applications.

02

Match the registered domain

Send the exact domain stored in the Merchant Panel and include it in the signature payload for every request.

03

Sign the exact raw body

Generate the JSON body once, sign that exact string and transmit the same string without rebuilding or reformatting it.

04

Use unique nonces

Create a cryptographically random nonce for every API call. Do not reuse a nonce within the acceptance window.

05

Verify amount and order ID

Before fulfilment, compare webhook data with the order stored on your server and process each successful order idempotently.

06

Use HTTPS callbacks

Use an HTTPS endpoint, verify webhook signatures and return a successful response only after durable processing.

09 SAMPLE INTEGRATIONS

Framework examples

<?php
function sendboxpayRequest(string $endpoint, array $payload): array
{
    $merchantId = getenv('SENDBOXPAY_MERCHANT_ID');
    $merchantDomain = getenv('SENDBOXPAY_MERCHANT_DOMAIN');
    $apiKey = getenv('SENDBOXPAY_API_KEY');
    $apiSecret = getenv('SENDBOXPAY_API_SECRET');
    $body = json_encode($payload, JSON_UNESCAPED_SLASHES);
    $timestamp = (string) time();
    $nonce = bin2hex(random_bytes(16));
    $signature = hash_hmac('sha256', $merchantId . "\n" . $merchantDomain . "\n" . $timestamp . "\n" . $nonce . "\n" . $body, $apiSecret);

    $ch = curl_init($endpoint);
    curl_setopt_array($ch, [
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => $body,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT => 30,
        CURLOPT_HTTPHEADER => [
            'Content-Type: application/json',
            'X-SBP-Merchant-ID: ' . $merchantId,
            'X-SBP-Merchant-Domain: ' . $merchantDomain,
            'X-SBP-API-Key: ' . $apiKey,
            'X-SBP-Timestamp: ' . $timestamp,
            'X-SBP-Nonce: ' . $nonce,
            'X-SBP-Signature: ' . $signature,
        ],
    ]);

    $response = curl_exec($ch);
    $status = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    if ($response === false || $status < 200 || $status >= 300) {
        throw new RuntimeException('Payment API request failed.');
    }

    return json_decode($response, true, 512, JSON_THROW_ON_ERROR);
}

$result = sendboxpayRequest('https://www.sendboxpay.cyou/api/v1/payment/create.php', [
    'order_id' => 'ORDER-' . time(),
    'amount' => '500.00',
    'customer_name' => 'Customer Name',
    'customer_email' => 'customer@example.com',
    'customer_phone' => '01712345678',
    'callback_url' => 'https://merchant.example.com/webhooks/sendboxpay',
]);

header('Location: ' . $result['checkout_url']);
exit;
<?php

namespace App\Services;

use Illuminate\Support\Facades\Http;
use Illuminate\Support\Str;
use RuntimeException;

class SendboxPay
{
    public function createPayment(array $payload): array
    {
        $merchantId = config('services.sendboxpay.merchant_id');
        $merchantDomain = config('services.sendboxpay.domain');
        $body = json_encode($payload, JSON_UNESCAPED_SLASHES);
        $timestamp = (string) time();
        $nonce = Str::random(32);
        $signature = hash_hmac(
            'sha256',
            $merchantId . "\n" . $merchantDomain . "\n" . $timestamp . "\n" . $nonce . "\n" . $body,
            config('services.sendboxpay.secret')
        );

        $response = Http::withBody($body, 'application/json')
            ->withHeaders([
                'X-SBP-Merchant-ID' => $merchantId,
                'X-SBP-Merchant-Domain' => $merchantDomain,
                'X-SBP-API-Key' => config('services.sendboxpay.key'),
                'X-SBP-Timestamp' => $timestamp,
                'X-SBP-Nonce' => $nonce,
                'X-SBP-Signature' => $signature,
            ])
            ->post('https://www.sendboxpay.cyou/api/v1/payment/create.php');

        if (!$response->successful()) {
            throw new RuntimeException($response->body());
        }

        return $response->json();
    }
}
import crypto from 'node:crypto';

export async function createPayment(payload) {
  const merchantId = process.env.SENDBOXPAY_MERCHANT_ID;
  const merchantDomain = process.env.SENDBOXPAY_MERCHANT_DOMAIN;
  const body = JSON.stringify(payload);
  const timestamp = Math.floor(Date.now() / 1000).toString();
  const nonce = crypto.randomBytes(16).toString('hex');
  const signature = crypto
    .createHmac('sha256', process.env.SENDBOXPAY_API_SECRET)
    .update(`${merchantId}\n${merchantDomain}\n${timestamp}\n${nonce}\n${body}`)
    .digest('hex');

  const response = await fetch('https://www.sendboxpay.cyou/api/v1/payment/create.php', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-SBP-Merchant-ID': merchantId,
      'X-SBP-Merchant-Domain': merchantDomain,
      'X-SBP-API-Key': process.env.SENDBOXPAY_API_KEY,
      'X-SBP-Timestamp': timestamp,
      'X-SBP-Nonce': nonce,
      'X-SBP-Signature': signature
    },
    body
  });

  const result = await response.json();
  if (!response.ok) throw new Error(JSON.stringify(result));
  return result;
}
import hashlib
import hmac
import json
import os
import secrets
import time
import requests

payload = {
    "order_id": f"ORDER-{int(time.time())}",
    "amount": "500.00",
    "customer_name": "Customer Name",
    "customer_email": "customer@example.com",
    "customer_phone": "01712345678",
}
merchant_id = os.environ["SENDBOXPAY_MERCHANT_ID"]
merchant_domain = os.environ["SENDBOXPAY_MERCHANT_DOMAIN"]
body = json.dumps(payload, separators=(",", ":"))
timestamp = str(int(time.time()))
nonce = secrets.token_hex(16)
message = f"{merchant_id}\n{merchant_domain}\n{timestamp}\n{nonce}\n{body}".encode()
signature = hmac.new(
    os.environ["SENDBOXPAY_API_SECRET"].encode(),
    message,
    hashlib.sha256,
).hexdigest()

response = requests.post(
    "https://www.sendboxpay.cyou/api/v1/payment/create.php",
    data=body,
    headers={
        "Content-Type": "application/json",
        "X-SBP-Merchant-ID": merchant_id,
        "X-SBP-Merchant-Domain": merchant_domain,
        "X-SBP-API-Key": os.environ["SENDBOXPAY_API_KEY"],
        "X-SBP-Timestamp": timestamp,
        "X-SBP-Nonce": nonce,
        "X-SBP-Signature": signature,
    },
    timeout=30,
)
response.raise_for_status()
print(response.json()["checkout_url"])
10
INTEGRATION PACKAGE

Download Deposit Module

Includes complete integration documentation, installation guide, example project structure, sample configuration, API client examples and webhook handlers for PHP, Laravel, Node.js and Python.

Download Module