测试环境 STAGING · 测试环境,用于验收。使用独立的测试数据,请不要填写真实客户资料。
开发者文档EN

TopUP 开放 API

第 1 版。"接口详情"里的每个字段都由自动测试和实际接口逐一核对,文档和接口不会不一致。

概览

  • 网络和币种:只支持 TRON 上的 USDT(TRC20)。金额用字符串表示,最多 6 位小数,例如 "100.5"。
  • 接口地址:https://{BASE_URL}/api/v1/,所有路径都以 "/" 结尾。不带结尾斜杠的请求会被跳转,有些 HTTP 工具在 POST 被跳转时会出错。
  • 按客户收款:你的每个客户有一个永久地址(发到账通知)。开启订单模式后,可以给客户创建订单,系统自动把到账匹配到订单(发订单匹配通知)。
  • 到账达到 19 个确认(大约 1 分钟)后才算入账,一般在付款后 2 分钟内发出回调。
  • 每一笔提币都经过人工审核。工作时间为东八区 8:00–23:00:工作时间内的申请 1 小时内处理,其余的顺延到下一个工作时间。
接口用途
POSTorders/创建订单
GETorders/查询订单
GETorders/list/订单列表
POSTorders/match/手动匹配
POSTorders/unmatch/解除匹配
POSTcustomers/新建或更新客户
GETcustomers/查询客户
GETcustomers/list/客户列表
GETcustomers/stats/客户统计
GETbalance/余额
GETledger/账本明细
GETdeposits/到账明细
POSTwithdrawals/发起提币
GETwithdrawals/查询提币
POSTwithdrawals/cancel/取消提币
POSTpayouts/batch/提交批量打款
GETpayouts/batch/查询批量打款

请求签名

每个请求都要带上三个请求头。Secret 在商户后台的"API 设置"里生成,只显示一次,请只保存在你的服务器上。

Header内容
X-TopUP-Key你的 API Key
X-TopUP-TimestampUnix 时间戳(秒),和服务器时间相差不能超过 5 分钟
X-TopUP-Signaturehex( HMAC-SHA256( Secret, 时间戳 + "\n" + 请求方法 + "\n" + 路径和查询参数 + "\n" + hex(SHA-256(请求体)) ) );GET 请求的请求体为空
Idempotency-Key每个 POST 请求都必须带上(8 到 128 位,可用字母、数字和 _ . : -,用 UUID 即可)。用同一个 Key 和同样的内容重试,会返回第一次的结果,不会重复创建(保留 24 小时)。失败的请求不占用这个 Key。

Node.js

import crypto from 'node:crypto';

const BASE = process.env.TOPUP_BASE || 'https://{BASE_URL}/api/v1/';
const KEY = process.env.TOPUP_KEY, SECRET = process.env.TOPUP_SECRET;

async function topup(method, path, body) {
  const ts = Math.floor(Date.now() / 1000).toString();
  const raw = body ? JSON.stringify(body) : '';
  const bodyHash = crypto.createHash('sha256').update(raw).digest('hex');
  const url = new URL(path, BASE);
  const toSign = [ts, method, url.pathname + url.search, bodyHash].join('\n');
  const sig = crypto.createHmac('sha256', SECRET).update(toSign).digest('hex');
  const res = await fetch(url, {
    method,
    headers: {
      'content-type': 'application/json',
      'X-TopUP-Key': KEY, 'X-TopUP-Timestamp': ts, 'X-TopUP-Signature': sig,
      ...(method === 'POST' ? { 'Idempotency-Key': crypto.randomUUID() } : {}),
    },
    body: raw || undefined,
  });
  return res.json();
}

const order = await topup('POST', 'orders/', { customer_id: 'user_88213', merchant_order_no: `ACME-${Date.now()}`, amount: '100.00' });
console.log(order.pay_url);

Python

import hashlib, hmac, json, os, time, uuid, requests

BASE = os.environ.get("TOPUP_BASE_URL", "https://{BASE_URL}")
KEY, SECRET = os.environ["TOPUP_KEY"], os.environ["TOPUP_SECRET"].encode()

def topup(method, path, body=None):
    ts = str(int(time.time()))
    raw = json.dumps(body, separators=(",", ":")) if body else ""
    body_hash = hashlib.sha256(raw.encode()).hexdigest()
    to_sign = "\n".join([ts, method, "/api/v1/" + path, body_hash])
    sig = hmac.new(SECRET, to_sign.encode(), hashlib.sha256).hexdigest()
    headers = {"content-type": "application/json", "X-TopUP-Key": KEY,
               "X-TopUP-Timestamp": ts, "X-TopUP-Signature": sig}
    if method == "POST":
        headers["Idempotency-Key"] = str(uuid.uuid4())
    return requests.request(method, BASE + "/api/v1/" + path, data=raw or None, headers=headers).json()

print(topup("GET", "balance/"))

订单收款

POST /api/v1/orders/
{
  "customer_id": "user_88213",          // required: your own ID for this customer
  "customer_name": "Lin Trading",       // optional, used only if the customer is new
  "customer_email": "lin@lintrading.example",
  "merchant_order_no": "ACME-88513",
  "amount": "100.00"
}
{
  "order_no": "ORD-20260929-0413",
  "merchant_order_no": "ACME-88513",
  "customer_id": "user_88213",
  "amount": "100.00",
  "matched": "0.00",
  "address": "TMa7yK2d9Qp4XvB8sN1cF6rH3wZ5jL0eUt",   // the customer's permanent address
  "network": "TRON",
  "token": "USDT",
  "status": "pending",
  "created_at": "2026-09-29T09:00:00.000Z",
  "expires_at": "2026-09-29T09:30:00.000Z",
  "deposits": [],
  "pay_url": "https://{BASE_URL}/pay/ORD-20260929-0413/"
}
  • customer_id 必填;新的 customer_id 会自动创建客户和永久地址。merchant_order_no 在你的账户里不能重复。
  • 过期时间和匹配阈值由平台为你的账户设置(在"API 设置"里可以看到)。创建订单需要开启订单模式,否则返回 403 order_mode_disabled。
  • 可以把 pay_url 发给付款方,也可以自己展示收款地址。
  • 如果创建时就匹配到了这个客户之前的到账,返回的状态可能已经是 completed,见"匹配规则"。

客户

POST /api/v1/customers/
{ "customer_id": "user_88213", "name": "Lin Trading", "email": "lin@lintrading.example" }

→ {
  "customer_id": "user_88213", "name": "Lin Trading", "email": "lin@lintrading.example", "remark": "",
  "address": "TXk8fQ2m9sR7ZcY1hN4vB6pW3aLd5Z3wQe",
  "total": "0.00", "count": 0, "fees": "0.00", "unmatched": "0.00",
  "last_payment_at": null, "created_at": "2026-09-11T02:10:00.000Z"
}
  • 每个客户一个永久地址,转到这个地址的钱都算这个客户的,不论有没有订单。customer_id 不能修改。
  • 低于 1 USDT 的付款不入账、不匹配、不发回调,也不会出现在你的到账明细和导出里(这类付款通常是垃圾"灰尘"转账)。
  • customers/stats/ 返回某个时间段的收款合计、笔数、手续费和未匹配金额。

匹配规则

匹配只是把到账和订单关联起来,不会改变余额;只在同一个客户内部进行,两个方向都会触发:

  • 订单在先、到账在后:到账匹配给"加上这笔后累计落在下限 L 和上限 H 之间"的未完成订单;都不满足时,匹配最早创建的未完成订单。
  • 到账在先、订单在后:从回看时间内最早的未匹配到账开始累计,达到 L 且不超过 H 时匹配,否则一笔都不匹配。
  • 状态:累计 < L 为 partial(继续等待),L ≤ 累计 ≤ H 为 completed,累计 > H 为 overpaid;过期时还没达到 L 的订单变为 expired(没有收到)或 expired_partial。
  • 过期后才到的钱记为未匹配,需要时用 orders/match/ 手动匹配。尽量不要让同一个客户同时有两个金额接近的未完成订单。

余额与账本

GET balance/ 返回 { "available": "48215.40", "frozen": "1002.00" }。账本只追加,每条记录的类型为 deposit、fee_in、freeze、unfreeze、withdraw、fee_out 之一。列表用 cursor 翻页。

提币

POST /api/v1/withdrawals/
{
  "kind": "payout",              // "payout" = to your customer, "cashout" = to your registered wallet
  "customer_id": "user_88213",   // optional, for payouts
  "to": "TXk8fQ2m9sR7ZcY1hN4vB6pW3aLd5Z3wQe",
  "amount": "1000.00",
  "merchant_ref": "PAYOUT-7781"
}

→ {
  "withdrawal_no": "WD-20260929-7F3A21", "kind": "payout", "customer_id": "user_88213",
  "to": "TXk8fQ2m9sR7ZcY1hN4vB6pW3aLd5Z3wQe", "amount": "1000.00", "fee": "2.00",   // 1002.00 is frozen
  "status": "pending", "txid": null, "reason": null, "merchant_ref": "PAYOUT-7781", "source": "api",
  "created_at": "2026-09-29T09:12:00.000Z"
}
  • API 提币需要先在"API 设置"里设置 IP 白名单;没有白名单时返回 403 ip_not_allowed。
  • 提交时冻结"金额 + 手续费",被驳回或取消时解冻。
  • 状态:pending → approved → broadcast → completed,或 rejected / cancelled / failed。每次变化都发 withdrawal.updated 回调。

回调

POST https://your-server.example/callback
X-TopUP-Timestamp: 1790665800
X-TopUP-Signature: 5f1c…

{
  "id": "evt_9f2a02",
  "type": "order.matched",       // deposit | order.matched | withdrawal.updated
  "created_at": "2026-09-29T09:10:03Z",
  "data": {
    "order_no": "ORD-20260929-0409",
    "merchant_order_no": "ACME-88509",
    "customer_id": "user_88213",
    "status": "completed",       // pending | partial | completed | overpaid | expired | expired_partial
    "amount": "500.00",
    "matched": "500.00",
    "created_at": "2026-09-29T09:05:00.000Z",
    "expires_at": "2026-09-29T09:35:00.000Z",
    "deposits": [{ "id": "1042", "txid": "a3c1…", "amount": "500.00", "matched_by": "deposit", "time": "2026-09-29T09:10:00.000Z" }],
    "manual": false
  }
}

签名:hex( HMAC-SHA256( Secret, 时间戳 + "\n" + 原始请求体 ) )。收到后请返回任意 2xx 状态码;否则我们在第一次发送之后的 1 分钟、5 分钟、30 分钟、2 小时、6 小时、12 小时、24 小时重试,然后停止,你可以在商户后台手动重发。同一个事件可能收到不止一次,请按 id 去重。

import crypto from 'node:crypto';

// Verify a TopUP callback. rawBody must be the exact request body you received,
// not an object you parsed and serialised again.
export function verifyCallback(secret, timestamp, signature, rawBody) {
  const expected = crypto.createHmac('sha256', secret).update(`${timestamp}\n${rawBody}`).digest('hex');
  const a = Buffer.from(expected), b = Buffer.from(String(signature || ''));
  const fresh = Math.abs(Date.now() / 1000 - Number(timestamp)) <= 300;
  return fresh && a.length === b.length && crypto.timingSafeEqual(a, b);
}

// Express example:
// app.post('/callback', express.raw({ type: 'application/json' }), (req, res) => {
//   if (!verifyCallback(SECRET, req.get('X-TopUP-Timestamp'), req.get('X-TopUP-Signature'), req.body)) return res.sendStatus(401);
//   const event = JSON.parse(req.body); // the same event may arrive more than once: deduplicate by event.id
//   res.sendStatus(200);
// });

回调内容

字段类型说明
id字符串事件编号,请按它去重
type字符串deposit、order.matched、withdrawal.updated 之一
created_at时间事件产生时间
dataobject事件内容,见下表

deposit

客户地址收到 1 USDT 及以上的付款并入账。data 的字段:

字段类型说明
customer_id字符串你的客户标识
chain字符串付款所在的链:eth、bsc 或 tron
address字符串收款地址
txid字符串链上交易哈希
amount金额到账金额
fee金额收款手续费
credited金额计入余额的金额
order_no字符串匹配到的订单(可能为 null)
time时间链上付款时间

order.matched

订单因为匹配或解除匹配发生变化。data 的字段:

字段类型说明
order_no字符串TopUP 生成的订单号
merchant_order_no字符串你的订单号
customer_id字符串你的客户标识
amount金额订单金额
matched金额已经匹配到这个订单的到账合计
status字符串pending、partial、completed、overpaid、expired、expired_partial 之一(见"匹配规则")
created_at时间创建时间
expires_at时间过期时间
deposits数组匹配到这个订单的到账(OrderDeposit 对象)
manual布尔值手动匹配或解除匹配时为 true

withdrawal.updated

提币创建或状态变化。data 的字段:

字段类型说明
withdrawal_no字符串提币单号
kind字符串payout(付给你的客户)或 cashout(提到你登记的钱包)
chain字符串付款所在的链:eth、bsc 或 tron
batch_no字符串所属的批量打款批次号;单笔提币为 null(可能为 null)
customer_id字符串代付对应的客户(可能为 null)
to字符串收款地址(所在链的地址)
amount金额提币金额
fee金额提币手续费(提交时冻结"金额 + 手续费")
status字符串pending、approved、broadcast、completed、rejected、cancelled、failed 之一
txid字符串广播后的链上交易哈希(可能为 null)
reason字符串驳回或失败的原因(可能为 null)
merchant_ref字符串你的备注编号(可能为 null)
source字符串api(开放 API)或 web(商户后台)
created_at时间创建时间

接口详情

金额是 USDT 的字符串(例如 "100.50"),时间是 UTC 的 ISO 8601 格式。列表接口返回 { items, next_cursor }:把 next_cursor 作为 cursor 传入,取下一页。

OrderDeposit

订单里 deposits 数组的每一项。

字段类型说明
id字符串到账编号
txid字符串链上交易哈希
amount金额到账金额
matched_by字符串匹配方式:deposit(先建单后到账)、order(先到账后建单)、manual(手动匹配)
time时间链上付款时间

POST/api/v1/orders/ · 创建订单

请求体(JSON)

字段类型必填说明
customer_id字符串是你给客户的标识,1 到 128 位,可用字母、数字和 _ . @ -;新的标识会自动创建客户(不带地址:地址在客户发起充值时按链生成)
merchant_order_no字符串是你的订单号,1 到 64 位,可用字母、数字、_ 和 -;在你的账户里不能重复
amount金额是订单金额(USDT),最多 6 位小数,例如 "100.5"
customer_name字符串否只在新建客户时使用
customer_email字符串否只在新建客户时使用
chain字符串否eth 或 bsc:付款人只能用这条链付款,创建订单时生成客户在这条链的地址。不传时由付款人在付款页选择(推荐),选了才生成那条链的地址

返回

字段类型说明
order_no字符串TopUP 生成的订单号
merchant_order_no字符串你的订单号
customer_id字符串你的客户标识
amount金额订单金额
matched金额已经匹配到这个订单的到账合计
status字符串pending、partial、completed、overpaid、expired、expired_partial 之一(见"匹配规则")
created_at时间创建时间
expires_at时间过期时间
deposits数组匹配到这个订单的到账(OrderDeposit 对象)
address字符串付款地址:指定了链时是这条链的地址;没有指定时为 null(付款人在付款页选链)(可能为 null)
network字符串address 所在的网络:ETH、BSC 或 TRON;没有指定链时为 null(可能为 null)
chain字符串创建订单时指定的链(eth 或 bsc);null 表示付款人在付款页自己选(可能为 null)
addresses数组这个客户已经生成过的地址:[{ chain, address }](指定了链时只给这条链)。ETH 和 BSC 是同一串地址,只按选定的网络转账(可能为 null)
token字符串固定为 USDT
pay_url字符串这个订单的付款页面

可能的错误:order_mode_disabled、duplicate_merchant_order_no、chain_not_enabled、invalid_param

GET/api/v1/orders/ · 查询订单

查询参数

字段类型必填说明
order_no字符串否订单号(和 merchant_order_no 二选一)
merchant_order_no字符串否你的订单号

返回

字段类型说明
order_no字符串TopUP 生成的订单号
merchant_order_no字符串你的订单号
customer_id字符串你的客户标识
amount金额订单金额
matched金额已经匹配到这个订单的到账合计
status字符串pending、partial、completed、overpaid、expired、expired_partial 之一(见"匹配规则")
created_at时间创建时间
expires_at时间过期时间
deposits数组匹配到这个订单的到账(OrderDeposit 对象)
address字符串付款地址:指定了链时是这条链的地址;没有指定时为 null(付款人在付款页选链)(可能为 null)
network字符串address 所在的网络:ETH、BSC 或 TRON;没有指定链时为 null(可能为 null)
chain字符串创建订单时指定的链(eth 或 bsc);null 表示付款人在付款页自己选(可能为 null)
addresses数组这个客户已经生成过的地址:[{ chain, address }](指定了链时只给这条链)。ETH 和 BSC 是同一串地址,只按选定的网络转账(可能为 null)
token字符串固定为 USDT
pay_url字符串这个订单的付款页面

可能的错误:not_found

GET/api/v1/orders/list/ · 订单列表

查询参数

字段类型必填说明
status字符串否按状态筛选
customer_id字符串否按客户筛选
cursor字符串否上一页返回的 next_cursor
limit整数否每页条数,1 到 100,默认 50

返回:{ items, next_cursor },每一项的字段:

字段类型说明
order_no字符串订单号
merchant_order_no字符串你的订单号
customer_id字符串你的客户标识
amount金额订单金额
matched金额已匹配合计
status字符串订单状态
created_at时间创建时间
expires_at时间过期时间

POST/api/v1/orders/match/ · 手动匹配

只改变到账和订单的关联,不改变余额;会发送 order.matched 回调(manual 为 true)。

请求体(JSON)

字段类型必填说明
order_no字符串是订单号
deposit_id字符串是到账编号(来自 deposits/;同一个客户、还没有匹配)

返回

字段类型说明
order_no字符串TopUP 生成的订单号
merchant_order_no字符串你的订单号
customer_id字符串你的客户标识
amount金额订单金额
matched金额已经匹配到这个订单的到账合计
status字符串pending、partial、completed、overpaid、expired、expired_partial 之一(见"匹配规则")
created_at时间创建时间
expires_at时间过期时间
deposits数组匹配到这个订单的到账(OrderDeposit 对象)

可能的错误:not_found、cannot_match

POST/api/v1/orders/unmatch/ · 解除匹配

请求体(JSON)

字段类型必填说明
order_no字符串是订单号
deposit_id字符串是当前匹配在这个订单上的到账编号

返回

字段类型说明
order_no字符串TopUP 生成的订单号
merchant_order_no字符串你的订单号
customer_id字符串你的客户标识
amount金额订单金额
matched金额已经匹配到这个订单的到账合计
status字符串pending、partial、completed、overpaid、expired、expired_partial 之一(见"匹配规则")
created_at时间创建时间
expires_at时间过期时间
deposits数组匹配到这个订单的到账(OrderDeposit 对象)

可能的错误:not_found、not_matched

POST/api/v1/customers/ · 新建或更新客户

没有传的字段保持不变;这里不生成地址:每条链的地址在客户第一次在这条链充值时生成,之后不会改变。

请求体(JSON)

字段类型必填说明
customer_id字符串是你给客户的标识(规则同"创建订单"),之后不能修改
name字符串否名称,最多 200 个字符
email字符串否邮箱
remark字符串否备注,最多 500 个字符

返回

字段类型说明
customer_id字符串你的客户标识
name字符串名称
email字符串邮箱(加密保存)
remark字符串备注
address字符串永久收款地址(TRON,旧字段;只有原来就有 TRON 地址的老客户才有,其他为 null;请改用 addresses)(可能为 null)
addresses数组每条链的永久收款地址:[{ chain, address }],chain 是 eth、bsc 或 tron。在客户发起充值时按链生成(订单指定了链,或付款人在付款页选了链),新客户为空;ETH 和 BSC 是同一串地址
total金额累计入账的到账金额
count整数入账的到账笔数
fees金额累计收款手续费
unmatched金额已入账但没有匹配订单的金额
last_payment_at时间最后一次付款时间(可能为 null)
created_at时间创建时间

可能的错误:invalid_param

GET/api/v1/customers/ · 查询客户

查询参数

字段类型必填说明
customer_id字符串是你的客户标识

返回

字段类型说明
customer_id字符串你的客户标识
name字符串名称
email字符串邮箱(加密保存)
remark字符串备注
address字符串永久收款地址(TRON,旧字段;只有原来就有 TRON 地址的老客户才有,其他为 null;请改用 addresses)(可能为 null)
addresses数组每条链的永久收款地址:[{ chain, address }],chain 是 eth、bsc 或 tron。在客户发起充值时按链生成(订单指定了链,或付款人在付款页选了链),新客户为空;ETH 和 BSC 是同一串地址
total金额累计入账的到账金额
count整数入账的到账笔数
fees金额累计收款手续费
unmatched金额已入账但没有匹配订单的金额
last_payment_at时间最后一次付款时间(可能为 null)
created_at时间创建时间

可能的错误:not_found

GET/api/v1/customers/list/ · 客户列表

查询参数

字段类型必填说明
q字符串否按客户标识、名称或邮箱搜索(部分匹配,不区分大小写),或按地址精确搜索
cursor字符串否上一页返回的 next_cursor
limit整数否每页条数,1 到 100,默认 50

返回:{ items, next_cursor },每一项的字段:

字段类型说明
customer_id字符串你的客户标识
name字符串名称
email字符串邮箱(加密保存)
remark字符串备注
address字符串永久收款地址(TRON,旧字段;只有原来就有 TRON 地址的老客户才有,其他为 null;请改用 addresses)(可能为 null)
addresses数组每条链的永久收款地址:[{ chain, address }],chain 是 eth、bsc 或 tron。在客户发起充值时按链生成(订单指定了链,或付款人在付款页选了链),新客户为空;ETH 和 BSC 是同一串地址
total金额累计入账的到账金额
count整数入账的到账笔数
fees金额累计收款手续费
unmatched金额已入账但没有匹配订单的金额
last_payment_at时间最后一次付款时间(可能为 null)
created_at时间创建时间

GET/api/v1/customers/stats/ · 客户统计

查询参数

字段类型必填说明
customer_id字符串是你的客户标识
from时间否开始时间(ISO 8601),默认从最早开始
to时间否结束时间(ISO 8601),默认到现在

返回

字段类型说明
customer_id字符串你的客户标识
from时间统计开始时间
to时间统计结束时间
total金额期间入账的到账金额
count整数入账笔数
fees金额收款手续费
unmatched金额没有匹配订单的金额
last_payment_at时间期间最后一次付款时间(可能为 null)
payouts金额已完成的给这个客户的代付金额
payout_count整数已完成的代付笔数

可能的错误:not_found、invalid_param

GET/api/v1/balance/ · 余额

返回

字段类型说明
available金额可用余额
frozen金额提币中冻结的金额
currency字符串固定为 USDT

GET/api/v1/ledger/ · 账本明细

查询参数

字段类型必填说明
customer_id字符串否按客户筛选
cursor字符串否上一页返回的 next_cursor
limit整数否每页条数,1 到 100,默认 50

返回:{ items, next_cursor },每一项的字段:

字段类型说明
id字符串记录编号,也用于翻页
type字符串deposit、fee_in、freeze、unfreeze、withdraw、fee_out 之一
amount金额变动金额:正数增加,负数减少(withdraw、fee_out 变动的是冻结余额)
available_after金额这条记录之后的可用余额
frozen_after金额这条记录之后的冻结余额
ref字符串关联的到账编号或提币单号
customer_id字符串关联的客户(可能为 null)
created_at时间记录时间

GET/api/v1/deposits/ · 到账明细

查询参数

字段类型必填说明
customer_id字符串否按客户筛选
matched字符串否"false" 表示已入账但没有匹配订单;"true" 表示已匹配
cursor字符串否上一页返回的 next_cursor
limit整数否每页条数,1 到 100,默认 50

返回:{ items, next_cursor },每一项的字段:

字段类型说明
id字符串到账编号(手动匹配时使用)
customer_id字符串你的客户标识
chain字符串付款所在的链:eth、bsc 或 tron
address字符串收款地址
txid字符串链上交易哈希
amount金额到账金额
fee金额收款手续费(最多等于到账金额)
credited金额计入余额的金额(到账金额减手续费)
result字符串固定为 credited。低于 1 USDT 的付款不入账,也不会列出
order_no字符串匹配到的订单(可能为 null)
matched_by字符串deposit、order、manual 之一(可能为 null)
time时间链上付款时间

POST/api/v1/withdrawals/ · 发起提币

需要先设置 IP 白名单;提交后立即冻结"金额 + 手续费";每一笔都经过人工审核。

请求体(JSON)

字段类型必填说明
kind字符串是payout(付给你的客户)或 cashout(提到开户时登记的钱包)
chain字符串否eth、bsc 或 tron(不传是 tron)
to字符串是收款地址:以太坊、BSC 是 0x 地址(大小写混合的必须校验和正确),TRON 是 T 开头的地址;cashout 必须是这条链上登记过的钱包
amount金额是金额(USDT),最多 6 位小数
customer_id字符串否代付时填写收款的客户
merchant_ref字符串否你的备注编号,最多 64 个字符

返回

字段类型说明
withdrawal_no字符串提币单号
kind字符串payout(付给你的客户)或 cashout(提到你登记的钱包)
chain字符串付款所在的链:eth、bsc 或 tron
batch_no字符串所属的批量打款批次号;单笔提币为 null(可能为 null)
customer_id字符串代付对应的客户(可能为 null)
to字符串收款地址(所在链的地址)
amount金额提币金额
fee金额提币手续费(提交时冻结"金额 + 手续费")
status字符串pending、approved、broadcast、completed、rejected、cancelled、failed 之一
txid字符串广播后的链上交易哈希(可能为 null)
reason字符串驳回或失败的原因(可能为 null)
merchant_ref字符串你的备注编号(可能为 null)
source字符串api(开放 API)或 web(商户后台)
created_at时间创建时间

可能的错误:ip_not_allowed、invalid_address、address_not_registered、insufficient_balance、invalid_param

GET/api/v1/withdrawals/ · 查询提币

查询参数

字段类型必填说明
withdrawal_no字符串是提币单号

返回

字段类型说明
withdrawal_no字符串提币单号
kind字符串payout(付给你的客户)或 cashout(提到你登记的钱包)
chain字符串付款所在的链:eth、bsc 或 tron
batch_no字符串所属的批量打款批次号;单笔提币为 null(可能为 null)
customer_id字符串代付对应的客户(可能为 null)
to字符串收款地址(所在链的地址)
amount金额提币金额
fee金额提币手续费(提交时冻结"金额 + 手续费")
status字符串pending、approved、broadcast、completed、rejected、cancelled、failed 之一
txid字符串广播后的链上交易哈希(可能为 null)
reason字符串驳回或失败的原因(可能为 null)
merchant_ref字符串你的备注编号(可能为 null)
source字符串api(开放 API)或 web(商户后台)
created_at时间创建时间

可能的错误:not_found

POST/api/v1/withdrawals/cancel/ · 取消提币

请求体(JSON)

字段类型必填说明
withdrawal_no字符串是提币单号;只能取消待审核(pending)的提币。批量打款里的单不能单笔取消,只能整批取消还没审核的部分

返回

字段类型说明
withdrawal_no字符串提币单号
kind字符串payout(付给你的客户)或 cashout(提到你登记的钱包)
chain字符串付款所在的链:eth、bsc 或 tron
batch_no字符串所属的批量打款批次号;单笔提币为 null(可能为 null)
customer_id字符串代付对应的客户(可能为 null)
to字符串收款地址(所在链的地址)
amount金额提币金额
fee金额提币手续费(提交时冻结"金额 + 手续费")
status字符串pending、approved、broadcast、completed、rejected、cancelled、failed 之一
txid字符串广播后的链上交易哈希(可能为 null)
reason字符串驳回或失败的原因(可能为 null)
merchant_ref字符串你的备注编号(可能为 null)
source字符串api(开放 API)或 web(商户后台)
created_at时间创建时间

可能的错误:not_found、invalid_state、batch_item_cancel

POST/api/v1/payouts/batch/ · 提交批量打款

需要先设置 IP 白名单。有一笔不对整个请求返回 422 invalid_rows,error.rows 列出 [{ index, line, code, errors }](index 从 0 起,line = index + 1;code 是这一笔的第一个问题,errors 列出全部问题),不冻结任何金额;全部没问题时一次冻结每笔的"金额 + 手续费",每一笔都经过人工审核。网络费不另收。这个接口的请求体上限是 256 KB。

请求体(JSON)

字段类型必填说明
items数组是最多 500 笔:[{ chain, to, amount, customer_id?, merchant_ref? }](chain 是 eth、bsc 或 tron;amount 是 USDT,最多 6 位小数)

返回

字段类型说明
batch_no字符串批次号
source字符串api(开放 API)或 web(商户后台上传表格)
status字符串pending(还有没审核的)、approved、partially_rejected(部分被驳回)、rejected、completed、cancelled 之一
count整数收下的笔数
total金额金额合计(不含手续费)
created_at时间创建时间
items数组逐笔:[{ withdrawal_no, chain, to, amount, fee, status, txid, reason, customer_id, merchant_ref }],按提交顺序
serviceobject处理时段(东八区 8:00–23:00):{ open },不在时段内另给 next_open_at(下一个 8:00)

可能的错误:ip_not_allowed、too_many_items、invalid_rows、insufficient_balance、invalid_param

GET/api/v1/payouts/batch/ · 查询批量打款

查询参数

字段类型必填说明
batch_no字符串是批次号

返回

字段类型说明
batch_no字符串批次号
source字符串api(开放 API)或 web(商户后台上传表格)
status字符串pending(还有没审核的)、approved、partially_rejected(部分被驳回)、rejected、completed、cancelled 之一
count整数收下的笔数
total金额金额合计(不含手续费)
created_at时间创建时间
items数组逐笔:[{ withdrawal_no, chain, to, amount, fee, status, txid, reason, customer_id, merchant_ref }],按提交顺序

可能的错误:not_found

错误码

出错时返回 { "error": { "code": "…", "message": "…", "field": "…" } }。

HTTPcode含义
400idempotency_key_requiredPOST 请求没有带 Idempotency-Key(8 到 128 位,可用字母、数字和 _ . : -)
400invalid_param请求体不是合法的 JSON
401invalid_signature没有签名、签名错误或 API Key 不存在
401timestamp_expired时间戳和服务器相差超过 5 分钟
403merchant_disabled账户已停用
403order_mode_disabled你的账户没有开启订单模式
403ip_not_allowed提币请求不是来自白名单 IP(或没有设置白名单)
404not_found接口不存在,或你的账户里没有这条记录
409duplicate_merchant_order_no商户订单号已经存在
409idempotency_conflict同一个 Idempotency-Key 用在了不同的请求上
409request_in_progress同一个 Idempotency-Key 的请求还在处理中,请稍后重试
409cannot_match这笔到账不能匹配到这个订单(不是同一个客户、已经匹配过、没有入账或订单已关闭)
409not_matched这笔到账没有匹配在这个订单上
409chain_not_enabled这条链还没有开放分配新地址(TRON 在后续版本开放)
409invalid_state当前状态不允许这个操作(例如取消已经不是待审核的提币)
409batch_item_cancel这笔属于批量打款,不能单笔取消,请整批取消(只取消还没审核的部分)
413too_large请求体超过 32 KB(POST payouts/batch/ 是 256 KB)
422invalid_param参数缺失或格式错误,见 error.field
422invalid_address不是这条链的合法地址
422too_many_items一批超过 500 笔
422invalid_rows批量打款里有不对的行,见 error.rows = [{ index, line, code, errors }]
422address_not_registeredcashout 的地址不是登记过的钱包
422insufficient_balance金额加手续费超过了可用余额
429rate_limited每秒超过 20 个请求,请稍后重试
503wallet_not_initialized服务还没有准备好
500internal_error服务器内部错误,可以用同一个 Idempotency-Key 重试

沙箱

暂时不提供沙箱。试用阶段请在正式环境用小金额(例如 1 USDT)联调。