Hosted Checkout Sessions
Create payment sessions from your server and redirect customers to complete their payment securely via bKash, Nagad, Rocket, or international cards. Amounts are settled to your workspace balance minus the platform fee.
Endpoints
| Method | Path | Purpose |
|---|---|---|
| POST | /api/v1/payments | Create a hosted checkout session (201). |
| GET | /api/v1/payments/:id | Retrieve a payment with its fee breakdown. |
| GET | /api/v1/payments?page=&limit=&status= | List payments, newest first. |
| POST | /api/v1/payments/:id/refund | Refund a paid payment. |
Create request body
| Field | Type | Required | Description |
|---|---|---|---|
| amount | number | Required | Amount in `currency`; must be at least 1. |
| success_url | string | Required | Absolute URL the customer returns to after paying. |
| cancel_url | string | Required | Absolute URL the customer returns to when they cancel. |
| currency | string | Optional | `BDT` (default) or `USD`. No other currency is accepted. |
| description | string | Optional | Shown to the customer on the checkout page. |
| customer | object | Optional | `{ name, email, phone }`, stored on the payment and echoed in webhooks. |
| metadata | object | Optional | Arbitrary key/value pairs, returned unchanged in webhooks. |
Field names are snake_case, and unknown fields are rejected.
The API validates strictly: successUrl, customerName and any other unrecognised field return 400 Bad Request. Send success_url / cancel_url and nest customer details under customer.
Node.js request example
const response = await fetch('https://api.superchatbd.com/api/v1/payments', {
method: 'POST',
headers: {
'Authorization': 'Bearer sk_live_your_api_key',
'Content-Type': 'application/json',
'Idempotency-Key': 'order_12345', // optional, but keeps retries safe
},
body: JSON.stringify({
amount: 1500,
currency: 'BDT',
description: 'Pro Subscription - 1 Month',
success_url: 'https://myshop.com/orders/12345/success',
cancel_url: 'https://myshop.com/cart',
customer: {
name: 'Ashraful Islam',
email: '[email protected]',
phone: '01700000000',
},
metadata: { orderId: '12345', userId: 'usr_883' },
}),
});
if (!response.ok) throw new Error(await response.text());
const session = await response.json();
console.log(session.checkoutUrl);
// Redirect the customer to session.checkoutUrlResponse
{
"id": "pay_9f82d1c720b14f76bf10fa37b12d5893",
"merchantTransactionId": "pay_9f82d1c720b14f76bf10fa37b12d5893",
"checkoutUrl": "https://superchat.bd/checkout/pay_9f82d1c720b14f76bf10fa37b12d5893",
"amount": 1500,
"currency": "BDT",
"status": "pending", // public status: pending | completed | failed | cancelled | refunded | expired
"rawStatus": "created", // internal status: created | paid | ...
"environment": "live", // "test" for sk_test_… keys
"isSimulated": false,
"platformFeeAmount": 75, // 5% platform fee
"feePercentage": 5,
"netAmount": 1425, // credited to your workspace on success
"description": "Pro Subscription - 1 Month",
"customer": { "name": "Ashraful Islam", "email": "[email protected]", "phone": "01700000000" },
"customerName": "Ashraful Islam",
"customerEmail": "[email protected]",
"customerPhone": "01700000000",
"paymentMethod": null,
"metadata": { "orderId": "12345", "userId": "usr_883" },
"success_url": "https://myshop.com/orders/12345/success",
"cancel_url": "https://myshop.com/cart",
"paid_at": null,
"created_at": "2026-09-20T05:00:00.000Z",
"createdAt": "2026-09-20T05:00:00.000Z",
"updatedAt": "2026-09-20T05:00:00.000Z"
}Payments created with an sk_test_ key run in the sandbox: they behave identically but can be settled instantly from the sandbox simulator. Legacy snake_case aliases (checkout_url, platform_fee, platform_fee_rate, net_amount) are still returned.
Refunding a payment
Refunds can be initiated by making a POST request to /api/v1/payments/:id/refund. Only payments in the internal paid status can be refunded. A successful refund immediately debits the developer workspace balance and lifetime earnings, updates the status to refunded, and triggers a payment.refunded webhook.
const response = await fetch('https://api.superchatbd.com/api/v1/payments/pay_9f82d1c720b14f76bf10fa37b12d5893/refund', {
method: 'POST',
headers: {
'Authorization': 'Bearer sk_live_your_api_key',
'Content-Type': 'application/json',
'Idempotency-Key': 'refund_order_12345',
},
body: JSON.stringify({
reason: 'Customer requested cancellation',
}),
});
const refundedPayment = await response.json();
console.log(refundedPayment.status); // "refunded"
console.log(refundedPayment.refund);
// {
// id: null,
// requiresManualSettlement: true, // true for EPS / BDT
// reason: "Customer requested cancellation"
// }Manual settlement for BDT / EPS transactions
Bangladeshi MFS providers (bKash, Nagad, Rocket) and the EPS gateway do not provide programmatic reversal APIs. When refunding a BDT payment, the API adjusts your balance and returns requiresManualSettlement: true in the refund payload. The merchant is responsible for transferring the refund amount directly to the customer's account.
Test payments (sk_test_) cannot be refunded since no real money was transferred.
When creating payments with a test API key (sk_test_...), two testing paths are supported:
- 1-Click Simulator Controls: On the hosted checkout page, click Instant Success or Simulate Fail to trigger webhooks and return immediately to your redirect URLs without opening a gateway.
- Interactive EPS Sandbox Gateway: Click Proceed to EPS Sandbox Gateway to interact with the real EPS sandbox (sandboxpgapi.eps.com.bd) and test bKash, Nagad, and Rocket simulated payments end-to-end.
All test transactions fire HMAC-signed payment.completed webhooks exactly like live transactions. Real money is never transferred and test payments never credit live workspace balances.
Live payments must use https:// URLs (localhost is allowed for local development).
If your API key is bound to an application that has registered redirect URIs, both URLs must share an origin with one of them — this is what stops a leaked key from turning your checkout into an open redirect.
