curl --request POST \
--url https://whitebit.com/api/v4/main-account/express-withdraw/token \
--header 'Content-Type: application/json' \
--header 'X-TXC-APIKEY: <api-key>' \
--header 'X-TXC-PAYLOAD: <api-key>' \
--header 'X-TXC-SIGNATURE: <api-key>' \
--data '
{
"ticker": "USDT",
"amount": "25.50",
"externalId": "order-100294",
"request": "{{request}}",
"nonce": 1594297865000
}
'import requests
url = "https://whitebit.com/api/v4/main-account/express-withdraw/token"
payload = {
"ticker": "USDT",
"amount": "25.50",
"externalId": "order-100294",
"request": "{{request}}",
"nonce": 1594297865000
}
headers = {
"X-TXC-APIKEY": "<api-key>",
"X-TXC-PAYLOAD": "<api-key>",
"X-TXC-SIGNATURE": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'X-TXC-APIKEY': '<api-key>',
'X-TXC-PAYLOAD': '<api-key>',
'X-TXC-SIGNATURE': '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
ticker: 'USDT',
amount: '25.50',
externalId: 'order-100294',
request: '{{request}}',
nonce: 1594297865000
})
};
fetch('https://whitebit.com/api/v4/main-account/express-withdraw/token', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://whitebit.com/api/v4/main-account/express-withdraw/token",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'ticker' => 'USDT',
'amount' => '25.50',
'externalId' => 'order-100294',
'request' => '{{request}}',
'nonce' => 1594297865000
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-TXC-APIKEY: <api-key>",
"X-TXC-PAYLOAD: <api-key>",
"X-TXC-SIGNATURE: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://whitebit.com/api/v4/main-account/express-withdraw/token"
payload := strings.NewReader("{\n \"ticker\": \"USDT\",\n \"amount\": \"25.50\",\n \"externalId\": \"order-100294\",\n \"request\": \"{{request}}\",\n \"nonce\": 1594297865000\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-TXC-APIKEY", "<api-key>")
req.Header.Add("X-TXC-PAYLOAD", "<api-key>")
req.Header.Add("X-TXC-SIGNATURE", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://whitebit.com/api/v4/main-account/express-withdraw/token")
.header("X-TXC-APIKEY", "<api-key>")
.header("X-TXC-PAYLOAD", "<api-key>")
.header("X-TXC-SIGNATURE", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"ticker\": \"USDT\",\n \"amount\": \"25.50\",\n \"externalId\": \"order-100294\",\n \"request\": \"{{request}}\",\n \"nonce\": 1594297865000\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://whitebit.com/api/v4/main-account/express-withdraw/token")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-TXC-APIKEY"] = '<api-key>'
request["X-TXC-PAYLOAD"] = '<api-key>'
request["X-TXC-SIGNATURE"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"ticker\": \"USDT\",\n \"amount\": \"25.50\",\n \"externalId\": \"order-100294\",\n \"request\": \"{{request}}\",\n \"nonce\": 1594297865000\n}"
response = http.request(request)
puts response.read_body{
"url": "https://whitebit.com/express-withdraw?token=8f3c0a7d4e21",
"expireAt": "2026-07-10 12:34:56"
}{
"code": 123,
"message": "<string>",
"errors": {}
}Create express withdraw token
The endpoint creates a signed, single-use Express Withdraw payment token that charges a specific amount from a WhiteBIT user’s balance to the partner’s Main balance in an instant, off-chain, zero-fee internal transfer. The response returns a URL that embeds the token; the paying user confirms the exact ticker and amount on the WhiteBIT-hosted confirmation surface.
Token and payment constraints:
- Each token is single-use: WhiteBIT marks the token used at confirmation and rejects any replay.
- Each token expires 90 seconds after creation; the
expireAtresponse field carries the authoritative expiry timestamp. Generate the token as close as possible to the moment of presenting the URL to the user. - The ticker must be a withdrawal-enabled cryptocurrency; the endpoint rejects fiat tickers.
- Each payment is capped at the equivalent of 10,000 USDT; WhiteBIT enforces the cap at token creation and re-enforces the cap at confirmation.
- WhiteBIT rejects self-payments: the paying user and the token creator must be different WhiteBIT accounts.
- The endpoint is idempotent per
externalId: re-submitting the sameexternalIdwith an identicaltickerandamountwhile the token is still valid returns the same token instead of creating a duplicate charge. After the token expires, the sameexternalIdreceives a fresh token.
Standard private-API rate limits apply — see Rate limits. The endpoint carries no endpoint-specific limit.
curl --request POST \
--url https://whitebit.com/api/v4/main-account/express-withdraw/token \
--header 'Content-Type: application/json' \
--header 'X-TXC-APIKEY: <api-key>' \
--header 'X-TXC-PAYLOAD: <api-key>' \
--header 'X-TXC-SIGNATURE: <api-key>' \
--data '
{
"ticker": "USDT",
"amount": "25.50",
"externalId": "order-100294",
"request": "{{request}}",
"nonce": 1594297865000
}
'import requests
url = "https://whitebit.com/api/v4/main-account/express-withdraw/token"
payload = {
"ticker": "USDT",
"amount": "25.50",
"externalId": "order-100294",
"request": "{{request}}",
"nonce": 1594297865000
}
headers = {
"X-TXC-APIKEY": "<api-key>",
"X-TXC-PAYLOAD": "<api-key>",
"X-TXC-SIGNATURE": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'X-TXC-APIKEY': '<api-key>',
'X-TXC-PAYLOAD': '<api-key>',
'X-TXC-SIGNATURE': '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
ticker: 'USDT',
amount: '25.50',
externalId: 'order-100294',
request: '{{request}}',
nonce: 1594297865000
})
};
fetch('https://whitebit.com/api/v4/main-account/express-withdraw/token', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://whitebit.com/api/v4/main-account/express-withdraw/token",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'ticker' => 'USDT',
'amount' => '25.50',
'externalId' => 'order-100294',
'request' => '{{request}}',
'nonce' => 1594297865000
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-TXC-APIKEY: <api-key>",
"X-TXC-PAYLOAD: <api-key>",
"X-TXC-SIGNATURE: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://whitebit.com/api/v4/main-account/express-withdraw/token"
payload := strings.NewReader("{\n \"ticker\": \"USDT\",\n \"amount\": \"25.50\",\n \"externalId\": \"order-100294\",\n \"request\": \"{{request}}\",\n \"nonce\": 1594297865000\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-TXC-APIKEY", "<api-key>")
req.Header.Add("X-TXC-PAYLOAD", "<api-key>")
req.Header.Add("X-TXC-SIGNATURE", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://whitebit.com/api/v4/main-account/express-withdraw/token")
.header("X-TXC-APIKEY", "<api-key>")
.header("X-TXC-PAYLOAD", "<api-key>")
.header("X-TXC-SIGNATURE", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"ticker\": \"USDT\",\n \"amount\": \"25.50\",\n \"externalId\": \"order-100294\",\n \"request\": \"{{request}}\",\n \"nonce\": 1594297865000\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://whitebit.com/api/v4/main-account/express-withdraw/token")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-TXC-APIKEY"] = '<api-key>'
request["X-TXC-PAYLOAD"] = '<api-key>'
request["X-TXC-SIGNATURE"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"ticker\": \"USDT\",\n \"amount\": \"25.50\",\n \"externalId\": \"order-100294\",\n \"request\": \"{{request}}\",\n \"nonce\": 1594297865000\n}"
response = http.request(request)
puts response.read_body{
"url": "https://whitebit.com/express-withdraw?token=8f3c0a7d4e21",
"expireAt": "2026-07-10 12:34:56"
}{
"code": 123,
"message": "<string>",
"errors": {}
}Payment flow
The partner integrates one endpoint; WhiteBIT hosts everything the paying user sees.- The partner creates a payment token with the currency, the amount, and a partner-side
externalId. - The partner presents the returned
urlto the user — redirect, deep link, or QR code. - The user opens the URL while authenticated on WhiteBIT and confirms the displayed ticker and amount on the WhiteBIT-hosted confirmation surface.
- WhiteBIT debits the user’s balance and credits the partner’s Main balance in a single internal, off-chain, zero-fee transfer, then marks the token used.
expireAt in the response carries the authoritative expiry. Create the token as close as possible to the moment of presenting the URL to the user; after expiry, re-create the token with the same externalId to receive a fresh one.191.Notes
- For the full integration walkthrough — token lifecycle, idempotency, and limits — see the Express Withdraw section of the Payment Integration guide.
- The endpoint does not support pagination.
Used in these guides
- Payment Integration — crypto deposits, withdrawals, conversion, WhiteBIT Codes, and Express Withdraw.
Authorizations
The public WhiteBIT API key.
Base64-encoded JSON request body.
HMAC-SHA512 signature of the payload, hex-encoded. Computed as hex(HMAC-SHA512(payload, api_secret)).
Body
Currency ticker to charge. Example: USDT
⚠️ The ticker must be a withdrawal-enabled cryptocurrency; the endpoint rejects fiat tickers. Use Asset Status endpoint to check the withdrawal status of a currency.
"USDT"
Partner-side reference for the payment (order or invoice identifier), unique per partner account. The identifier powers idempotency and replay protection: a pending externalId with an identical ticker and amount returns the same token; the endpoint rejects an already-paid externalId with error code 19.
"order-100294"
Request signature
"{{request}}"
Unique request identifier
1594297865000
Response
Token created. Present the returned URL to the paying user before the expiry in expireAt.
URL to present to the paying user (redirect, deep link, or QR code). The value is the WhiteBIT-hosted web confirmation page by default, or a mobile deep link when one is configured for the partner at onboarding; in both cases the unique token travels in the token query parameter. Treat the value as opaque.
"https://whitebit.com/express-withdraw?token=8f3c0a7d4e21"
Absolute token expiry timestamp in YYYY-MM-DD HH:MM:SS format (UTC). The authoritative expiry: each token expires 90 seconds after creation.
"2026-07-10 12:34:56"
Was this page helpful?