---
url: /en/reference/withdraws.md
---
# Withdrawals

Withdrawals: create and query

Status: REQUESTING (pending review) → PENDING (approved, signing / broadcasting) → BROADCASTED (broadcast, confirming) → CONFIRMED; other final states are REJECTED (review rejected) and FAILED. Each transition into BROADCASTED / CONFIRMED / FAILED / REJECTED emits an event (withdraw.broadcasted / confirmed / failed / rejected) whose data equals GET /v1/withdraws/{withdraw_id}.

## List withdrawals

```http
GET /v1/withdraws
```

API key scope: `read`

List withdrawals: ordered by withdraw_id descending, cursor pagination; look up your own order number with biz_id

**Parameters**

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `user_id` | query | string | no | User ID: optional |
| `biz_id` | query | string | no | Merchant order number: optional |
| `chain_code` | query | string | no | Chain code: optional |
| `token_code` | query | string | no | Token code: optional |
| `status` | query | string | no | Status: optional |
| `tx_hash` | query | string | no | Transaction hash: optional |
| `start_time` | query | string | no | Start time: by creation time, Unix milliseconds, inclusive |
| `end_time` | query | string | no | End time: by creation time, Unix milliseconds, inclusive |
| `page_size` | query | integer | no | Page size: default 20, max 100 (larger values are treated as 100) |
| `page_token` | query | string | no | Page token: the next_page_token from the previous page; omit for the first page. Opaque — pass it back unchanged |

**Response** (200, `WithdrawPage`)

| Field | Type | Description |
|---|---|---|
| `next_page_token` | string | page_token for the next page; empty means no more pages |
| `withdraws` | object (Withdraw)\[] |  |
| `withdraws[].amount` | string | Amount (main unit) actually sent on-chain |
| `withdraws[].amount_raw` | string | Amount (integer, smallest unit) |
| `withdraws[].biz_id` | string | Merchant order number |
| `withdraws[].block_number` | string |  |
| `withdraws[].broadcast_time` | string | Broadcast time (Unix milliseconds); 0 if not broadcast |
| `withdraws[].chain_code` | string |  |
| `withdraws[].confirm_time` | string | Confirmation time (Unix milliseconds); 0 if not confirmed |
| `withdraws[].confirmations` | integer |  |
| `withdraws[].create_time` | string | Creation time (Unix milliseconds) |
| `withdraws[].decimals` | integer |  |
| `withdraws[].fee` | string | Fee (main unit), charged off-chain |
| `withdraws[].from_address` | string | Outbound hot wallet address: set after approval; empty for in-pool transfers |
| `withdraws[].internal` | boolean | Whether it is an in-pool transfer (both sides are pooled merchants; not on-chain, instant) |
| `withdraws[].reason` | string | Failure or rejection reason (set when FAILED / REJECTED) |
| `withdraws[].status` | string | REQUESTING / PENDING / BROADCASTED / CONFIRMED / REJECTED / FAILED |
| `withdraws[].to_address` | string |  |
| `withdraws[].token_code` | string |  |
| `withdraws[].tx_hash` | string | On-chain transaction hash: set after signing; empty for in-pool transfers |
| `withdraws[].user_id` | string |  |
| `withdraws[].withdraw_id` | string |  |

Response example:

```json
{
  "next_page_token": "",
  "withdraws": [
    {
      "amount": "12.5",
      "amount_raw": "12500000",
      "biz_id": "order-20261109-0001",
      "block_number": "77123456",
      "broadcast_time": "1762650000000",
      "chain_code": "TRON",
      "confirm_time": "1762650000000",
      "confirmations": 0,
      "create_time": "1762650000000",
      "decimals": 6,
      "fee": "",
      "from_address": "TJRabPrwbZy45sbavfcjinPJC18kjpRTv8",
      "internal": false,
      "reason": "AMOUNT_BELOW_MIN",
      "status": "REQUESTING",
      "to_address": "TXYZopYRdj2D9XRtbG411XZZ3kM5VkAeBf",
      "token_code": "USDT",
      "tx_hash": "3f1c0e…（交易哈希）",
      "user_id": "u_10001",
      "withdraw_id": "1987654321098753"
    }
  ]
}
```

On failure the unified error body is returned; see [Errors](/en/guide/errors).

## Create withdrawal

```http
POST /v1/withdraws
```

API key scope: `withdraw`

Create withdrawal: withdrawals to external addresses go to manual review; between two pooled merchants it is an in-pool transfer (instant, not on-chain)

**Request body**

| Field | Type | Description |
|---|---|---|
| `amount` | string | Amount in the main unit, e.g. 12.5 |
| `biz_id` | string | Business order number: the merchant-side idempotency key, unique per merchant |
| `chain_code` | string | Chain code, e.g. TRON / ETH / BSC |
| `force_onchain` | boolean | Force on-chain: when the destination is another address in the platform pool, the default is an in-pool transfer (instant, no gas, no fee); true sends it on-chain as a normal withdrawal |
| `to_address` | string | Destination address |
| `token_code` | string | Token, e.g. USDT |
| `user_id` | string | User ID: the merchant's own user identifier |

Request example:

```json
{
  "amount": "12.5",
  "biz_id": "order-20261109-0001",
  "chain_code": "TRON",
  "force_onchain": false,
  "to_address": "TXYZopYRdj2D9XRtbG411XZZ3kM5VkAeBf",
  "token_code": "USDT",
  "user_id": "u_10001"
}
```

**Response** (200, `Withdraw`)

| Field | Type | Description |
|---|---|---|
| `amount` | string | Amount (main unit) actually sent on-chain |
| `amount_raw` | string | Amount (integer, smallest unit) |
| `biz_id` | string | Merchant order number |
| `block_number` | string |  |
| `broadcast_time` | string | Broadcast time (Unix milliseconds); 0 if not broadcast |
| `chain_code` | string |  |
| `confirm_time` | string | Confirmation time (Unix milliseconds); 0 if not confirmed |
| `confirmations` | integer |  |
| `create_time` | string | Creation time (Unix milliseconds) |
| `decimals` | integer |  |
| `fee` | string | Fee (main unit), charged off-chain |
| `from_address` | string | Outbound hot wallet address: set after approval; empty for in-pool transfers |
| `internal` | boolean | Whether it is an in-pool transfer (both sides are pooled merchants; not on-chain, instant) |
| `reason` | string | Failure or rejection reason (set when FAILED / REJECTED) |
| `status` | string | REQUESTING / PENDING / BROADCASTED / CONFIRMED / REJECTED / FAILED |
| `to_address` | string |  |
| `token_code` | string |  |
| `tx_hash` | string | On-chain transaction hash: set after signing; empty for in-pool transfers |
| `user_id` | string |  |
| `withdraw_id` | string |  |

Response example:

```json
{
  "amount": "12.5",
  "amount_raw": "12500000",
  "biz_id": "order-20261109-0001",
  "block_number": "77123456",
  "broadcast_time": "1762650000000",
  "chain_code": "TRON",
  "confirm_time": "1762650000000",
  "confirmations": 0,
  "create_time": "1762650000000",
  "decimals": 6,
  "fee": "",
  "from_address": "TJRabPrwbZy45sbavfcjinPJC18kjpRTv8",
  "internal": false,
  "reason": "AMOUNT_BELOW_MIN",
  "status": "REQUESTING",
  "to_address": "TXYZopYRdj2D9XRtbG411XZZ3kM5VkAeBf",
  "token_code": "USDT",
  "tx_hash": "3f1c0e…（交易哈希）",
  "user_id": "u_10001",
  "withdraw_id": "1987654321098753"
}
```

On failure the unified error body is returned; see [Errors](/en/guide/errors).

## Get withdrawal

```http
GET /v1/withdraws/{withdraw_id}
```

API key scope: `read`

Get withdrawal

**Parameters**

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `withdraw_id` | path | string | yes | Withdrawal ID |

**Response** (200, `Withdraw`)

| Field | Type | Description |
|---|---|---|
| `amount` | string | Amount (main unit) actually sent on-chain |
| `amount_raw` | string | Amount (integer, smallest unit) |
| `biz_id` | string | Merchant order number |
| `block_number` | string |  |
| `broadcast_time` | string | Broadcast time (Unix milliseconds); 0 if not broadcast |
| `chain_code` | string |  |
| `confirm_time` | string | Confirmation time (Unix milliseconds); 0 if not confirmed |
| `confirmations` | integer |  |
| `create_time` | string | Creation time (Unix milliseconds) |
| `decimals` | integer |  |
| `fee` | string | Fee (main unit), charged off-chain |
| `from_address` | string | Outbound hot wallet address: set after approval; empty for in-pool transfers |
| `internal` | boolean | Whether it is an in-pool transfer (both sides are pooled merchants; not on-chain, instant) |
| `reason` | string | Failure or rejection reason (set when FAILED / REJECTED) |
| `status` | string | REQUESTING / PENDING / BROADCASTED / CONFIRMED / REJECTED / FAILED |
| `to_address` | string |  |
| `token_code` | string |  |
| `tx_hash` | string | On-chain transaction hash: set after signing; empty for in-pool transfers |
| `user_id` | string |  |
| `withdraw_id` | string |  |

Response example:

```json
{
  "amount": "12.5",
  "amount_raw": "12500000",
  "biz_id": "order-20261109-0001",
  "block_number": "77123456",
  "broadcast_time": "1762650000000",
  "chain_code": "TRON",
  "confirm_time": "1762650000000",
  "confirmations": 0,
  "create_time": "1762650000000",
  "decimals": 6,
  "fee": "",
  "from_address": "TJRabPrwbZy45sbavfcjinPJC18kjpRTv8",
  "internal": false,
  "reason": "AMOUNT_BELOW_MIN",
  "status": "REQUESTING",
  "to_address": "TXYZopYRdj2D9XRtbG411XZZ3kM5VkAeBf",
  "token_code": "USDT",
  "tx_hash": "3f1c0e…（交易哈希）",
  "user_id": "u_10001",
  "withdraw_id": "1987654321098753"
}
```

On failure the unified error body is returned; see [Errors](/en/guide/errors).
