curl --request POST \
--url https://banker.qfex.com/withdraw \
--header 'Content-Type: application/json' \
--header 'x-qfex-hmac-signature: <api-key>' \
--header 'x-qfex-nonce: <api-key>' \
--header 'x-qfex-public-key: <api-key>' \
--header 'x-qfex-timestamp: <api-key>' \
--data '
{
"amount": 2,
"address": "<string>",
"network": "ARBITRUM_ONE"
}
'import requests
url = "https://banker.qfex.com/withdraw"
payload = {
"amount": 2,
"address": "<string>",
"network": "ARBITRUM_ONE"
}
headers = {
"x-qfex-hmac-signature": "<api-key>",
"x-qfex-nonce": "<api-key>",
"x-qfex-public-key": "<api-key>",
"x-qfex-timestamp": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'x-qfex-hmac-signature': '<api-key>',
'x-qfex-nonce': '<api-key>',
'x-qfex-public-key': '<api-key>',
'x-qfex-timestamp': '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({amount: 2, address: '<string>', network: 'ARBITRUM_ONE'})
};
fetch('https://banker.qfex.com/withdraw', 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://banker.qfex.com/withdraw",
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([
'amount' => 2,
'address' => '<string>',
'network' => 'ARBITRUM_ONE'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-qfex-hmac-signature: <api-key>",
"x-qfex-nonce: <api-key>",
"x-qfex-public-key: <api-key>",
"x-qfex-timestamp: <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://banker.qfex.com/withdraw"
payload := strings.NewReader("{\n \"amount\": 2,\n \"address\": \"<string>\",\n \"network\": \"ARBITRUM_ONE\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-qfex-hmac-signature", "<api-key>")
req.Header.Add("x-qfex-nonce", "<api-key>")
req.Header.Add("x-qfex-public-key", "<api-key>")
req.Header.Add("x-qfex-timestamp", "<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://banker.qfex.com/withdraw")
.header("x-qfex-hmac-signature", "<api-key>")
.header("x-qfex-nonce", "<api-key>")
.header("x-qfex-public-key", "<api-key>")
.header("x-qfex-timestamp", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"amount\": 2,\n \"address\": \"<string>\",\n \"network\": \"ARBITRUM_ONE\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://banker.qfex.com/withdraw")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-qfex-hmac-signature"] = '<api-key>'
request["x-qfex-nonce"] = '<api-key>'
request["x-qfex-public-key"] = '<api-key>'
request["x-qfex-timestamp"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"amount\": 2,\n \"address\": \"<string>\",\n \"network\": \"ARBITRUM_ONE\"\n}"
response = http.request(request)
puts response.read_bodyRequest a crypto withdrawal to a registered address
Standard API keys require deposit_withdraw. Keys issued or replaced through POST /builder/web3/api-key also support crypto withdrawals to registered destinations when the user owns the selected account. This builder access is not selectable in Developer Settings. Every withdrawal, including all API keys and JWT sessions, must use a destination registered by the authenticated user on the requested network. Addresses are checked before debiting funds; Arbitrum matching is case-insensitive and TRON matching is exact. The user’s primary account is debited. Requests are not idempotent; reconcile withdrawal history after a timeout before retrying.
curl --request POST \
--url https://banker.qfex.com/withdraw \
--header 'Content-Type: application/json' \
--header 'x-qfex-hmac-signature: <api-key>' \
--header 'x-qfex-nonce: <api-key>' \
--header 'x-qfex-public-key: <api-key>' \
--header 'x-qfex-timestamp: <api-key>' \
--data '
{
"amount": 2,
"address": "<string>",
"network": "ARBITRUM_ONE"
}
'import requests
url = "https://banker.qfex.com/withdraw"
payload = {
"amount": 2,
"address": "<string>",
"network": "ARBITRUM_ONE"
}
headers = {
"x-qfex-hmac-signature": "<api-key>",
"x-qfex-nonce": "<api-key>",
"x-qfex-public-key": "<api-key>",
"x-qfex-timestamp": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'x-qfex-hmac-signature': '<api-key>',
'x-qfex-nonce': '<api-key>',
'x-qfex-public-key': '<api-key>',
'x-qfex-timestamp': '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({amount: 2, address: '<string>', network: 'ARBITRUM_ONE'})
};
fetch('https://banker.qfex.com/withdraw', 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://banker.qfex.com/withdraw",
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([
'amount' => 2,
'address' => '<string>',
'network' => 'ARBITRUM_ONE'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-qfex-hmac-signature: <api-key>",
"x-qfex-nonce: <api-key>",
"x-qfex-public-key: <api-key>",
"x-qfex-timestamp: <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://banker.qfex.com/withdraw"
payload := strings.NewReader("{\n \"amount\": 2,\n \"address\": \"<string>\",\n \"network\": \"ARBITRUM_ONE\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-qfex-hmac-signature", "<api-key>")
req.Header.Add("x-qfex-nonce", "<api-key>")
req.Header.Add("x-qfex-public-key", "<api-key>")
req.Header.Add("x-qfex-timestamp", "<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://banker.qfex.com/withdraw")
.header("x-qfex-hmac-signature", "<api-key>")
.header("x-qfex-nonce", "<api-key>")
.header("x-qfex-public-key", "<api-key>")
.header("x-qfex-timestamp", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"amount\": 2,\n \"address\": \"<string>\",\n \"network\": \"ARBITRUM_ONE\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://banker.qfex.com/withdraw")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-qfex-hmac-signature"] = '<api-key>'
request["x-qfex-nonce"] = '<api-key>'
request["x-qfex-public-key"] = '<api-key>'
request["x-qfex-timestamp"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"amount\": 2,\n \"address\": \"<string>\",\n \"network\": \"ARBITRUM_ONE\"\n}"
response = http.request(request)
puts response.read_bodyAuthorizations
HMAC-SHA256 signature (hex-encoded).
Unique request nonce (hex encoded, max 100 characters).
QFEX API Authentication requires these headers:
- x-qfex-public-key: Your public API key
- x-qfex-hmac-signature: HMAC signature of the request (hex encoded)
- x-qfex-nonce: Unique nonce for the request (hex encoded, max 100 characters)
- x-qfex-timestamp: Unix timestamp of the request
These four are required. Optionally send x-qfex-requested-account-id (UUID) to act as a subaccount; see Signature Generation below.
Signature Generation:
- Generate a cryptographically secure random nonce (hex encoded, max 100 characters) and capture the current Unix timestamp.
- Build the string
${nonce}:${unix_ts}and compute an HMAC-SHA256 using your secret key. - Hex-encode the HMAC result to get the signature.
- Send the required auth headers below. The nonce must be unique within a 15 minute window.
Important: The signature itself must be hex-encoded before being sent in the x-qfex-hmac-signature header.
Optional header: x-qfex-requested-account-id (UUID) selects a subaccount; omit it to use the primary account.
Unix timestamp (seconds since epoch).
Body
Response
Withdrawal accepted and debited. The response body is empty; on-chain settlement may still be pending or require manual review.