Accept payments from customers all over Bangladesh — bKash, Nagad, Rocket, Upay, mCash, Tap, Binance Pay, cards and more — with automatic verification. This page explains everything you need to integrate NobabPay into your website, app or bot.
NobabPay is a full-featured payment gateway for Bangladesh. Your customers never leave your brand — they are redirected to a secure, white-labelled checkout page, and your server is notified automatically when the payment succeeds.
Every payment is automatically verified against the real transaction (SMS or gateway API). You do not need to check anything manually. When the payment completes you receive a webhook and the customer is redirected back to your success_url.
You can go from zero to your first live payment in about 10 minutes. Here is the whole flow.
Log in to nobabpay.top → Settings → Brands → click your API Key to copy it, then open Edit Brand and fill the Domain field with your website (e.g. your-site.com). The key only works from that domain — see Domain security.
Call /api/payment/create with the amount, success and cancel URLs. We return a payment_url.
Send the customer to payment_url. They pay on our secure checkout page.
Receive the webhook (or verify with the transaction ID) and confirm the order on your side.
POST /api/payment/create request, one redirect, and one webhook handler. That's the entire integration.amount, show the returned payment_url to your customer and poll the Verify API. Full steps: No website? (bots, apps, social pages).success_url, cancel_url and webhook_url must be on that same domain — otherwise the API answers 403. Details: Domain security.All endpoints accept and return JSON. Every request must be made over HTTPS and must include your API key.
Send your API key in the request header:
You can also pass it as a POST parameter named api_key instead of the header (the header is recommended — a key in the URL can end up in server logs). Your key is found at nobabpay.top → Settings → Brands (click the key to copy).
Every key is locked to the Domain saved on its brand: requests that come from a different website are rejected with 403, and the same is true for success_url / cancel_url / webhook_url that point somewhere else. Set the domain before you go live — see Domain security.
An API key belongs to a brand, and a brand has a Domain. The key only works from that domain, so a key that gets copied into someone else's website stops working. Three rules apply to every request:
| Rule | What it means |
|---|---|
| 1. Save your Domain | nobabpay.top → Settings → Brands → Edit Brand → Domain. Write one domain (your-site.com) or several separated by commas (your-site.com, shop.your-site.com). Any sub-domain of a saved domain is allowed automatically. |
| 2. Callback URLs must be on it | success_url, cancel_url and webhook_url must point to your saved domain (or its sub-domains). Our own checkout and dashboard pages are always allowed. |
| 3. POST only | Both endpoints answer POST requests. Any other method returns 405. |
If a brand has no Domain saved, the key cannot be used from a browser at all and its callbacks may only use our own pages — so always fill in the Domain field.
{
"status": 0,
"message": "This website is not allowed to use this API key."
}| Message | Why | Fix |
|---|---|---|
This website is not allowed to use this API key. | The request came from a domain that is not saved on the brand (or an Origin that carries no domain at all, such as a sandboxed iframe). | Open Edit Brand and add that domain to the Domain field, or call the API from your own server. |
success_url is not allowed for this brand key. Allowed domain(s): … | One of the callback URLs points to a different website. | Use your own domain for success_url, cancel_url and webhook_url — or add that domain to the brand. |
This brand has no domain configured, so browser calls are not allowed… | The brand has no Domain saved and the call came from a browser. | Save the brand's Domain in the panel. |
success_url is not allowed because no domain is configured for this brand key… | The brand has no Domain saved, so no callback URL can be trusted. | Save the brand's Domain in the panel, then retry. |
Creates a payment and returns the checkout URL you redirect the customer to. POST only — any other method returns 405.
| Parameter | Type | Required | Description |
|---|---|---|---|
amount | number | Yes | Amount to charge (e.g. 500 or 49.50). Maximum 1,000,000. |
success_url | string | No | URL the customer is redirected to after a successful payment. If you send it, it must be on your brand Domain (see Domain security). If you leave it out, the customer finishes on our own result page - see No website? |
cancel_url | string | No | URL for a cancelled / failed payment. Same rules as success_url. |
webhook_url | string | No | Server-to-server notification URL. We POST the payment status here. Highly recommended. Must be on your brand Domain. |
metadata | object | No | Any JSON object you want back, e.g. {"order_id": 1024}. Returned unchanged in the verify response. |
cus_name | string | No | Customer name shown on the checkout page (default: Default Name). |
cus_email | string | No | Customer email (default: default@gmail.com). |
curl -X POST https://pay.nobabpay.top/api/payment/create \
-H "API-KEY: your_brand_api_key" \
-H "Content-Type: application/json" \
-d '{
"amount": 500,
"success_url": "https://your-site.com/payment/success",
"cancel_url": "https://your-site.com/payment/cancel",
"webhook_url": "https://your-site.com/payment/webhook",
"metadata": {"order_id": 1024, "user_id": 55},
"cus_name": "Rahim Uddin",
"cus_email": "rahim@example.com"
}'{
"status": 1,
"message": "Payment Link",
"payment_url": "https://pay.nobabpay.top/api/execute/a1b2c3d4e5f6...",
"transaction_id": "SN9GOP758751"
}Next step: redirect or send your customer to payment_url (HTTP 302 / window.location), and store transaction_id - that is the value you check later with the Verify API.
status == 1 and payment_url, not by status alone: a few error replies use the string "error", which is truthy in every language.Checks the current status of a transaction using its ID. Use this in your webhook handler or on the success page before shipping the order.
| Parameter | Type | Required | Description |
|---|---|---|---|
transaction_id | string | Yes | The NobabPay transaction ID: the transaction_id returned by create, the transactionId from the webhook or from the redirect URL. A transaction ID typed by the customer is not accepted - it must be ours. |
curl -X POST https://pay.nobabpay.top/api/payment/verify \
-H "API-KEY: your_brand_api_key" \
-H "Content-Type: application/json" \
-d '{"transaction_id": "SXF80K119297"}'{
"cus_name": "Rahim Uddin",
"cus_email": "rahim@example.com",
"amount": "500.000",
"transaction_id": "SXF80K119297",
"metadata": {"order_id": 1024, "user_id": 55},
"payment_method": "bkash",
"status": "COMPLETED"
}{
"status": 0,
"message": "failed"
}This reply means we have no such transaction ID in your account (a made-up ID, a typo, or an ID that belongs to another brand) - it does not mean a payment failed. Compare the ID character by character, or use the value returned by create.
| Status | Meaning | Action |
|---|---|---|
COMPLETED | The payment succeeded. | Fulfil the order. |
PENDING | The payment is still processing. | Wait — check again later or wait for the webhook. |
ERROR | The transaction failed. | Treat as unpaid; ask the customer to retry. |
"status": 0 + "message": "failed" | No transaction with that ID exists in your account. | Check the ID (it is not a failed payment) - use the value returned by create. |
You do not need a website, a domain or a webhook to accept payments. Send only the amount: the customer finishes on NobabPay's own result page, and you confirm the payment by checking the Verify API with the transaction_id that create returned.
curl -X POST https://pay.nobabpay.top/api/payment/create \
-H "API-KEY: your_brand_api_key" \
-d "amount=100" \
-d "cus_name=Telegram user" \
-d "metadata={\"telegram_id\":123456,\"bot_url\":\"https://t.me/yourbot\"}"metadata.bot_url (for example https://t.me/yourbot) and our result page shows the customer a Back to Telegram button. Only Telegram links are accepted — the page can never redirect to an unknown website.You get payment_url (send it to the customer - an inline button is nicest) and transaction_id (save it with your order).
repeat every 5-10 seconds (up to about 10 minutes):
POST https://pay.nobabpay.top/api/payment/verify
body: {"transaction_id": "SN9GOP758751"}
status COMPLETED -> deliver the order, stop
status ERROR -> tell the customer it failed, stop
status PENDING -> wait and repeat
{"status":0,"message":"failed"} -> unknown ID, do not deliververify answers COMPLETED.This is the complete journey of one payment, from creation to confirmation. Understand this once and the whole API becomes obvious.
/api/payment/create with the amount and your URLs.payment_url. You redirect the customer there.webhook_url with the result./api/payment/verify with the transaction ID to confirm (recommended).success_url (or cancel_url).NobabPay notifies your server automatically. Here is exactly what is sent and how to use it safely.
webhook_url, success_url and cancel_url must be on the Domain saved on your brand — a URL on any other website makes the create call fail with 403. See Domain security.When a payment status changes, NobabPay sends a POST request (form-encoded) to your webhook_url:
| Parameter | Description |
|---|---|
paymentMethod | The payment method used (e.g. bkash, nagad, binance). |
transactionId | Unique NobabPay transaction ID — use this with the Verify API. |
paymentAmount | The amount paid. |
paymentFee | The gateway fee deducted. |
status | pending | completed | failed |
/api/payment/verify with transactionId and only fulfil the order when the returned status is COMPLETED. Never trust the webhook body alone.After the payment, the customer is redirected to your success_url (on success) or cancel_url (on cancel/failure), with these query parameters appended:
| Parameter | Description |
|---|---|
status | pending, completed or failed |
transactionId | The NobabPay transaction ID. |
paymentMethod | The method the customer used. |
paymentAmount | Amount paid. |
paymentFee | Gateway fee. |
Use the redirect page only to show a nice confirmation screen. Fulfil the order based on the webhook or verify API result.
Copy-paste ready examples in PHP, Python and JavaScript. Replace YOUR_API_KEY and your URLs, and you are done.
<?php // 1. Create the payment function nobabpay_create_payment($amount, $metadata) { $payload = [ 'amount' => $amount, 'success_url' => 'https://your-site.com/payment/success', 'cancel_url' => 'https://your-site.com/payment/cancel', 'webhook_url' => 'https://your-site.com/payment/webhook', 'metadata' => $metadata, ]; $ch = curl_init('https://pay.nobabpay.top/api/payment/create'); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => json_encode($payload), CURLOPT_HTTPHEADER => [ 'API-KEY: YOUR_API_KEY', 'Content-Type: application/json', ], ]); $response = curl_exec($ch); curl_close($ch); return json_decode($response, true); } // 2. Redirect the customer $result = nobabpay_create_payment(500, ['order_id' => 1024]); header('Location: ' . $result['payment_url']); exit;
<?php // Receive the webhook from NobabPay $transaction_id = $_POST['transactionId'] ?? ''; // Always verify with the API before trusting the webhook $ch = curl_init('https://pay.nobabpay.top/api/payment/verify'); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => json_encode(['transaction_id' => $transaction_id]), CURLOPT_HTTPHEADER => ['API-KEY: YOUR_API_KEY', 'Content-Type: application/json'], ]); $verified = json_decode(curl_exec($ch), true); curl_close($ch); if (!empty($verified['status']) && $verified['status'] === 'COMPLETED') { $meta = json_decode($verified['metadata'] ?? '{}', true); // Mark order $meta['order_id'] as paid with $verified['transaction_id'] } http_response_code(200); echo 'OK';
import requests, json API = "https://pay.nobabpay.top/api" HEADERS = {"API-KEY": "YOUR_API_KEY", "Content-Type": "application/json"} # Create payment r = requests.post(f"{API}/payment/create", json={ "amount": 500, "success_url": "https://your-site.com/payment/success", "cancel_url": "https://your-site.com/payment/cancel", "webhook_url": "https://your-site.com/payment/webhook", "metadata": {"order_id": 1024}, }, headers=HEADERS) payment = r.json() # redirect customer: payment["payment_url"] # Verify payment r = requests.post(f{API}/payment/verify", json={ "transaction_id": "SXF80K119297" }, headers=HEADERS) print(r.json())
const API = 'https://pay.nobabpay.top/api'; const HEADERS = { 'API-KEY': 'YOUR_API_KEY', 'Content-Type': 'application/json' }; // Create payment const res = await fetch(`${API}/payment/create`, { method: 'POST', headers: HEADERS, body: JSON.stringify({ amount: 500, success_url: 'https://your-site.com/payment/success', cancel_url: 'https://your-site.com/payment/cancel', webhook_url: 'https://your-site.com/payment/webhook', metadata: { order_id: 1024 }, }), }); const { payment_url } = await res.json(); // redirect customer to payment_url // Verify payment const v = await fetch(`${API}/payment/verify`, { method: 'POST', headers: HEADERS, body: JSON.stringify({ transaction_id: 'SXF80K119297' }), }); console.log(await v.json());
Every error is returned as JSON with a status of 0 and a human-readable message.
{ "status": 0, "message": "API key missing. Send it in the API-KEY header." }| Message | Cause | Fix |
|---|---|---|
API key missing. Send it in the API-KEY header. | No key reached us — usually a missing/renamed header or a typo in the key name. | Send the API-KEY header exactly as shown above. |
Invalid API Request. The API key is unknown, the brand is switched off, or the owner plan has expired. | The key was received but no matching, usable brand was found. | Check the key in Settings → Brands, make sure the brand switch is Active, and that the account plan is running. |
This website is not allowed to use this API key. | Domain lock: the caller's website is not the brand's saved Domain. | Add the domain in Edit Brand, or call the API from your own server. See Domain security. |
… is not allowed for this brand key. Allowed domain(s): … | Domain lock: a callback URL points to a different website. | Use your brand Domain for success_url, cancel_url and webhook_url. |
HTTP 405 — Only POST requests are accepted. | The endpoint was called with GET/HEAD (for example an <img> or a link). | Use POST. |
Invalid Parameters | amount, success_url or cancel_url is missing/invalid. | Send all required fields. |
Metadata must be in JSON format | metadata was sent as a string instead of an object. | Send it as a real JSON object. |
Maximum amount 1000000 | The amount exceeds the limit. | Split the payment or lower the amount. |
HTTP 400 / 404 | Bad endpoint or invalid request path. | Use the exact URLs from this documentation. |
No coding needed — install these and accept payments in minutes.
Full payment gateway plugin with auto-verification via webhook. Download nobabpay-wordpress.zip from the links below.
Invoice payment module for hosting businesses. Download nobabpay-whmcs.zip and upload modules/gateways/ to your WHMCS root.
The Nobab Pay Android app forwards your bKash/Nagad/Rocket payment SMS for instant auto-verification.
WooCommerce setup: Plugins → Add New → Upload the zip → Activate → WooCommerce → Settings → Payments → NobabPay → Enable and paste your API key.
WHMCS setup: Upload the modules/ folder to your WHMCS root → Setup → Payments → Payment Gateways → NobabPay → Activate and paste your API key.
Quick answers to the questions developers ask most.
POST /api/payment/verify with the transaction ID. Only a status of COMPLETED means the money arrived. The webhook and the customer redirect alone are not enough.403 This website is not allowed to use this API key. — why?a.com, b.com). The same rule applies to success_url, cancel_url and webhook_url.403. For unrelated projects use a separate brand (and therefore its own key) per website; that also keeps reporting and payouts separate.