A short, server-side payment flow
bestuPay is non-custodial. Customers pay the receiving wallet configured for your site, while the platform handles payment creation, exact-amount matching, on-chain status and notifications.
Create an order
Your server sends the local order number, amount and title.
Redirect to checkout
Send the customer to the returned checkout URL.
Track payment
bestuPay monitors the selected receiving wallet on-chain.
Verify the webhook
Validate the signature before fulfilling the local order.
Create your first payment
Store the API secret on your server. Never expose it in browser JavaScript, a mobile application or public source control.
curl -X POST https://dash.bestupay.com/api/v1/simple/payments \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_SECRET" \
-d '{
"order_no": "ORDER-20260921-001",
"amount": "328.00",
"title": "Business Plan"
}'
<?php
$payload = [
'order_no' => 'ORDER-' . time(),
'amount' => '328.00',
'title' => 'Business Plan',
];
$ch = curl_init('https://dash.bestupay.com/api/v1/simple/payments');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Authorization: Bearer ' . $apiSecret,
],
CURLOPT_POSTFIELDS => json_encode($payload),
]);
$result = json_decode(curl_exec($ch), true);
header('Location: ' . $result['data']['checkout_url']);
const response = await fetch(
'https://dash.bestupay.com/api/v1/simple/payments',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${process.env.BESTUPAY_API_SECRET}`
},
body: JSON.stringify({
order_no: `ORDER-${Date.now()}`,
amount: '328.00',
title: 'Business Plan'
})
}
);
const result = await response.json();
res.redirect(result.data.checkout_url);
import os
import requests
response = requests.post(
"https://dash.bestupay.com/api/v1/simple/payments",
headers={
"Authorization": f"Bearer {os.environ['BESTUPAY_API_SECRET']}"
},
json={
"order_no": "ORDER-20260921-001",
"amount": "328.00",
"title": "Business Plan",
},
)
checkout_url = response.json()["data"]["checkout_url"]
{
"success": true,
"data": {
"payment_id": "pay_...",
"checkout_url": "https://dash.bestupay.com/checkout/?payment_id=pay_..."
}
}
Create payment
The quick endpoint uses your site configuration for the receiving wallets, callback URL and return URL.
| Field | Type | Required | Description |
|---|---|---|---|
order_no | string | Yes | Your unique local order number. |
amount | decimal string | Yes | Original order value in USDT, with up to two decimal places. |
title | string | Yes | Product or order summary shown in merchant records. |
notify_url | URL | No | Fallback callback URL when none is configured for the site. |
return_url | URL | No | Customer return destination. Do not use it as proof of payment. |
expires_in | integer | No | Payment lifetime in seconds, from 300 to 86400. |
Verify before fulfillment
Read the raw JSON request body and calculate its HMAC-SHA256 digest using the Webhook Secret for the site. Compare the lowercase hexadecimal result with X-BestuPay-Signature using a timing-safe function.
X-BestuPay-Signature = HMAC-SHA256(raw JSON body, Webhook Secret)
Processing rules
- Return an HTTP 2xx response only after the event has been accepted.
- Use the event ID for idempotency so retries cannot fulfill an order twice.
- Match the local record using
merchant_order_noororder_no. - Fulfill only verified events whose status is
paid. - Route underpaid, overpaid, expired and late payments to review.
Choose the shortest path for your stack
Custom backend
Use the REST API from PHP, Node.js, Python, Java, Go or another server-side environment.
View examplesWordPress plugin
Configure credentials, callback handling and checkout redirects from your WordPress installation.
Download kitWooCommerce
Install the payment gateway, configure merchant credentials and complete orders after verified webhooks.
Download pluginProduction readiness
- Keep API and Webhook secrets server-side.
- Use HTTPS for callback and return URLs.
- Validate signatures with the raw request body.
- Make webhook processing idempotent.
- Do not fulfill from the browser return URL.
- Log event IDs and payment IDs for audits.
- Rotate credentials after suspected exposure.
- Handle exception statuses explicitly.