Create Exclusive Wallet

Create a dedicated deposit address for a bindKey; subsequent deposits to this address remain associated with that binding.

If notifyUrl is provided, future auto-created recharge orders for this exclusive address will callback to that URL first. This is useful when each site or app receives its own member recharge notifications.

POST/openapi/payin/exclusive-bindings

Request Headers

FieldTypeRequiredDescription
x-api-keystringYesMerchant API Key. Use the value beginning with mch_ from the merchant API settings page.
x-merchant-uidstringYesMerchant UID.
x-timestampstringYes13-digit millisecond timestamp. The default allowed clock drift is 5 minutes.
x-noncestringYesUnique random string for each request, up to 128 characters. Reuse is rejected.
x-signaturestringYesHex signature generated with HMAC-SHA256. The payload contains Merchant UID, timestamp, nonce, method, path, canonical query, and canonical body.

Request Parameters

FieldTypeRequiredDescription
chainCodestringYesChain code. Supported values: TRON / BSC / SOL.
tokenSymbolstringYesToken symbol.
bindKeystringYesUnique binding key on the merchant side. Maximum 128 characters.
labelstringNoBinding remark. Maximum 100 characters.
notifyUrlstringNoIndependent callback URL for this exclusive address. Auto-created orders from future deposits will callback here first. Maximum 500 characters; private, loopback and unsafe destinations are forbidden.

Request Example

{
  "chainCode": "TRON",
  "tokenSymbol": "USDT",
  "bindKey": "USER_90001",
  "label": "VIP User 90001",
  "notifyUrl": "https://merchant.example.com/api/uugate/member-topup-notify"
}

Response Fields

FieldTypeRequiredDescription
bindingIdnumberYesBinding record ID.
chainCodestringYesChain code.
tokenSymbolstringYesToken symbol.
bindKeystringYesBinding key.
addressIdnumberYesAddress ID.
addressstringYesExclusive receiving address.
addressTypestringYesAlways exclusive.
notifyUrlstring | nullYesExclusive callback URL used by this binding.
statusstringYesBinding status.

Response Example

{
  "bindingId": 70031,
  "chainCode": "TRON",
  "tokenSymbol": "USDT",
  "bindKey": "USER_90001",
  "addressId": 31088,
  "address": "TQ3sCY8k9h7G9UsApY3JPt5VDpNKr2kJ1E",
  "addressType": "exclusive",
  "notifyUrl": "https://merchant.example.com/api/uugate/member-topup-notify",
  "status": "active"
}

Code Examples

Run: save Java as UUGateExample.java (UUGateCallback.java for callbacks) and use java filename; PHP: php example.php; Go: go run example.go; Node.js: node example.mjs. Callback verifiers read the raw body from standard input.

import { createHmac, randomBytes } from 'node:crypto';

function required(name) {
  const value = process.env[name]?.trim();
  if (!value) throw new Error(name + ' is required');
  return value;
}
const uid = required("UUGATE_MERCHANT_UID"), key = required("UUGATE_API_KEY");
const timestamp = String(Date.now()), nonce = randomBytes(16).toString("hex");
const method = 'POST', path = '/openapi/payin/exclusive-bindings';
const canonicalQuery = '', canonicalBody = "{\"bindKey\":\"USER_90001\",\"chainCode\":\"TRON\",\"label\":\"VIP User 90001\",\"notifyUrl\":\"https://merchant.example.com/api/uugate/member-topup-notify\",\"tokenSymbol\":\"USDT\"}";
const payload = [uid, timestamp, nonce, method, path, canonicalQuery, canonicalBody].join('\n');
const signature = createHmac('sha256', key).update(payload, 'utf8').digest('hex');
const base = (process.env.UUGATE_BASE_URL || 'https://api.uugate.com').replace(/\/+$/, '');
const response = await fetch(base + path, {
  method, redirect: 'error', signal: AbortSignal.timeout(30000),
  headers: { 'Content-Type': 'application/json', 'x-api-key': key, 'x-merchant-uid': uid,
    'x-timestamp': timestamp, 'x-nonce': nonce, 'x-signature': signature },
  ...(canonicalBody ? { body: canonicalBody } : {}),
});
const raw = await response.text();
if (!response.ok) throw new Error('HTTP ' + response.status + ': ' + (raw || 'empty response body'));
JSON.parse(raw);
console.log(raw);

Notes

  • If the same bindKey is created again, the platform idempotently returns the existing binding and address, which works well for a get-or-create flow.
  • For member recharge, pass notifyUrl at binding time so deposits of any amount to the exclusive address callback directly to the corresponding site or app.
  • All four languages use the same endpoint paths, parameters and response contract. Credentials come from UUGATE_MERCHANT_UID and UUGATE_API_KEY; UUGATE_BASE_URL defaults to https://api.uugate.com.
  • canonicalBody is compact JSON with sorted field names. After changing parameters, sort object keys recursively, preserve array order and use UTF-8 without extra slash or Unicode escaping. Amounts are strings; booleans are true / false.
  • Successful responses return the business object directly, without a code / data wrapper. Check HTTP status before processing the body. Business errors return code, message, data and requestId; security denials may only return HTTP 401 / 403 with an empty body.
  • After a timeout or HTTP 5xx, query the order before retrying creation or submission. Generate a new timestamp, nonce and signature for every new request.