The OTC withdrawal API allows merchants to obtain a quote for cryptocurrency and fiat currency. After receiving a valid quote, the merchant can sell the held cryptocurrency via OTC and settle the fiat funds into a designated bank account. This API is available to Gate Pay merchants only.
API Description: Before creating a fiat withdrawal order, merchants must first request a quote to obtain an executable price and its validity period. During the validity period, the quote token locks the exchange rate, amount, and currency. Once a quote is successfully obtained, the merchant must execute the quote using the quote token within the validity period to create an order.
Data Type: JSON (content-type: application/json)
Request Method: POST
Path: /withdraw/open/otc/api/v1/quote
Authentication Method: Signature Verification
Request Body:
| Field Name | Type | Required | Description |
|---|---|---|---|
| cryptoCurrency | string | Yes | Cryptocurrency. Currently supported: USDT only |
| fiatCurrency | string | Yes | Fiat currency. Currently supported: USD only |
| cryptoAmount | string | No | Cryptocurrency amount. Required when side is CRYPTO |
| fiatAmount | string | No | Fiat amount. Required when side is FIAT |
| side | string | Yes | Quote Direction: CRYPTO: Quote based on cryptocurrency amount (cryptoAmount is required) FIAT: Quote based on fiat amount (fiatAmount is required) |
| promotionCode | string | No | Promotion code |
| type | string | Yes | BUY: Deposit SELL: Withdrawal Currently supported: SELL only |
| Field Name | Type | Description |
|---|---|---|
| cryptoCurrency | string | Cryptocurrency |
| fiatCurrency | string | Fiat currency |
| cryptoAmount | string | Cryptocurrency amount |
| fiatAmount | string | Fiat amount |
| fiatRate | string | Fiat exchange rate (fiat/crypto) |
| cryptoRate | string | Crypto exchange rate (crypto/fiat) |
| validPeriod | integer | Quote validity period, in seconds |
| quoteToken | string | Quote token, used to place an order |
CURL Request
curl --location --request POST 'https://openplatform.gateapi.io/withdraw/open/otc/api/v1/quote' \\
--header 'X-GatePay-Certificate-ClientId: sTTGwlmQBGMpwaLg' \\
--header 'X-GatePay-Timestamp: 1769588949' \\
--header 'x-GatePay-Nonce: 2730095202' \\
--header 'x-GatePay-Signature: 7f780aa07e120dda16f0b0139e86a32ebe9833f10b3bf75fafc55dea46658e14a3f18078fa45ecfd9b81b4edf2c0bc91d1d9dc9ca4de5eed3189437f8e31fd69' \\
--header 'Content-Type: application/json' \\
--data-raw '{
"cryptoCurrency": "USDT",
"fiatCurrency": "USD",
"cryptoAmount": "1000",
"side": "CRYPTO",
"type": "SELL"
}'
Response:
{
"code": "",
"data": {
"cryptoCurrency": "USDT",
"fiatCurrency": "USD",
"cryptoAmount": "10000",
"fiatAmount": "9898.72",
"fiatRate": "0.989872",
"cryptoRate": "1.01023613",
"validPeriod": 300,
"quoteToken": "adhk543"
},
"status": "",
"label": "",
"errorMessage": ""
}
API Description: After obtaining a quote, the merchant must execute the quote within its validity period to create a fiat withdrawal order.
Data Type: JSON (content-type: application/json)
Request Method: POST
Path: /withdraw/open/otc/api/order/create
Authentication Method: Signature Verification
Request Body:
| Field Name | Type | Required | Description |
|---|---|---|---|
| quoteToken | string | Yes | Quote token |
| bankAccountId | string | Yes | Bank account ID |
| cryptoCurrency | string | Yes | Cryptocurrency |
| fiatCurrency | string | Yes | Fiat currency |
| cryptoAmount | string | Yes | Cryptocurrency amount |
| fiatAmount | string | Yes | Fiat amount |
| type | string | Yes | BUY: Deposit SELL: Withdrawal Currently supported: SELL only |
| clientOrderId | string | Yes | Merchant Order Number; Create order failed, please change the order number |
| Field Name | Type | Description |
|---|---|---|
| orderId | string | Order ID |
| status | string | Order status |
| createTime | integer | Creation Time |
| clientOrderId | string | Merchant Order Number |
CURL Request
curl --location --request POST 'https://openplatform.gateapi.io/withdraw/open/otc/api/order/create' \\
--header 'Content-Type: application/json' \\
--header 'X-GatePay-Certificate-ClientId: sTTGwlmQBGMpwaLg' \\
--header 'X-GatePay-Timestamp: 1769669668127' \\
--header 'x-GatePay-Nonce: 7508857261' \\
--header 'x-GatePay-Signature: 9636bd4c3edac24af5ea2b410c38aa0bafc7e73d6333158205a3f3652cfd97e2a94e38a259a057bee565889b1c686a22b03943a196c19d1eaa43ecb5a045cec1' \\
--data-raw '{
"cryptoCurrency": "USDT",
"fiatCurrency": "USD",
"cryptoAmount": "10000",
"fiatAmount": "9800",
"type": "SELL",
"quoteToken": "qdfh34543",
"bankAccountId": "2897434"
}'
Response:
{
"code": "000000",
"data": {
"orderId": "2016768770965639168",
"status": "PROCESSING",
"createTime": 1769670119407
},
"status": "SUCCESS",
"errorMessage": ""
}
API Description: After a quote is executed and an order is successfully created, merchants can query the order status and related details using the returned order ID.
Data Type: JSON (content-type: application/json)
Request Method: GET
Path: /withdraw/open/otc/api/order/detail
Authentication Method: Signature Verification
Request Parameters:
| Field Name | Type | Required | Description |
|---|---|---|---|
| orderId | string | No | Order ID.Required when clientOrderId is null |
| clientOrderId | string | No | Merchant Order Number.Required when orderId is null |
| Field Name | Type | Description |
|---|---|---|
| orderId | string | Order ID |
| status | string | Order Status: PROCESSING: Processing FAIL: Failure DONE: Success DISPATCHED: Dispatched |
| cryptoCurrency | string | Cryptocurrency |
| fiatCurrency | string | Fiat currency |
| type | string | BUY: Deposit SELL: Withdrawal |
| cryptoAmount | string | Cryptocurrency amount |
| fiatAmount | string | Fiat amount |
| fiatRate | string | Fiat exchange rate (fiat/crypto) |
| bankAccountId | string | Bank Account ID |
| createTime | integer | Creation Time |
| updateTime | integer | Last update time |
| clientOrderId | string | Merchant Order Number |
| errMsg | string | Failure reason |
| tradeFee | string | Fee (in same currency as fiatCurrency) |
| finalFiatAmount | string | Net amount (in same currency as fiatCurrency) |
CURL Request
curl --location --request GET 'https://openplatform.gateapi.io/withdraw/open/otc/api/order/detail?orderId=35599620284481595' \\
--header 'Content-Type: application/json' \\
--header 'X-GatePay-Certificate-ClientId: sTTGwlmQBGMpwaLg' \\
--header 'X-GatePay-Timestamp: 1769670845426' \\
--header 'x-GatePay-Nonce: 9099836565' \\
--header 'x-GatePay-Signature: 3eef45b012cf9710eb06587775f5fc2807b7445fb0fdd3c830cf453ee07b34824c0b4bf187a1ad783f886c592b04da7b0ab5d8bf47b8741c82bd408db7b811b4'
Response:
{
"code": "000000",
"data": {
"cryptoCurrency": "USDT",
"fiatCurrency": "USD",
"cryptoAmount": "100000",
"fiatAmount": "99810.08",
"orderId": "35599620284481595",
"status": "DONE",
"createTime": 1761205415973,
"updateTime": 1761205416189,
"bankAccountId": "123141284812832183",
"type": "SELL",
"fiatRate": "0.9981"
},
"status": "SUCCESS",
"errorMessage": ""
}
API Description: After executing quotes and creating orders, merchants can query order status and related details in batches using the returned order ID.
Data Type: JSON (content-type: application/json)
Request Method: POST
Path: /withdraw/open/otc/api/order/list
Authentication Method: Signature Verification
Request Body:
| Field Name | Type | Required | Description |
|---|---|---|---|
| status | string | No | Order Status: PROCESSING: Processing FAIL: Failure DONE: Success DISPATCHED: Dispatched |
| type | string | No | BUY: Deposit SELL: Withdrawal |
| cryptoCurrency | string | No | Cryptocurrency |
| fiatCurrency | string | No | Fiat currency |
| startTime | string | No | Start time (creation time) |
| endTime | string | No | End time (creation time) |
| page | integer | No | Page number, default 1 |
| pageSize | integer | No | Page size, default 10, maximum 500 |
| clientOrderId | string | No | Merchant Order Number |
| Field Name | Type | Description |
|---|---|---|
| data | array | Order list |
| data[].order_id | string | Order ID |
| data[].status | string | Order Status: PROCESSING: Processing FAIL: Failure DONE: Success DISPATCHED: Dispatched |
| data[].cryptoCurrency | string | Cryptocurrency |
| data[].fiatCurrency | string | Fiat currency |
| data[].bankAccountId | string | Bank Account ID |
| data[].cryptoAmount | string | Cryptocurrency amount |
| data[].fiatAmount | string | Fiat amount |
| data[].fiatRate | string | Fiat exchange rate (Fiat/Crypto) |
| data[].createTime | integer | Creation Time |
| data[].updateTime | integer | Last update time |
| data[].type | string | BUY: Deposit SELL: Withdrawal |
| data[].clientOrderId | string | Merchant Order Number |
| data[].errMsg | string | Failure reason |
| data[].tradeFee | string | Fee (in same currency as fiatCurrency) |
| data[].finalFiatAmount | string | Net amount (in same currency as fiatCurrency) |
| page | integer | Current page |
| pageSize | integer | Page size |
| total | integer | Total records |
CURL Request
curl --location --request POST 'https://openplatform.gateapi.io/withdraw/open/otc/api/order/list' \\
--header 'Content-Type: application/json' \\
--header 'X-GatePay-Certificate-ClientId: sTTGwlmQBGMpwaLg' \\
--header 'X-GatePay-Timestamp: 1769671300600' \\
--header 'x-GatePay-Nonce: 8907767296' \\
--header 'x-GatePay-Signature: ec0102f15ced90319c02c8feb24ee81d0e9a701a2078c7b7fbfe68b9216611a6eaa2a67aa37d964b3cc9e491a3cfa8eee07c736d22b8d92fdd0f16e0bc316a4a' \\
--data-raw '{
"page": 1,
"pageSize": 10
}'
Response:
{
"code": "000000",
"data": {
"page": 1,
"pageSize": 10,
"total": 49,
"data": [
{
"cryptoCurrency": "USDT",
"fiatCurrency": "USD",
"cryptoAmount": "10000",
"fiatAmount": "99810.08",
"orderId": "2016769960466059264",
"status": "DONE",
"createTime": 1769670404763,
"updateTime": 1769670720469,
"type": "SELL",
"bankAccountId": "2897434",
"fiatRate": "0.9981",
"clientOrderId": "980932432"
},
{
"cryptoCurrency": "USDT",
"fiatCurrency": "USD",
"cryptoAmount": "10000",
"fiatAmount": "99810.08",
"orderId": "2016768770965639168",
"status": "DONE",
"createTime": 1769670119407,
"updateTime": 1769670300606,
"type": "SELL",
"bankAccountId": "2897434",
"fiatRate": "0.9981",
"clientOrderId": "980932433"
}
]
},
"status": "SUCCESS",
"errorMessage": ""
}
API Description:If you need to add a bank account, you may first query the list of available countries for bank account registration.
Data Type: JSON (content-type: application/json)
Request Method: GET
Path: /withdraw/open/otc/api/bank/country/list
Authentication Method: Signature Verification
Request Parameters:
Response Body:
| Field Name | Type | Description |
|---|---|---|
| data | array | Countriy List |
| data[].countryId | int | Country ID |
| data[].countryName | string | Country name |
| data[].countryCn | string | Country name (Chinese) |
CURL Request
curl --location --request GET 'https://openplatform.gateapi.io/withdraw/open/otc/api/bank/country/list' \
--header 'Content-Type: application/json' \
--header 'X-GatePay-Certificate-ClientId: sTTGwlmQBGMpwaLg' \
--header 'X-GatePay-Timestamp: 1769671300600' \
--header 'x-GatePay-Nonce: 8907767296' \
--header 'x-GatePay-Signature: ec0102f15ced90319c02c8feb24ee81d0e9a701a2078c7b7fbfe68b9216611a6eaa2a67aa37d964b3cc9e491a3cfa8eee07c736d22b8d92fdd0f16e0bc316a4a' \
Response:
{
"code": "000000",
"data": [
{
"countryId": 260,
"countryCn": "阿富汗",
"countryName": "Afghanistan"
},
{
"countryId": 3,
"countryCn": "阿尔巴尼亚",
"countryName": "Albania"
},
{
"countryId": 4,
"countryCn": "阿尔及利亚",
"countryName": "Algeria"
}
],
"status": "SUCCESS",
"errorMessage": ""
}
API Description:A bank account must be added for OTC fiat withdrawal; the bank statement must be uploaded at the same time when adding a new bank account.
Data Type:JSON (content-type:multipart/form-data)
Request Method:POST
Path: /withdraw/open/otc/api/bank/create
Authentication Method:Signature Verification
Request Parameters:
| Field Name | Type | Required | Description |
|---|---|---|---|
| bankAccountName | string | Yes | Account holder name |
| bankName | string | Yes | Bank name |
| countryId | int | Yes | Country ID |
| address | string | Yes | Bank address |
| iban | string | Yes | IBAN |
| swift | string | Yes | SWIFT |
| remittanceLineNumber | string | No | Routing / clearing code |
| agentBankName | string | No | Agent bank name |
| agentBankSwift | string | No | Agent bank SWIFT |
| file | file | Yes | File stream,max size 4MB,only suppot jpg、jpeg、png; A bank statement issued within the last 3 months. The account holder's name must exactly match the name used for identity verification. If discrepancies arise due to language or other reasons, supporting documents must be provided (e.g., a bank certificate, a passport, an official name change document) |
| Field Name | Type | Description |
|---|---|---|
| bankAccountId | string | Bank Account ID |
CURL Request
curl --location --request POST 'https://openplatform.gateapi.io/withdraw/open/otc/api/bank/create' \
--header 'X-GatePay-MerchantId;' \
--form 'bankAccountName="bank001"' \
--form 'bankName="bankName01"' \
--form 'countryId="260"' \
--form 'address="123"' \
--form 'iban="123213213"' \
--form 'swift="21321"' \
--form 'remittanceLineNumber="312"' \
--form 'agentBankName="213"' \
--form 'agentBankSwift="454"' \
--form 'file=@"/Downloads/bank.jpg"'
Response:
{
"code": "000000",
"data": {
"bankAccountId": "2897434"
},
"status": "SUCCESS",
"errorMessage": ""
}
API Description:Returns all bank account details bound to the merchant
Data Type: JSON (content-type: application/json)
Request Method: GET
Path: /withdraw/open/otc/api/bank/list
Authentication Method: Signature Verification
Request Parameters: (Fuzzy Query)
| Field Name | Type | Required | Description |
|---|---|---|---|
| bankAccountName | string | No | Account holder name |
| iban | string | No | IBAN |
| swift | string | No | SWIFT |
| bankName | string | No | Bank name |
| Field Name | Type | Description |
|---|---|---|
| data | array | Bank List |
| data[].bankAccountId | string | Bank Account ID |
| data[].bankAccountName | string | Account holder name |
| data[].bankName | string | Bank name |
| data[].countryId | int | Country ID |
| data[].countryName | string | Country Name |
| data[].address | string | Bank address |
| data[].iban | string | IBAN |
| data[].swift | string | SWIFT |
| data[].remittanceLineNumber | string | Routing / clearing code |
| data[].agentBankName | string | Agent bank name |
| data[].agentBankSwift | string | Agent bank SWIFT |
CURL Request
curl --location --request GET 'https://openplatform.gateapi.io/withdraw/open/otc/api/bank/list?bankAccountName=bank001&bankName=bankName01&iban=123213213&swift=21321' \
--header 'Content-Type: application/json' \
--header 'X-GatePay-Certificate-ClientId: sTTGwlmQBGMpwaLg' \
--header 'X-GatePay-Timestamp: 1769671300600' \
--header 'x-GatePay-Nonce: 8907767296' \
--header 'x-GatePay-Signature: ec0102f15ced90319c02c8feb24ee81d0e9a701a2078c7b7fbfe68b9216611a6eaa2a67aa37d964b3cc9e491a3cfa8eee07c736d22b8d92fdd0f16e0bc316a4a' \
Response:
{
"code": "000000",
"data": [
{
"bankAccountId": 501,
"bankAccountName": "12312",
"bankName": "123123",
"countryId": 260,
"countryName": "Afghanistan",
"address": "123123",
"iban": "12313123",
"swift": "123132123",
"remittanceLineNumber": "3123123",
"agentBankName": "",
"agentBankSwift": ""
},
{
"bankAccountId": 642,
"bankAccountName": "testname",
"bankName": "123123",
"countryId": 11,
"countryName": "Australia",
"address": "123123",
"iban": "UYTU****GFHG",
"swift": "13123",
"remittanceLineNumber": "1231",
"agentBankName": "",
"agentBankSwift": ""
}
],
"status": "SUCCESS",
"errorMessage": ""
}
API Description:Deletes a specified bank account
Data Type: JSON (content-type: application/json)
Request Method: POST
Path: /withdraw/open/otc/api/bank/delete
Authentication Method: Signature Verification
Request Parameters:
| Field Name | Type | Required | Description |
|---|---|---|---|
| bankAccountId | string | Yes | Bank Account ID |
CURL Request
curl --location --request POST 'https://openplatform.gateapi.io/withdraw/open/otc/api/bank/delete' \
--header 'Content-Type: application/json' \
--header 'X-GatePay-Certificate-ClientId: sTTGwlmQBGMpwaLg' \
--header 'X-GatePay-Timestamp: 1769671300600' \
--header 'x-GatePay-Nonce: 8907767296' \
--header 'x-GatePay-Signature: ec0102f15ced90319c02c8feb24ee81d0e9a701a2078c7b7fbfe68b9216611a6eaa2a67aa37d964b3cc9e491a3cfa8eee07c736d22b8d92fdd0f16e0bc316a4a' \
--data-raw '{
"bankAccountId": 796
}'
Response:
{
"code": "000000",
"data": {},
"status": "SUCCESS",
"errorMessage": ""
}
When OTC order status changes (e.g., withdrawal success, withdrawal failure, etc.), GatePay will send order status notifications to the merchant. The notification URL is the callback url parameter provided during merchant registration.
If notification fails due to network or other unknown reasons, GatePay will retry at 15 seconds, 30 seconds, 3 minutes, 10 minutes, 20 minutes, 30 minutes, 60 minutes, 3 hours, and 6 hours. If retries also fail, the merchant can call the order query API to obtain the order status.
When receiving asynchronous notification messages, the merchant must verify the message signature to validate the authenticity of the message.Refer to API Signature for security verification
| Field Name | Type | Description |
|---|---|---|
bizType | string | Notification type. Fixed value: OTC |
bizId | string | Order ID |
bizStatus | string | Notification status: WITHDRAW_SUCCESS, WITHDRAW_FAIL, WITHDRAW_DISPATCHED |
clientId | string | Client ID of the merchant who created the order |
data | string | Message content |
Message structure example:
{
"bizType":"OTC",
"bizId":"6948484859590",
"bizStatus":"WITHDRAW_SUCCESS",
"clientId":"cdhu-fgrfg44-5ggd-cdvsa",
"data":"{...Json format data...}"
}
After receiving the asynchronous callback message, the merchant must respond to confirm successful receipt. Message structure example:
{
"returnCode": "SUCCESS",
"returnMessage": ""
}
| Field Name | Type | Description |
|---|---|---|
orderId | string | Order ID |
clientOrderId | string | Merchant Order Number |
fiatRate | string | Fiat exchange rate (fiat/crypto) |
type | string | BUY: Deposit SELL: Withdrawal Currently supported: SELL only |
fiatCurrency | string | Fiat currency |
fiatAmount | string | Estimated fiat amount |
cryptoCurrency | string | Cryptocurrency |
cryptoAmount | string | Cryptocurrency amount |
updateTime | string | Last update time |
errMsg | string | Failure reason |
tradeFee | string | Fee (in same currency as fiatCurrency) |
finalFiatAmount | string | Net amount (in same currency as fiatCurrency) |
| Error Code | Description | Solution |
|---|---|---|
400001 | Invalid request parameters | Check if the request parameters are valid |
400002 | Signature verification failed | Check if the merchant signature is correct |
400003 | Request timestamp expired | Check the timestamp field in the request header |
400004 | API credential does not exist or is invalid | Check if the API credential exists or is valid |
400611 | Insufficient balance | Check the account balance |
550175 | Order does not exist | Check if the order was initiated or if the order ID is correct |
5503001 | API rate limit exceeded | Retry later |
5502961 | Service unavailable in user's country | Check if the service is allowed in the user's country |
5502971 | User is not eligible for OTC trading | Check the user's OTC trading eligibility |
5502761 | ClientOrderId is duplicated | Change clientOrderId |
550018 | Rejected by risk control | Retry later |
400000 | Unknown error | Internal system error |
550301 | The user has not completed the relevant Global OTC authentication | - |
550302 | The user has not completed the individual OTC professional certification application | - |
550303 | The user has not completed the enterprise OTC professional certification application | - |
550304 | The user's OTC professional certification application has been rejected | - |
550305 | The user's OTC professional certification has been frozen | - |
550306 | The user's professional certification is under review | - |
550307 | The user's transaction limit is insufficient, an application for limit increase is required | - |
550308 | The user's limit increase application is under review | - |
550309 | The limit increase application has been rejected, please reapply | - |
550310 | The user has not bound a bank card | Please bind a bank account and try again |
550311 | The current operation is restricted, please contact customer service for handling | - |
550312 | Cryptocurrency withdrawal is prohibited | - |
550313 | The inquiry has expired | Please requote and place the order with the new token |
550314 | idempotency check failed | - |
550315 | Amount out of range | Please adjust the quotation amount. For details, contact customer service |
550316 | Create bank account failed | - |
550317 | Delete bank account failed | - |
550318 | Invalid promotion code | Please use a valid promotion code |