Public integration guide. API base URL: https://api.toknex.space. Confirm network settings and one-time fees in your merchant account.

Integration guide

This guide shows how to add USDT payments to an existing website or app. The examples use plain HTTPS + JSON, so they work in any language; ready-made clients are available for PHP, Node.js and Python.

How the money flows

Your customer's wallet ──USDT──► customer's personal deposit address ──(automatic)──► gateway treasury
                                          │
                                          ├─ deposit.detected   (seen on chain)
                                          ├─ deposit.confirmed  (account-configured confirmations confirmations → credit your customer)
                                          └─ deposit.collected  (swept to the treasury)
Your merchant balance += amount − platform fee   →   Settlements → your payout wallet

Key ideas:

Step 1: Configure your server

Store two secrets in your server environment (never in code or client apps):

GATEWAY_BASE_URL=https://api.toknex.space
GATEWAY_API_KEY=sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
GATEWAY_WEBHOOK_SECRET=whsec_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Every request sends:

Authorization: Bearer $GATEWAY_API_KEY
Content-Type: application/json

Step 2: Create a customer and their deposit address

Call this when a customer registers, or the first time they open your "Pay with USDT" page. Use your own customer id as external_id: the call is safe to repeat, and returns the same customer and address again.

curl -X POST https://api.toknex.space/api/v1/users \
  -H "Authorization: Bearer $GATEWAY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: create-user-10025" \
  -d '{"external_id":"10025","name":"Asha Patel","email":"[email protected]"}'
{
  "id": 4821,
  "external_id": "10025",
  "name": "Asha Patel",
  "email": "[email protected]",
  "status": "ACTIVE",
  "created_at": "2026-10-25T09:00:00+00:00",
  "deposit_wallet": {
    "user_id": 4821,
    "external_id": "10025",
    "network": "BSC",
    "network_name": "BNB Smart Chain",
    "chain_id": 56,
    "token": "USDT",
    "token_standard": "BEP-20",
    "token_contract": "0x55d398326f99059fF775485246999027B3197955",
    "deposit_address": "0x3fA1c6d1B0F5f1E2d6C4b9A8e7D3c2B1a0F9e8D7",
    "deployed": false,
    "status": "ACTIVE",
    "minimum_deposit": "account-configured min deposit",
    "required_confirmations": account-configured confirmations,
    "qr_payload": "0x3fA1c6d1B0F5f1E2d6C4b9A8e7D3c2B1a0F9e8D7"
  }
}

Save id (our user id) and deposit_wallet.deposit_address with your customer record. Everywhere in the API, {id} can be either our numeric id or your external_id.

Note: "deployed": false is normal. The address is a deterministic smart-contract address that can receive USDT immediately; its contract is created automatically when funds are first collected.

Step 3: Show the payment instructions

You have two options.

Option A: Your own page (full control)

Show the customer:

Suggested copy:

Send USDT (BEP-20) to your personal address below. Your balance updates automatically after account-configured confirmations network confirmations, usually within a minute. Only send USDT on BNB Smart Chain.

Option B: Hosted deposit page (no front-end work)

Create a one-time link and redirect the customer to it:

curl -X POST https://api.toknex.space/api/v1/users/10025/portal-link \
  -H "Authorization: Bearer $GATEWAY_API_KEY"
{ "url": "https://api.toknex.space/portal/link/2f8Kq…", "expires_at": "2026-10-25T09:30:00+00:00" }

The link works once and expires after 30 minutes. Create a fresh one each time the customer clicks "Pay with USDT". The hosted page shows the address, QR code, network warnings and live deposit status.

Step 4: Receive webhooks and credit the customer

When a deposit reaches account-configured confirmations confirmations we POST a deposit.confirmed event to your webhook URL:

{
  "id": "evt_7731",
  "type": "deposit.confirmed",
  "created": 1792915965,
  "data": {
    "id": 9177,
    "user_id": 4821,
    "external_id": "10025",
    "deposit_address": "0x3fa1…",
    "from_address": "0x8b2c…",
    "tx_hash": "0x5d…",
    "amount": "500.000000000000000000",
    "amount_raw": "500000000000000000000",
    "status": "CONFIRMED",
    "credited": true,
    "below_minimum": false
  }
}

Your handler should:

  1. Verify the signature (see Webhooks). Reject anything that fails.
  2. De-duplicate on data.id (the deposit id). The same deposit can be delivered more than once.
  3. If type is deposit.confirmed and data.credited is true, credit data.amount to the customer identified by data.external_id, inside a database transaction.
  4. Respond HTTP 200 within 10 seconds. Do slow work (emails, fulfilment) after responding, or in a queue.

Minimal PHP handler:

$raw = file_get_contents('php://input');
if (!preg_match('/t=(\d+),v1=([0-9a-f]{64})/', $_SERVER['HTTP_X_GATEWAY_SIGNATURE'] ?? '', $m)
    || abs(time() - (int) $m[1]) > 300
    || !hash_equals(hash_hmac('sha256', $m[1] . '.' . $raw, getenv('GATEWAY_WEBHOOK_SECRET')), $m[2])) {
    http_response_code(401); exit;
}
$event = json_decode($raw, true);
if ($event['type'] === 'deposit.confirmed' && $event['data']['credited']) {
    $db->beginTransaction();
    // INSERT ... payments (gateway_deposit_id UNIQUE) -> skip if it already exists
    // UPDATE customers SET balance = balance + :amount WHERE id = :external_id
    $db->commit();
}
http_response_code(200);

Full, production-ready receivers: PHP · Node.js · Python.

Important: use string or decimal types for amounts (DECIMAL(36,18) in SQL, Decimal in Python, a big-number library in JavaScript). Never parse them into floating-point numbers.

Webhooks can be delayed if your server is down. Run a job every few minutes that pulls recent deposits and processes any you have not seen:

curl "https://api.toknex.space/api/v1/deposits?status=CONFIRMED&since_id=9100&limit=100" \
  -H "Authorization: Bearer $GATEWAY_API_KEY"

Process each item exactly like a webhook (the same de-duplication on id), and store the highest id you have processed as the next since_id.

Order-based checkout

The address identifies a customer, not an order. For "pay this invoice" flows:

  1. Create or fetch the customer's address as above.
  2. Show the order amount and the address.
  3. When deposit.confirmed arrives, add the amount to the customer's balance in your system. If the balance covers an open order, mark the order paid and deduct it.
  4. Overpayments stay on the customer's balance for future orders; for underpayments, show the remaining amount.

This approach is robust when customers pay in several transfers, pay slightly too much because of exchange withdrawal fees, or pay late.

Deposit statuses

StatusMeaningWhat you do
DETECTEDTransfer seen on chain, 0–1 confirmationsShow "payment detected"
CONFIRMINGWaiting for account-configured confirmations confirmationsShow progress
CONFIRMEDFinal: credited to your balanceCredit the customer
COLLECTION_PENDING / COLLECTION_SUBMITTEDBeing swept to the treasuryNothing
COLLECTEDSwept to the treasuryNothing
REORGEDThe block was replaced; we re-check itWait; it returns to DETECTED if re-mined
FAILEDCould not be verifiedContact support if unexpected

Checklist before launch

See the Testing & go-live checklist.