Integration documentation

Add USDT payments to any website or app. Base URL: http://x.smboostzone.shop · Networks: TRC20, BEP20

Overview

Your server creates an invoice, sends the customer to the hosted pay page, and receives a signed webhook when the payment is confirmed (or fails). Everything is server-to-server and signed with HMAC-SHA256.

StepWhoWhat
1Your serverPOST /api/create.php → get pay_url
2CustomerOpens pay_url, sends the exact USDT amount
3GatewayDetects payment on-chain, page turns Successful
4Gateway → youPOST signed invoice.paid / invoice.failed to your callback_url
5CustomerReturns to your return_url → you show status from your DB
Unique amount: each invoice gets a slightly different amount (e.g. 10.5021) so payments can be matched without per-order wallets. The customer must send that exact amount.

Quick start (5 minutes)

  1. Open Admin → Merchants, add your site, copy API Key and API Secret.
  2. Download the Integration Kit (PHP) or use the samples below.
  3. Create an invoice from your checkout, redirect to pay_url.
  4. Add a public HTTPS callback_url endpoint that verifies the signature and updates your order/wallet.
  5. Test with a small amount (1 USDT) — see Testing.

Authentication & signatures

Each merchant has an api_key (public id) and api_secret (private — server only). Requests are signed with HMAC-SHA256 (hex) using the secret.

EndpointMessage to sign
POST /api/create.phpapi_key|order_id|amount
GET /api/status.phpinvoice_id
Webhook (incoming)timestamp.raw_body
Sign the exact amount string you send ("10.50" and "10.5" produce different signatures).

Create invoice

POST http://x.smboostzone.shop/api/create.php · application/x-www-form-urlencoded

FieldReq.Description
api_key✅Your merchant key
order_id✅Your unique order id (≤100 chars)
amount✅String, max 2 decimals, e.g. 10.50 (min 1)
sign✅HMAC as above
networkTRC20 | BEP20 — empty = customer chooses on the pay page
callback_urlWebhook URL (public http/https)
return_urlCustomer is redirected here after payment (?invoice_id=…&order_id=… appended)
pagecheckout = modern dark checkout (currency → network sheet → QR page). Default = classic pay page
<?php
require 'UsdtGateway.php';                         // Integration Kit से
$gw = new UsdtGateway('http://x.smboostzone.shop', 'YOUR_API_KEY', 'YOUR_API_SECRET');

$inv = $gw->createInvoice('ORDER-1001', '10.50', [
  'callback_url' => 'https://yourshop.com/callback.php',
  'return_url'   => 'https://yourshop.com/return.php',
  // 'network'   => 'TRC20',                       // optional: TRC20 | BEP20
]);
header('Location: ' . $inv['pay_url']);            // customer को payment page पर भेजें
// Node 18+
const crypto = require('crypto');
const BASE='http://x.smboostzone.shop', KEY='YOUR_API_KEY', SECRET='YOUR_API_SECRET';

async function createInvoice(orderId, amount, extra = {}) {
  const f = { api_key: KEY, order_id: orderId, amount, ...extra };      // amount = string "10.50"
  f.sign = crypto.createHmac('sha256', SECRET).update(`${KEY}|${orderId}|${amount}`).digest('hex');
  const r = await fetch(`${BASE}/api/create.php`, { method: 'POST', body: new URLSearchParams(f) });
  const j = await r.json(); if (!j.success) throw new Error(j.error);
  return j;                                                              // j.pay_url
}
import hmac, hashlib, requests
BASE, KEY, SECRET = "http://x.smboostzone.shop", "YOUR_API_KEY", "YOUR_API_SECRET"

def create_invoice(order_id, amount, **extra):            # amount = string "10.50"
    f = {"api_key": KEY, "order_id": order_id, "amount": amount, **extra}
    f["sign"] = hmac.new(SECRET.encode(), f"{KEY}|{order_id}|{amount}".encode(), hashlib.sha256).hexdigest()
    j = requests.post(f"{BASE}/api/create.php", data=f, timeout=20).json()
    if not j.get("success"): raise RuntimeError(j.get("error"))
    return j                                               # j["pay_url"]
KEY="YOUR_API_KEY"; SECRET="YOUR_API_SECRET"; ORDER="ORDER-1001"; AMOUNT="10.50"
SIGN=$(echo -n "$KEY|$ORDER|$AMOUNT" | openssl dgst -sha256 -hmac "$SECRET" | awk '{print $2}')
curl -X POST "http://x.smboostzone.shop/api/create.php" \
  -d "api_key=$KEY&order_id=$ORDER&amount=$AMOUNT&network=TRC20&sign=$SIGN" \
  -d "callback_url=https://yourshop.com/callback.php&return_url=https://yourshop.com/return.php"

Response

{
  "success": true,
  "invoice_id": "INV37227043E4BC58",
  "order_id": "ORDER-1001",
  "status": "pending",
  "network": "TRC20",
  "amount": "10.50",
  "pay_amount": "10.5021",
  "pay_address": "T...",
  "expires_at": "2026-10-29T04:00:25Z",
  "pay_url": "http://x.smboostzone.shop/pay.php?id=INV37227043E4BC58"
}

Calling again with the same order_id + amount while an invoice is pending returns the same invoice (idempotent).

Check status

GET http://x.smboostzone.shop/api/status.php?api_key=KEY&invoice_id=INV…&sign=HMAC(invoice_id)

{ "success": true, "invoice_id": "INV…", "order_id": "ORDER-1001", "status": "paid",
  "network": "TRC20", "amount": "10.50", "pay_amount": "10.5021", "txid": "…", "paid_at": "2026-10-29T03:30:25Z" }

Use it to reconcile if a webhook was missed. status is pending, paid or expired.

Webhooks

Sent as POST JSON to your callback_url with headers X-Gateway-Timestamp and X-Gateway-Signature.

eventWhen
invoice.paidPayment confirmed on-chain
invoice.failedInvoice expired without payment
{ "event": "invoice.paid", "invoice_id": "INV…", "order_id": "ORDER-1001", "network": "TRC20",
  "amount": "10.50", "pay_amount": "10.5021", "status": "paid", "txid": "…", "paid_at": "2026-10-29T03:30:25Z" }

{ "event": "invoice.failed", "invoice_id": "INV…", "order_id": "ORDER-1001", "network": "TRC20",
  "amount": "10.50", "pay_amount": "10.5021", "status": "expired",
  "reason": "payment_not_received", "expired_at": "2026-10-29T04:00:25Z" }

Retries: if you don't return HTTP 2xx, it retries after 1 min, 5 min, 30 min, 2 h and 6 h. You can also press Resend callback in the admin panel.

Verify a webhook

  1. Compute HMAC_SHA256(timestamp + "." + RAW_BODY, api_secret) and compare with X-Gateway-Signature (constant-time).
  2. Reject if the timestamp is older than ~10 minutes (replay protection).
  3. Find your order, check the amount matches, update it idempotently (the same webhook may arrive twice).
  4. Return 200 OK.
<?php   // callback.php
require 'UsdtGateway.php';
$gw = new UsdtGateway('http://x.smboostzone.shop', 'YOUR_API_KEY', 'YOUR_API_SECRET');
try { $d = $gw->verifyWebhook(); } catch (Throwable $e) { http_response_code(403); exit; }   // signature + time check

if ($d['event'] === 'invoice.paid')   { /* order paid / wallet credit  (idempotent!) */ }
if ($d['event'] === 'invoice.failed') { /* order failed / cancel */ }
echo 'OK';                                          // 2xx वापस करें, वरना retry होगा
const express = require('express'); const crypto = require('crypto');
const app = express();
app.post('/callback', express.raw({ type: '*/*' }), (req, res) => {
  const ts = req.header('X-Gateway-Timestamp') || '', sig = req.header('X-Gateway-Signature') || '';
  const body = req.body.toString('utf8');                       // RAW body पर verify करें
  const exp = crypto.createHmac('sha256', SECRET).update(`${ts}.${body}`).digest('hex');
  if (Math.abs(Date.now()/1000 - Number(ts)) > 600 || sig.length !== exp.length ||
      !crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(exp))) return res.sendStatus(403);
  const d = JSON.parse(body);
  if (d.event === 'invoice.paid')   { /* mark paid (idempotent) */ }
  if (d.event === 'invoice.failed') { /* mark failed */ }
  res.send('OK');
});
import hmac, hashlib, time
from flask import Flask, request, abort
app = Flask(__name__)

@app.post("/callback")
def callback():
    ts = request.headers.get("X-Gateway-Timestamp", ""); sig = request.headers.get("X-Gateway-Signature", "")
    body = request.get_data(as_text=True)                       # RAW body
    exp = hmac.new(SECRET.encode(), f"{ts}.{body}".encode(), hashlib.sha256).hexdigest()
    if abs(time.time() - int(ts or 0)) > 600 or not hmac.compare_digest(sig, exp): abort(403)
    d = request.get_json()
    if d["event"] == "invoice.paid": pass      # mark paid (idempotent)
    if d["event"] == "invoice.failed": pass    # mark failed
    return "OK"
Never mark an order paid just because the customer landed on return_url. Only the signed webhook (or signed status API) is proof.

Statuses & errors

StatusMeaning
pendingWaiting for payment
paidMatching payment found on-chain
expiredTime ran out → pay page shows Failed, invoice.failed sent
HTTPerrorCause
401invalid_api_key / invalid_signatureWrong key, secret or message
422invalid_amount, invalid_order_id, amount_too_smallValidation
422network_not_supportedNetwork is disabled
422invalid_callback_url, callback_url_not_publicBad or private URL
503no_free_amount_slot_try_againToo many open invoices for that amount

Testing & go-live

  • Use the Live Demo to see the complete flow end-to-end.
  • Send a small real payment (1 USDT) on each network and confirm the webhook arrives (Admin → Webhooks).
  • Let an invoice expire to test invoice.failed.
  • Replay a webhook (Admin → Invoices → Resend) and confirm your handler is idempotent.
  • Serve both sites over HTTPS and keep the secret server-side.

Integration kit (PHP) & examples

Copy-paste ready files — checkout, signed webhook receiver, return page and a one-file SDK.

File
UsdtGateway.php
SDK (createInvoice, getInvoice, verifyWebhook)
Download
checkout.php
Mobile + amount → order → pay page
Download
callback.php
Signed webhook receiver (credit / fail)
Download
return.php
Result page
Download
schema.sql
orders table
Download
config.sample.php
Config
Download
node_example.js
Node.js example
Download
python_example.py
Python example
Download
curl_examples.sh
cURL
Download

⬇ Download full kit (.zip)

Add-Funds kit (dark checkout design)

Mobile + amount + method form → modern dark checkout with network picker, QR and exact amount → balance credited by signed webhook.

⬇ Download Add-Funds kit (.zip) See the checkout in the demo

FAQ

Do funds pass through you?

No. Payments go directly to the merchant's wallet address. Only public addresses are stored.

What if the customer sends a wrong amount?

The transfer appears under Unmatched in the admin panel where it can be assigned to the invoice manually.

How fast is confirmation?

TRC20: usually within a minute or two. BEP20: after ~5 block confirmations (≈ 15-30 s) plus the polling interval.

Which currencies?

USDT on TRON (TRC20) and BNB Smart Chain (BEP20).