Error Codes
Every error this API returns.
{"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:
{"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:
- Retry the identical request with the same
newClientOrderId. Idempotency guarantees you get the stored outcome, not a second order. - Or, if you did not set a client order id, call
GET /v1/positionsandGET /v1/userTradesand 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 |


