https://openplatform.gateapi.io
- Log into the merchant backend at
https://www.gate.com/zh/merchant#/get-started
- Fill in basic information to apply for merchant status
- Go to the application configuration page to configure a new application
- View the list of configured applications to obtain the application
ClientId
- Go to the developer page to generate the "Payment API Key," used for signing and verifying the payment interface
- Go to the developer page to generate the "Authorization Key," used for signing and verifying the authorization interface
- Payment API Key, used for request signing
ClientId
, used for identity verification, along with the payment API key for signature verification
Field | Description |
---|---|
Transmission Method | To ensure transaction security, use HTTPS and TLS1.2 or higher |
Data Format | Both request and response data are in JSON format |
Signature Algorithm | HMAC-512 algorithm |
Signature Requirement | Both request and response data require signature verification; see the Interface Signature section for details |
Validation Logic | First check the protocol's status field, then the business response, and finally the transaction status |
All interface responses return in JSON
format
Field Name | Type | Description |
---|---|---|
status | string | API response result, SUCESS for success, FAIL for failure |
code | string | Response error code |
label | string | Response error name |
errorMessage | string | Error description |
data | string | Business response data in JSON format |
Successful response example:
{
"status": "SUCCESS",
"code": "000000",
"errorMessage": "",
"data": {
"prepayId": "43013197477711872",
"merchantId": 10002,
"merchantTradeNo": "13683379532935164644",
"currency": "USDT",
"totalFee": "1.6",
"merchant_name": "MINIAPP PAYMENT TEST",
"goods_name": "NFT",
"status": "PENDING",
"qrcode": "http://openplatform.gate.io/qr/P_6uSR4icI56VUdM2lbYdVihLxR_SsrcNfbdzNzfgp0=",
"create_time": 1672216745425,
"expire_time": 1672220345420
}
}
Failure response example:
{
"status": "FAIL",
"code": "400002",
"label": "INVALID_SIGNATURE",
"errorMessage": "Incorrect signature result",
"data": {}
}
To ensure that requests received by the GatePay API come from authorized third-party platforms, GatePay API will check the required fields in the HTTP request headers for signature validation.
In the new protocol header, the signature is calculated using the key generated in the merchant backend.
Header Field | To ensure transaction security, HTTPS transmission is used |
---|---|
X-GatePay-Certificate-ClientId | clientId assigned to the merchant when registering the application in the Gate merchant backend |
X-GatePay-Timestamp | UTC timestamp in milliseconds when the request is generated. Note: GatePay will not process requests if the difference between the received request time and this timestamp exceeds 10 seconds. |
X-GatePay-Nonce | Random string that conforms to HTTP Header specifications, recommended length within 32 characters, composed of numbers and letters |
X-GatePay-Signature | Request signature. GatePay uses this signature to verify the legitimacy of the request. |
Constructing the signature string:
We expect the technical developers of merchants to construct the signature string according to the rules specified in this document. GatePay will use the same method to construct the signature string. If the merchant constructs the signature string incorrectly, the signature verification will fail. Below is the specific format of the signature string.
Each line is a parameter, ending with \n
(newline character, ASCII code 0x0A). If the parameter itself ends with \n
, an additional \n
is required.
request timestamp\nrequest random string\nrequest body\n
Signature algorithm examples are shown on the right.
Python
import hashlib
import hmac
def generate_signature(timestamp: string, nonce: string, body string, secret: string) -> string:
'''
Generate the request signature
:param timestamp: UTC timestamp as string, precision is milliseconds
:param nonce: random string
:param body: request body
:param secret: api_secret provided by GatePay
:return: string signature
'''
payload = '%s\n%s\n%s\n' % (timestamp, nonce, body)
signed = hmac.new(secret.encode(), payload.encode(), hashlib.sha512)
return signed.digest().hex()
Data Type: JSON (content-type:application/json)
Request Method: POST
Path: /v1/pay/withdraw
erification Method: Signature verification
Request Body Content:
Field Name | Type | Required | Description |
---|---|---|---|
batch_id | string | Yes | A unique ID generated by the merchant, composed of uppercase and lowercase letters, numbers, and underscores, max length 32 characters. |
withdraw_list | array object | Yes | Details of each withdrawal sub-order |
channel_id | string | No | Client Name. |
Fields in the withdraw_list:
Field Name | Type | Required | Description |
---|---|---|---|
merchant_withdraw_id | string | Yes | Unique ID for the sub-order generated by the merchant, composed of uppercase and lowercase letters, numbers, and underscores, max length 32 characters. |
amount | string | Yes | Withdrawal amount for each transaction, precision max length 6 digits; exceeding 6 digits will be truncated. |
currency | string | Yes | Currency for withdrawal |
chain | string | Yes | Network chain |
address | string | Yes | Withdrawal address |
memo | string | Yes | Remarks for a transfer, etc.; required for transfers on certain networks. Filling it out when it's not required may result in failure, max length 128 characters |
Response Body Content:
Field Name | Type | Description |
---|---|---|
batch_id | string | Unique ID generated by the merchant |
Request Example:
curl --location 'https://openplatform.gateapi.io/v1/pay/withdraw' \
--header 'X-GatePay-Certificate-ClientId: mZ96D37oKk-HrWJc' \
--header 'Content-Type: application/json' \
--header 'X-GatePay-Timestamp: 1725956825391' \
--header 'X-GatePay-Nonce: 1698252264' \
--header 'X-GatePay-Signature: fee74083ef2f64b8c0acbc4c0638586e6352b0d307d74aac038b2a7f40b396f8b47e6c18a6ed3da296168c9ff5a2a973b55115f969e95c0231c2bbbc70f7dea7' \
--data '{
"batch_id" : "237394559478075350",
"channel_id" : "123456",
"withdraw_list": [
{
"merchant_withdraw_id": "M137394559478075550",
"currency": "USDT",
"amount": "1",
"chain": "ETH",
"address": "0x1234567890abcdef",
"memo" : "Payment for services-1"
},
{
"merchant_withdraw_id": "M137394559478075551",
"currency": "USDT",
"amount": "0.001",
"chain": "ETH",
"address": "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa",
"memo" : "Payment for services-1"
}
]
}'
Response Example:
{
"status": "SUCCESS",
"code": "000000",
"errorMessage": "",
"data": {
"batch_id": "237394559478075550"
}
}
JSON (content-type:application/json)
POST
/v1/pay/withdraw/query
Field Name | Type | Required | Description |
---|---|---|---|
batch_id | string | Yes | Unique ID generated by the merchant at /v1/pay/withdraw |
detail_status | string | Yes | Query status of sub-orders ALL: all sub-orders PENDING: pending sub-orders PROCESSING: submitted withdrawal request, pending confirmation CHECK: in review FAIL: failed sub-orders DONE: successful sub-orders |
Field Name | Type | Description |
---|---|---|
id | int64 | Record ID |
batch_id | string | Merchant batch withdrawal ID |
merchant_id | int64 | Merchant ID |
channel_id | string | Customer channel name |
suborder_id | string | Sub-order ID generated by gatepay |
withdraw_id | string | Withdrawal transaction ID, used to query withdrawal order |
chain | string | gate_chain name |
address | string | Withdrawal address |
currency | string | Currency |
amount | decimal.Decimal | Initiated withdrawal amount |
fee | decimal.Decimal | Transaction fee |
tx_id | string | Transaction hash |
timestamp | int64 | Deposit/withdrawal operation time |
memo | string | Transfer memo and other note information |
status | string | Status |
merchant_withdraw_id | string | Merchant withdrawal ID |
err_msg | string | Reason for withdrawal initiation failure |
client_id | string | Client ID |
create_time | int64 | Creation time |
update_time | int64 | Update time |
fee_type | int8 | 0-Amount is deduction amount, 1-Amount is received amount |
batch_withdraw_id | string | Deprecated |
desc | string | Non-column field, customer channel remarks |
reconciliation_status | int8 | Withdrawal reconciliation status: 0-Not reconciled, 1-Reconciliation in progress, 2-Reconciliation matching failed, 3-Reconciliation matching successful |
is_placed | int | 0-Not placed, 1-Placed |
finish_time | int64 | Order completion time |
sub_amount | decimal.Decimal | Total deduction amount (fee amount + received amount) |
done_amount | decimal.Decimal | Received amount |
Field Name | Type | Description |
---|---|---|
batch_id | string | Batch ID |
merchant_id | int64 | Merchant ID |
client_id | string | Client ID |
status | string | Main order status |
create_time | int64 | Main order creation time |
withdraw_list | []*gfpay.BatchWithdrawSuborderDB | Sub-order information |
channel_id | string | Customer channel name |
Request Example:
curl --location 'https://openplatform.gateapi.io/v1/pay/withdraw/query' \
--header 'X-GatePay-Certificate-ClientId: mZ96D37oKk-HrWJc' \
--header 'Content-Type: application/json' \
--header 'X-GatePay-Timestamp: 1726027137585' \
--header 'X-GatePay-Nonce: 2290830087' \
--header 'X-GatePay-Signature: 601d560c54d53412aca5901256f101e7078b5779f61f30bedfe9a5f0b92f049589952a151ea477371e4a99ac0e1c3cc8dec62654b3c6a1794ef981efe19232bc' \
--data '{
"batch_id":"237394559478075555",
"detail_status":"ALL"
}'
Response Example:
{
"status": "SUCCESS",
"code": "000000",
"errorMessage": "",
"data": {
"batch_id": "237394559478075350",
"merchant_id": 10002,
"client_id": "mZ96D37oKk-HrWJc",
"status": "FAIL",
"create_time": 1726055849126,
"channel_id": "123456",
"withdraw_list": [
{
"id": 35,
"batch_id": "237394559478075350",
"merchant_id": 10002,
"suborder_id": "268830764354768896",
"chain": "ETH",
"address": "0x1234567890abcdef",
"currency": "USDT",
"amount": "1",
"fee": "0",
"tx_id": "",
"timestamp": 0,
"memo": "Payment for services-1",
"status": "FAIL",
"merchant_withdraw_id": "M137394559478075550",
"err_msg": "unexpected http code error",
"client_id": "mZ96D37oKk-HrWJc",
"create_time": 1726055848856,
"update_time": 1726055856011,
"channel_id": "123456",
"fee_type": 1,
"done_amount": "1"
},
{
"id": 36,
"batch_id": "237394559478075350",
"merchant_id": 10002,
"suborder_id": "268830764354768897",
"chain": "ETH",
"address": "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa",
"currency": "USDT",
"amount": "0.001",
"fee": "0",
"tx_id": "",
"timestamp": 0,
"memo": "Payment for services-1",
"status": "FAIL",
"merchant_withdraw_id": "M137394559478075551",
"err_msg": "unexpected http code error",
"client_id": "mZ96D37oKk-HrWJc",
"create_time": 1726055848856,
"update_time": 1726055856010,
"channel_id": "123456",
"fee_type": 1,
"done_amount": "0.001"
}
]
}
}
If batch_id does not exist, return empty:
{
"status": "SUCCESS",
"code": "000000",
"errorMessage": "",
"data": {
"batch_id": "237394559478075358",
"merchant_id": 0,
"client_id": "",
"status": "",
"create_time": 0,
"withdraw_list": []
}
}
Data Type: JSON (content-type: application/json)
Request Method: GET
Path: /v1/pay/wallet/currency_chains
Authentication: Signature Verification
Request Body:
Field Name | Type | Required | Description |
---|---|---|---|
currency | string | Yes | Specify currency name |
Response Format:
Status Code 200
Field Name | Type | Required | Description |
---|---|---|---|
chain | string | Yes | Blockchain network name (e.g. ERC20, TRC20, BEP20) |
name_cn | string | Yes | Chinese name of blockchain (e.g. 以太坊 for Ethereum) |
name_en | string | Yes | English name of blockchain (e.g. Ethereum, Tron) |
contract_address | string | Yes | Smart contract address (empty string for native coins like BTC, ETH) |
is_disabled | integer(int32) | Yes | Global disable status: 0-enabled 1-disabled |
is_deposit_disabled | integer(int32) | Yes | Deposit function status: 0-enabled 1-disabled |
is_withdraw_disabled | integer(int32) | Yes | Withdrawal function status: 0-enabled 1-disabled |
decimal | string | Yes | Withdrawal precision (decimal places, e.g. "6" for BTC) |
Sample Code
# coding: utf-8
import requests
host = "https://openplatform.gateapi.io/"
prefix = "/v1/pay"
headers = {'Accept': 'application/json', 'Content-Type': 'application/json'}
url = '/wallet/currency_chains'
query_param = 'currency=GT'
r = requests.request('GET', host + prefix + url + "?" + query_param, headers=headers)
print(r.json())
Response Example: CODE 200
[
{
"chain": "ETH",
"name_cn": "以太坊ERC20",
"name_en": "ETH/ERC20",
"contract_address": "",
"is_disabled": 0,
"is_deposit_disabled": 0,
"is_withdraw_disabled": 0
}
]
Data Type: JSON (content-type: application/json)
Request Method: GET
Path: /v1/pay/wallet/total_balance
Authentication: Signature Verification
Request Body:
Field Name | Type | Required | Description |
---|---|---|---|
currency | string | Yes | Specify currency name |
Response Format:
Status Code 200
Field Name | Type | Required | Description |
---|---|---|---|
total | object | Yes | Total account balance converted to target currency |
› amount | string | Yes | Total balance amount |
› currency | string | Yes | Target currency |
› unrealised_pnl | string | No | Unrealized PnL total (only appears in futures/options/delivery/total accounts) |
› borrowed | string | No | Total margin borrowing (only appears in margin/cross_margin accounts) |
details | object | Yes | Account type details |
› account_type | object | Yes | Account type key (see account types below) |
›› amount | string | Yes | Balance amount for this account type |
›› currency | string | Yes | Target currency |
›› unrealised_pnl | string | No | Unrealized PnL (only appears in futures/options/delivery/total accounts) |
›› borrowed | string | No | Margin borrowing (only appears in margin/cross_margin accounts) |
Simple Code
# coding: utf-8
import requests
host = "https://openplatform.gateapi.io/"
prefix = "/v1/pay"
headers = {'Accept': 'application/json', 'Content-Type': 'application/json'}
url = '/wallet/currency_chains'
query_param = 'currency=GT'
r = requests.request('GET', host + prefix + url + "?" + query_param, headers=headers)
print(r.json())
Response:
CODE 200
[
{
"chain": "ETH",
"name_cn": "以太坊ERC20",
"name_en": "ETH/ERC20",
"contract_address": "",
"is_disabled": 0,
"is_deposit_disabled": 0,
"is_withdraw_disabled": 0
}
]
Data Type: JSON (content-type: application/json)
Request Method: GET
Path: /v1/pay/wallet/withdraw_status
Authentication: Signature Verification
Request Body:
Field Name | Type | Required | Description |
---|---|---|---|
currency | string | Yes | Specify currency name |
Response Format:
Status Code 200
Field Name | Type | Required | Description |
---|---|---|---|
currency | string | Yes | Currency symbol (e.g. BTC, ETH) |
name | string | Yes | Currency name (e.g. Bitcoin, Ethereum) |
name_cn | string | Yes | Chinese name of currency (e.g. 比特币, 以太坊) |
deposit | string | Yes | Deposit fee (usually "0" as string) |
withdraw_percent | string | Yes | Withdrawal fee percentage (e.g. "0.1" means 0.1%) |
withdraw_fix | string | Yes | Fixed withdrawal fee (e.g. "0.0005") |
withdraw_day_limit | string | Yes | Daily withdrawal limit (max total withdrawal amount per day) |
withdraw_amount_mini | string | Yes | Minimum withdrawal amount (single withdrawal cannot be lower than this) |
withdraw_day_limit_remain | string | No | Remaining daily withdrawal limit (available amount left for today) |
withdraw_eachtime_limit | string | Yes | Maximum single withdrawal amount (cannot exceed this per transaction) |
withdraw_fix_on_chains | object | No | Fixed withdrawal fees per chain (property: chain name, value: fee string) |
withdraw_percent_on_chains | object | No | Percentage withdrawal fees per chain (property: chain name, value: percentage string) |
No handling fees are charged for withdrawals to a Gate addresss, whereas handling fees apply when withdrawingto a non-Gate address.
Simple Code:
import requests
import time
import hashlib
import hmac
import math
import random
host = "https://openplatform.gateapi.io/"
prefix = "/v1/pay"
headers = {'Accept': 'application/json', 'Content-Type': 'application/json'}
url = '/wallet/withdraw_status'
query_param = ''
nonce = math.floor(((random.random() * 9 + 1) * 1000000000))
secret = ""
sign_headers = generate_signature(str(int(time.time()*1000)),nonce,"",secret)
headers.update(sign_headers)
r = requests.request('GET', host + prefix + url, headers=headers)
print(r.json())```
Response:
[
{
"currency": "GT",
"name": "GateToken",
"name_cn": "GateToken",
"deposit": "0",
"withdraw_percent": "0%",
"withdraw_fix": "0.01",
"withdraw_day_limit": "20000",
"withdraw_day_limit_remain": "20000",
"withdraw_amount_mini": "0.11",
"withdraw_eachtime_limit": "20000",
"withdraw_fix_on_chains": {
"BTC": "20",
"ETH": "15",
"TRX": "0",
"EOS": "2.5"
},
"withdraw_percent_on_chains": {
"ETH": "0%",
"GTEVM": "0%"
}
}
]
JSON (content-type: application/json)
GET
/v1/pay/wallet/withdrawals
Field Name | Type | Required | Description |
---|---|---|---|
currency | string | No | Specify currency to query, returns all currencies if empty |
withdraw_id | string | No | Withdrawal record ID (starts with 'w', e.g. w1879219868), queries single record if specified |
asset_class | string | No | Currency type (Main/Pilot zone), empty by default. Values: SPOT, PILOT |
withdraw_order_id | string | No | User-defined withdrawal order number for specific record query |
from | integer(int64) | No | Start timestamp (Unix) units in seconds, defaults to last 7 days |
to | integer(int64) | No | End timestamp (Unix) units in seconds, defaults to current time |
limit | integer | No | Maximum number of records to return |
offset | integer | No | Return record offset (starts from 0) |
Query time range cannot exceed 30 days
Detailed description:
Status Code 200
Field Name | Type | Description |
---|---|---|
id | string | Transaction record ID |
txid | string | Blockchain transaction hash |
block_number | string | Block number |
withdraw_order_id | string | Client order ID (max 32 chars, only allows numbers/letters/_/-/.) |
timestamp | string | Operation time |
amount | string | Amount of currency |
fee | string | Fee amount |
currency | string | Currency name |
address | string | Withdrawal address |
fail_reason | string | Failure reason (only when status = CANCEL) |
timestamp2 | string | Final status time: • CANCEL: Cancellation time • DONE(block_number>0): Success time |
memo | string | Transaction memo/notes |
status | string | Transaction status: - DONE: Completed (block_number > 0 means on-chain confirmed) - CANCEL: Cancelled - REQUEST: Requesting - MANUAL: Pending manual review - BCODE: Top-up code operation - EXTPEND: Sent awaiting confirmation - FAIL: On-chain failure awaiting confirmation - INVALID: Invalid order - VERIFY: Verifying - PROCES: Processing - PEND: Processing - DMOVE: Pending manual review - REVIEW: Under review |
chain | string | Withdrawal chain name |
Request:
# coding: utf-8
import requests
import time
import hashlib
import hmac
host = "https://openplatform.gateapi.io"
prefix = "/v1/pay"
headers = {'Accept': 'application/json', 'Content-Type': 'application/json'}
url = '/wallet/withdrawals'
query_param = ''
sign_headers = gen_sign('GET', prefix + url, query_param)
headers.update(sign_headers)
r = requests.request('GET', host + prefix + url, headers=headers)
print(r.json())
Response:
[
[
{
"id": "w1879219868",
"currency": "USDT",
"address": "THISISTESTADDRESSFORGATEPAY",
"amount": "4.023",
"fee": "0",
"txid": "Internal transaction 260594131",
"chain": "BSC",
"timestamp": "1745220149",
"status": "DONE",
"withdraw_order_id": "202504211521368538928",
"block_number": "1000",
"fail_reason": "",
"type": "appbankgp",
"timestamp2": "1745220149",
"memo": ""
}
]
]
Withdrawal order callback notification fields:
Field Name | Type | Description |
---|---|---|
main_order | object | Main withdrawal order details |
suborders | array | Suborder details |
Field Name | Type | Required | Description |
---|---|---|---|
batch_id | string | Yes | Batch ID |
merchant_id | integer | Yes | Merchant ID |
status | string | Yes | Order status |
client_id | string | Yes | Client ID |
pay_back_status | string | Yes | Refund status |
channel_id | string | Yes | Channel ID |
Field Name | Type | Required | Description |
---|---|---|---|
merchant_id | integer | Yes | Merchant ID |
channel_id | string | Yes | Channel ID |
suborder_id | string | Yes | Suborder ID |
chain | string | Yes | Blockchain network |
address | string | Yes | Receiving address |
currency | string | Yes | Currency |
amount | string | Yes | Transfer amount |
fee | string | Yes | Fee |
tx_id | string | Yes | Transaction hash |
memo | string | Yes | Memo |
status | string | Yes | Status (DONE/FAIL) |
merchant_withdraw_id | string | Yes | Merchant withdrawal ID |
fee_type | integer | Yes | Fee type: 0-Withdrawal amount includes fee, 1-Withdrawal amount is net amount |
batch_withdraw_id | string | Yes | Batch withdrawal ID |
desc | string | Yes | Description |
reconciliation_status | integer | Yes | Reconciliation status |
is_placed | integer | Yes | Processing status: 0-Not submitted, 1-Submitted |
finish_time | integer | Yes | Completion timestamp |
sub_amount | string | Yes | Suborder total amount |
done_amount | string | Yes | Actual completed amount |
Callback :
{
"main_order": {
"batch_id": "831618381568",
"merchant_id": 17329983,
"status": "SUCCESS",
"client_id": "igasgasdbub",
"pay_back_status": "NO",
"channel_id": ""
},
"suborders": [
{
"merchant_id": 130559,
"channel_id": "",
"suborder_id": "30969031299072",
"chain": "TRX",
"address": "QBTW9qTMQBTW9qnoeMMmUxaAWEqVDDUgUw",
"currency": "USDT",
"amount": "2362.1",
"fee": "1",
"tx_id": "aaa33e642d6fb6e3272ae3c21c60f1248d1cd7ccdc000458308d690699",
"memo": "",
"status": "DONE",
"merchant_withdraw_id": "1839295815",
"fee_type": 1,
"batch_withdraw_id": "",
"desc": "",
"reconciliation_status": 0,
"is_placed": 1,
"finish_time": 1748581414000,
"sub_amount": "2363.1",
"done_amount": "2362.1"
}
]
}
HTTP Status Code | Error Code | descriptions | Notes |
---|---|---|---|
200 | 550233 | Insufficient withdrawal balance. | 提现划转余额不足 |
200 | 550234 | Memo exceeds length limit. | 提现memo超过长度限制 |
200 | 550235 | The minimum precision limit of the withdrawal currency, the precision can not be less than 6 decimal places | 提现币种最小精度限制,精度不能小于小数点6位 |
200 | 550236 | The user does not have withdrawal permissions. | 当前提现用户无权限,可联系运营人员申请开通 |
200 | 550237 | Failure to transfer. | 提现划转失败 |
200 | 550238 | The number of withdrawals exceeds the limit of {xx} | 提现子单数量超限制 |
200 | 550239 | amount is required. | 提现金额不能为空 |
200 | 550240 | currency is required. | 提现币种不能为空 |
200 | 550241 | address is required. | 提现地址不能为空 |
200 | 550242 | chain is required. | 提现链名不能为空 |
200 | 550243 | withdraw_order_id is required. | 子单withdraw_order_id参数不能为空 |
200 | 550244 | batch_id is required. | batch_id不能为空 |
200 | 550245 | batch_id duplicates | batch_id重复 |
200 | 550246 | currency withdrawals are not supported yet. | 不支持的币种提现 |
200 | 550247 | Incorrect state parameters. | 提现查询接口状态参数不合法 |
200 | 550248 | Sub-order parameter error. | 子订单参数错误 |
200 | 550249 | Invalid merchant order id. | batch_id,或者withdraw_order_id参数不合法 |