Documentation Index Fetch the complete documentation index at: https://docs.qfex.com/llms.txt
Use this file to discover all available pages before exploring further.
All websocket channels may return an error frame instead of the expected response. Error frames share a single, consistent schema.
Error Envelope
{
"err" : {
"error_code" : "RateLimited" ,
"message" : "You have exceeded the allowed message rate." ,
"incoming_message" : {
"type" : "add_order" ,
"params" : {
"symbol" : "AAPL" ,
"side" : "BUY" ,
"order_type" : "LIMIT" ,
"order_time_in_force" : "GTC" ,
"quantity" : 10.0 ,
"price" : 200.0 ,
"client_order_id" : "my-order-001" ,
"take_profit" : null ,
"stop_loss" : null
}
}
}
}
Fields
Field Type Required Description error_codestring Yes Machine-readable error code (see list below). Matches server enum variant exactly. messagestring/null No Human-readable context. May be null. incoming_messageobject/null No Echo of the request that caused the error (your original message), when available.
Note: incoming_message uses the same tagged format as requests ({ "type": "<snake_case>", "params": { ... } }).
Error Codes
These values map 1:1 to the server enum:
Code When it happens Suggested Client Action RateLimitedYou’ve exceeded the allowed message rate (weighted per message type). Backoff and retry later. Consider batching and respecting published limits. InvalidJSONFormatMessage is not valid JSON or doesn’t match the expected schema. Validate JSON and schema before sending. Include required fields and correct types/enum values. AlreadyAuthenticatedYou attempted to authenticate again after a successful auth on the same connection. Do not re-auth on an already authenticated socket. InvalidParameterOne or more parameters are out of range, missing, or invalid for the specified message. Correct the parameter(s) and retry. PermissionDeniedThe API key or user lacks permission for the requested action. Check key scopes/roles; contact support if needed. ServerErrorUnexpected internal error. Safe to retry after a short delay; if persistent, contact support with timestamp and incoming_message. InvalidOrderThe order is invalid or malformed. Check order parameters and format; correct the order and retry. AlreadySubscribedToLeaderboardThe user is already subscribed to a leaderboard. Do not attempt to subscribe again; check current subscriptions first. TncRequiredThe user needs to agree to the latest Terms and Conditions. Agree to the latest Terms and Conditions.
Rate limiting notes
The server computes message weight by the message "type" (e.g., "add_order", "cancel_order") and applies limits over a sliding window. Some messages are heavier than others. If you see RateLimited, delay and reduce frequency; prefer fewer, larger requests when possible.
Examples
1) Invalid JSON
{
"err" : {
"error_code" : "InvalidJSONFormat" ,
"message" : "Expected field `symbol` (string)." ,
"incoming_message" : {
"type" : "add_order" ,
"params" : {
"side" : "BUY" ,
"order_type" : "LIMIT" ,
"order_time_in_force" : "GTC" ,
"quantity" : 10.0 ,
"price" : 200.0
}
}
}
}
2) Already authenticated
{
"err" : {
"error_code" : "AlreadyAuthenticated" ,
"message" : "Connection is already authenticated." ,
"incoming_message" : { "type" : "auth" , "params" : { ... } }
}
}
3) Invalid parameter
{
"err" : {
"error_code" : "InvalidParameter" ,
"message" : "price must be >= min_tick and within price bands." ,
"incoming_message" : {
"type" : "modify_order" ,
"params" : {
"symbol" : "AAPL" ,
"order_id" : "cd1a2b0c-...-f3" ,
"quantity" : 10.0 ,
"price" : 0.0001 ,
"take_profit" : 0.0 ,
"stop_loss" : 0.0 ,
"side" : "BUY"
}
}
}
}
4) Permission denied
{
"err" : {
"error_code" : "PermissionDenied" ,
"message" : "API key does not allow trading on this account." ,
"incoming_message" : {
"type" : "transfer_balance" ,
"params" : { "amount" : 100.0 , "to_api_key" : "****" }
}
}
}
5) Rate limited
{
"err" : {
"error_code" : "RateLimited" ,
"message" : "Too many requests. Please retry after 200ms." ,
"incoming_message" : { "type" : "cancel_all_orders" , "params" : {} }
}
}
6) Server error
{
"err" : {
"error_code" : "ServerError" ,
"message" : "Unexpected error processing request." ,
"incoming_message" : { "type" : "get_user_trades" , "params" : { "limit" : 50 } }
}
}
Client Handling Patterns
import json
import websocket
def on_message ( ws , message ):
msg = json.loads(message)
if msg.get( "type" ) == "error" :
code = msg.get( "error_code" )
print ( f "[ERROR] { code } : { msg.get( 'message' ) } " )
# basic strategy
if code == "RateLimited" :
# implement backoff before retrying your last request
return
elif code in ( "InvalidJSONFormat" , "InvalidParameter" ):
# fix your payload; don't auto-retry
return
elif code in ( "PermissionDenied" , "AlreadyAuthenticated" ):
# adjust flow; no retry
return
else :
# ServerError or unknown: small backoff and optional retry
return
else :
print ( "OK:" , msg)
import WebSocket from "ws" ;
const ws = new WebSocket ( "wss://trade.qfex.com?api_key=YOUR_API_KEY" );
ws . on ( "message" , ( raw ) => {
const msg = JSON . parse ( raw . toString ());
if ( msg . type === "error" ) {
const { error_code , message } = msg ;
console . error ( `[ERROR] ${ error_code } : ${ message || "" } ` );
switch ( error_code ) {
case "RateLimited" :
// schedule retry w/ backoff
break ;
case "InvalidJSONFormat" :
case "InvalidParameter" :
// fix payload, do not blind-retry
break ;
case "PermissionDenied" :
case "AlreadyAuthenticated" :
// update client state/flow
break ;
default :
// transient server error: optional retry with jitter
break ;
}
return ;
}
// handle normal messages…
});
type ErrorFrame struct {
Type string `json:"type"`
ErrorCode string `json:"error_code"`
Message * string `json:"message,omitempty"`
IncomingMessage json . RawMessage `json:"incoming_message,omitempty"`
}
func handleMessage ( raw [] byte ) {
// peek at "type"
var meta struct { Type string `json:"type"` }
if err := json . Unmarshal ( raw , & meta ); err != nil { return }
if meta . Type == "error" {
var ef ErrorFrame
if err := json . Unmarshal ( raw , & ef ); err == nil {
log . Printf ( "[ERROR] %s : %s " , ef . ErrorCode , deref ( ef . Message ))
// handle per code...
}
return
}
// normal flow...
}
Authentication & Errors
trade.qfex.com requires authentication within 1 minute of connecting.
Attempting to re-authenticate an already authenticated connection yields AlreadyAuthenticated.
Troubleshooting Checklist
Validate JSON (types/enums/required fields).
Respect rate limits (reduce burstiness; batch where possible).
Ensure your API key has the right permissions.
Log incoming_message from error frames to quickly reproduce issues.
For persistent ServerError, contact support@qfex.com with timestamp and offending incoming_message.