Yellow BoxTrading APIv1 · pre-release

Error Codes

Every error this API returns.

JSON
{"code":-1121,"msg":"Invalid symbol."}
Field Type Description
code INT Negative integer. Stable — branch on this.
msg STRING English text. Informational; wording may change. Never parse it.
mt5RetCode INT Present only when the trade server answered. Raw MT5 return code — see Common Definition.

When an order endpoint (POST /v1/order, PUT /v1/order, DELETE /v1/order, PUT /v1/position, DELETE /v1/position, POST /v1/batchOrders items) recorded the operation and it was then rejected, the error body carries three additional fields so the failure can be correlated without a second lookup:

JSON
{"code":-2018,"msg":"Insufficient margin on the trading account.","mt5RetCode":10019,"status":"REJECTED","clientOrderId":"bot-003","login":100123}

A request refused before anything was recorded (a validation, scope or rate-limit error) carries only code and msg — plus, inside a POST /v1/batchOrders response, the item's login and clientOrderId where they could be read.

New codes may be added at any time. Treat an unknown code in the -10xx/-11xx range as "my request is wrong, do not retry", and an unknown code in the -50xx range as "execution problem, status may be unknown".

-10xx — General, server and network

Something went wrong that is not about the content of your request.

Code msg HTTP Notes
-1000 Unknown error, please check your request or try again later. The execution status is UNKNOWN and could have been a success. 503 May have executed. Confirm before retrying. See the 503 semantics.
-1000 Service is currently unavailable, please try again later. 503 Did not execute. Retry with backoff. Same code, different message — read msg. Also the stored outcome of an order the service could not queue within its dispatch window (GET /v1/order shows REJECTED with this code): it never executed, and retrying the same newClientOrderId sends it as a fresh order.
-1001 Internal error; unable to process your request. Please try again. 500
-1002 You are not authorized to execute this request. 401 Missing or malformed X-YBX-APIKEY header.
-1003 Too many requests; current limit is %s requests per minute. Please use the WebSocket streams for live updates to avoid polling. 429 Retry-After carries the wait. A repeat breach escalates to HTTP 418.
-1006 An unexpected response was received from the trade server. Execution status is UNKNOWN. 503 Confirm before retrying.
-1007 Timeout waiting for response from the trade server. Execution status is UNKNOWN. 504 Confirm before retrying.
-1008 Server is currently overloaded with other requests. Please try again in a few minutes. 503 Did not execute. Also refuses a market-stream WebSocket connection over the per-IP or service-wide connection limit, before the upgrade.
-1014 Unsupported order combination. 400 The parameters are individually valid but cannot be combined.
-1015 Too many new orders; current limit is %s orders per %s. 429 The ORDERS bucket, not REQUEST_WEIGHT.
-1016 This service is no longer available. 410 A retired endpoint. Permanent; do not retry.
-1017 Trading is temporarily disabled on this API. Retry later. 503 The trading surface is switched off. Market data, market streams and account reads stay available. Retryable — retry with backoff, and alert if it persists.
-1020 This operation is not supported. 400 A plain HTTP request to a WebSocket URL, or an unknown WebSocket control method.
-1021 Timestamp for this request is outside of the recvWindow. 400 Clock drift, or a request that sat in a queue too long. Sync against GET /v1/time.
-1022 Signature for this request is not valid. 401 Almost always a totalParams mismatch — re-encoding after signing, or splitting parameters between query and body.

-11xx — Request and validation

Your request is malformed. Fix it; do not retry unchanged.

Code msg HTTP
-1100 Illegal characters found in a parameter. 400
-1101 Too many parameters sent for this endpoint. 400
-1102 A mandatory parameter was not sent, was empty/null, or malformed. 400
-1103 An unknown parameter was sent. 400
-1104 Not all sent parameters were read. 400
-1105 A parameter was empty. 400
-1106 A parameter was sent when not required. 400
-1111 Precision is over the maximum defined for this symbol. 400
-1115 Invalid timeInForce. 400
-1116 Invalid order type. 400
-1117 Invalid side. 400
-1118 New client order ID was empty. 400
-1119 Client order ID is too long or contains illegal characters. 400
-1120 Invalid interval. 400
-1121 Invalid symbol. 400
-1122 Invalid login. 400
-1125 This listenKey does not exist. 400
-1127 Lookup interval is too big. 400
-1128 Combination of optional parameters invalid. 400
-1130 Invalid data sent for a parameter. 400
-1131 batchOrders must contain between 1 and 100 items. 400
-1132 Duplicate client order ID in batch. 400
-1133 Client order ID was already used by a different operation. 400

-1102 covers a missing timestamp; a timestamp or recvWindow that is present but not an integer — or a recvWindow outside 1–60000 — is -1130. A present-but-unparseable numeric or decimal parameter, a limit outside its range and an unknown newOrderRespType are -1130 too.

-1106 is returned when timeInForce is sent on a MARKET order, or stopLimitPrice on an order that is not a stop-limit.

-1121 is also what a WebSocket SUBSCRIBE returns for a stream name whose symbol does not exist — including one that differs only in case.

-1122 means the login value is not a valid int64. A login that exists but is not yours is -2022.

-1133 is returned on every endpoint that takes newClientOrderId — including POST /v1/order and each POST /v1/batchOrders item (as the error object in that item's slot) — when your key already used that id for a different kind of operation or for a different login. Nothing is executed and nothing is replayed.

-20xx — Processing and authorization

The request is well-formed but cannot be carried out.

Code msg HTTP Notes
-2010 New order was rejected. 400 Generic placement rejection where no more specific code applies.
-2011 Cancel was rejected. 400
-2013 Order does not exist. 400 Also returned for an order belonging to a different login — never a permission error.
-2014 API-key format invalid. 401
-2015 Invalid API-key, IP, or permissions for action. 401 Unknown key, revoked key, source IP not allowlisted, or a read-only key on a TRADE endpoint. Deliberately not distinguished.
-2018 Insufficient margin on the trading account. 400 MT5 10019.
-2021 Order would immediately trigger. 400 A pending price on the wrong side of the market.
-2022 Login is not in this API key's scope, or the account is not tradable. 400 Deliberately ambiguous: not in this key's scope, does not exist, the owner is inactive, or the account is not active. A key cannot probe for logins it does not own. Not returned merely because trading is disabled — that is -2024.
-2023 Position does not exist. 400 Also returned for a position on a different login.
-2024 Trading is disabled for this account. 400 The account exists and is in scope, but trading on it is forbidden. Returned by the operations that TRADE; reads such as GET /v1/account still succeed and report tradeAllowed: false.

-40xx — Filters and symbol rules

The request violates a symbol specification or a group limit. Every one of these is checkable against GET /v1/exchangeInfo before you send.

Code msg HTTP mt5RetCode
-4001 Price less than 0. 400
-4002 Invalid price. 400 10015
-4003 Volume less than 0. 400
-4004 Invalid volume. 400 10014
-4005 Volume greater than volumeMax for this symbol. 400
-4006 Volume less than volumeMin for this symbol. 400
-4007 Volume is not a multiple of volumeStep for this symbol. 400
-4008 Price is not a multiple of tickSize for this symbol. 400
-4009 Stop levels are too close to market. 400 10016
-4010 Market is closed for this symbol. 400 10018
-4011 Trading is disabled for this symbol. 400 10017
-4012 Invalid order expiration. 400 10022
-4013 Only long positions are allowed for this symbol. 400 10042
-4014 Only short positions are allowed for this symbol. 400 10043
-4015 Only position closing is allowed for this symbol. 400 10044
-4016 This order type is not allowed for this symbol. 400
-4017 Fill mode is not supported for this symbol. 400 10030
-4018 Order limit reached for this account. 400 10033
-4019 Position limit reached for this account. 400 10040
-4020 Volume limit reached for this account. 400 10034
-4021 Order or position is too close to market to be modified. 400 10029
-4022 Hedge positions are prohibited for this account. 400 10046
-4023 Position closure is not allowed by the FIFO rule. 400 10045
-4024 Volume to close exceeds the current volume of the position. 400 10038
-4025 An order to close this position already exists. 400 10039

-4005, -4006, -4007, -4008 and -4009 are raised before the trade server is contacted where the service can determine them from the symbol specification, so they usually carry no mt5RetCode. The same violation caught by the server carries one.

-50xx — Execution

The trade server was reached and something happened during execution. These are the codes where mt5RetCode is normally present.

Code msg HTTP mt5RetCode Did it execute?
-5001 Requote. 400 10004 No. Re-price and resend with a new client order id.
-5002 Price has changed. 400 10020 No.
-5003 No price available for this symbol. 400 10021 No.
-5004 Order has been changed. 400 10023 No — your modification raced another change. Re-read and retry.
-5005 Request does not contain changes. 400 10025 No.
-5006 Position is already closed. 400 10036 No — it was already gone.
-5007 The trade server rejected the request. 400 10006, 10011 No.
-5008 The trade server did not answer in time. Execution status is UNKNOWN — confirm via the user data stream or GET /v1/order before retrying. 504 10012 Unknown.
-5009 Execution status is UNKNOWN. Confirm via the user data stream or GET /v1/order before retrying. 503 Unknown. Retrying the same newClientOrderId is safe; a new one is not.
-5010 Request canceled by the trade server. 400 10007 No.
-5011 The trade server is rejecting new requests. Retry shortly. 503 10024 No. Back off.
-5012 Autotrading is disabled on the trade server. 400 10026, 10027 No. Operator action required.
-5013 Request blocked by the dealer. 400 10028 No.
-5014 Allowed only for real accounts. 400 10032 No.
-5015 No connection to the trade server. 503 10031 No. Retry with backoff. Also returned when a read cannot reach the trade server — an uncached market-data or account snapshot — in which case there is no mt5RetCode; and by every TRADE endpoint, POST /v1/batchOrders included, when the execution path is not running, before any order is created.
-5016 Invalid or prohibited order type. 400 10035 No.
-5017 Invalid request. 400 10013 No.
-5018 Request rejected, order canceled. 400 10041 No — a broker routing rule cancelled it.

Reading -5008 and -5009

These two are the only codes that mean "we do not know". Everything else is definitive.

-5009 also covers a failure to write the order to the execution queue: the write may have landed before the error surfaced, so the operation is recorded as still open rather than rejected, and the order can still fill. Retry it the same way as any other -5009 — identically, same newClientOrderId. The same holds for an internal fault in the trade executor after the request may have been sent: the order is recorded IN_DOUBT with -5009, never as a retryable -1000.

The safe recovery is identical for both:

  1. Retry the identical request with the same newClientOrderId. Idempotency guarantees you get the stored outcome, not a second order.
  2. Or, if you did not set a client order id, call GET /v1/positions and GET /v1/userTrades and reconcile before doing anything else.

Never respond to -5008 or -5009 by sending the same order with a new client order id. That is how a position gets opened twice.

Reserved codes

These codes are part of the catalogue so a client can model them, but the current implementation does not return them: -1000 with the "execution status is UNKNOWN" message (unknown outcomes are reported as -5008 / -5009), -1006, -1007, -1014, -1103, -1104, -1105, -1111, -2011 and -2014 (an unrecognised key of any format is -2015). Handle them as their family describes; they may start appearing without notice.

Quick index

Range Family Retry?
-1000, -1006, -1007 Unknown execution status Only with the same client order id, after confirming
-1001, -1008, -1017 Server-side, no execution Yes, with backoff
-1003, -1015 Rate limit After Retry-After
-1002, -1021, -1022, -2014, -2015 Authentication No — fix credentials or clock
-11xx Malformed request No — fix the request
-2013, -2022, -2023 Not found / not in scope No
-2010, -2018, -2021, -2024 Rejected, did not execute Not unchanged — fix the cause first
-40xx Symbol or group rule No — check GET /v1/exchangeInfo
-5001 … -5007, -5010 … -5018 Execution, definitively did not happen Yes, as a new order
-5008, -5009 Execution status unknown Only with the same client order id