Change Log
Newest first. Backward-compatibility rules: general-info.md § Versioning.
Changes that only add a field, an enum value, an endpoint or a stream are listed here but are not breaking — your client must already tolerate them.
v1.0.0 (draft) — documentation verified against the implementation, 2026-10-08
No behaviour changed; the documentation was corrected to match what the service does.
- New page: Known limitations (pre-release) — the first session against
the new trade server: no dealer answer (non-market operations stay
ACCEPTED/NEW),origClientOrderIddoes not resolve a pending order for modify / cancel / query, cancels fail on the server,GET /v1/userTradesis empty on staging, and the server reports a UTC+3 offset. DELETE /v1/ordertakesnewClientOrderId(idempotency key for the cancel); its response carriesclientOrderIdandside.PUT /v1/position's response carriesclientOrderId.DELETE /v1/positionhas noprofitfield — the realised profit is on theDEALevent (rp) andGET /v1/userTrades.- Order responses omit
sl,tpandexpirationwhen none is set (they were shown as"0"/0).GET /v1/orderandGET /v1/openOrdersstill always carry them. - A pending order is
NEWfrom the moment it is queued, including onACK;PUT /v1/order,DELETE /v1/orderandPUT /v1/positionalways wait up to 5 s likeRESULT. fillModesnever containsRETURN. Unmapped MT5 values appear asUNKNOWN_<n>.marginLevelis"0.00"(two decimals) with no open position.- Error details documented:
-1106fortimeInForceonMARKETand for a straystopLimitPrice,-1130for a malformedtimestamp/recvWindow,-1128forendTimebeforestartTime, batch envelope errors (-1130,-1131,-1132), WebSocket control-frame codes and close codes. Codes in the catalogue that are not currently returned are listed under error-codes.md § Reserved codes.
v1.0.0 (draft) — second hardening pass, 2026-09-24
Still draft and pre-launch; listed because each is observable.
-1133onPOST /v1/orderand on eachPOST /v1/batchOrdersitem. AnewClientOrderIdyour key already used for a different kind of operation — or for a differentlogin— is refused (in a batch, as the error object in that item's slot). The login rule now applies to every endpoint that takesnewClientOrderId, includingDELETE /v1/allOpenPositions.- A retried
POST /v1/orderis answered from the stored record before any validation. A retried limit order whose price the market has since crossed returns its stored status instead of-2021. - An internal fault in the trade executor is reported as
IN_DOUBT(-5009), never as a retryable-1000: the order may have been sent. Retry only with the samenewClientOrderId. - Orders that could not be queued within about a minute are expired, not sent late. They read
REJECTEDwith-1000"Service is currently unavailable" onGET /v1/order; nothing executed. Retrying the samenewClientOrderIdsends it as a fresh order. If such an order did reach the trade server after all, its fill still lands and the record changes toFILLED. - A
REJECTEDorder can still becomeFILLEDwhen its rejection was the execution path's own refusal (nomt5RetCode) and a later attempt under the samenewClientOrderIdexecuted. A rejection carrying anmt5RetCodeis final, as before. POST /v1/batchOrdersanswers-5015when the execution path is not running, before any item is queued or charged — like every other TRADE endpoint. A trade executor that stopped reading its queue is now detected within about 30 seconds.DELETE /v1/allOpenPositionsretries complete an interrupted sweep. A position in the original snapshot whose close was never queued is closed on the retry if it is still open, and reportedREJECTED(-5006) if it has closed since. A concurrent identical sweep returns the first sweep's snapshot.C(clientOrderId) onDEAL/ORDER_UPDATEis only published to the key that owns it. Where two keys share a login, the other key receives the event withoutC.GET /v1/accountsand the user data stream list exactly the logins the REST endpoints accept. An archived account is no longer listed or streamed.- Market-stream connections are capped at 20 concurrent per client IP (and by overall capacity);
an excess connection is refused before the upgrade with
-1008. - A user data stream is also closed (
1011) when the server's own intake falls behind for your logins, not only when your connection reads too slowly.
v1.0.0 (draft) — clarifications, 2026-09-19
Still draft, still pre-launch, so none of this is a breaking change to a live client. Listed because each one is behaviour an integrator can observe.
PARTIALLY_FILLEDis now a market-execution status.POST /v1/orderwithtype=MARKET,DELETE /v1/positionand eachDELETE /v1/allOpenPositionsleg can report it.executedVolumeis the sum of the deals that have filled the order andpricetheir volume-weighted average; the status becomesFILLEDwhen the sum reaches the requestedvolume. Previously a partial fill was reported asFILLEDwith the volume you requested.DELETE /v1/allOpenPositionsretries replay the original snapshot. Reusing anewClientOrderIdreturns the first sweep's legs and closes nothing opened since — including after a sweep that found nothing, which staysrequested: 0. A fresh sweep needs a fresh id.PUT /v1/order:timeInForceis conditionally mandatory. It is required when the service cannot determine the order's current expiration mode — typically an order this API did not place.-1102rather than a guess, because a guess would rewrite aDAYorder asGTC.- Retries of
PUT/DELETE /v1/order,PUT/DELETE /v1/positionare answered from the stored record, not re-validated: a retried close whose position has since closed returns its storedFILLEDoutcome instead of-2023, and a retried modify returns its stored outcome instead of-5005. - A failure to queue an order answers
-5009(execution status UNKNOWN), not-1000: the write may have landed before the error surfaced, so the order is recorded as still open and can still fill. Retry it identically, samenewClientOrderId. - TRADE endpoints answer
-5015when the execution path is not running, before any order is created — instead of accepting an order that would sit queued indefinitely. - A user data stream that falls too far behind is CLOSED (
1011, "queue overflow; resnapshot") rather than silently dropping events. Reconnect and resnapshot via REST, as documented. - A user data stream stops delivering for a login that leaves the key's scope, within about 30 seconds, instead of at the listenKey's 24-hour expiry. The socket closes when nothing remains in scope.
- A malformed control frame no longer closes the connection. A wrong-typed
methodorparamsitem answers the documented error frame and the socket stays open.
v1.0.0 (draft) — initial contract
Status: draft. The service is being built to this document. Endpoints, field names and error codes are the contract; base URLs are placeholders pending DNS. Nothing is live yet.
REST
- General:
GET /v1/ping,GET /v1/time,GET /v1/exchangeInfo. - Market data:
GET /v1/ticker/price,GET /v1/ticker/bookTicker,GET /v1/ticker/24hr,GET /v1/klines,GET /v1/ticks. - Trade:
POST /v1/order,PUT /v1/order,DELETE /v1/order,GET /v1/order,GET /v1/openOrders,GET /v1/allOrders,GET /v1/positions,PUT /v1/position,DELETE /v1/position,DELETE /v1/allOpenPositions,POST /v1/batchOrders. - Account:
GET /v1/account,GET /v1/accounts,GET /v1/userTrades. - User data stream:
POST /v1/listenKey,PUT /v1/listenKey,DELETE /v1/listenKey.
WebSocket
- Market streams:
<SYMBOL>@tick,<SYMBOL>@bookTicker,<SYMBOL>@kline_<interval>,<SYMBOL>@ticker,<SYMBOL>@depth(optional, enabled on request). - User data stream events:
DEAL,ORDER_UPDATE,POSITION_UPDATE,ACCOUNT_UPDATE,listenKeyExpired.
Model
- Binance-style conventions:
X-YBX-APIKEY, HMAC-SHA256 over query string + body,recvWindow, weight and order-count headers, 429 → 418 escalation,{"code","msg"}errors, SUBSCRIBE/UNSUBSCRIBE/LIST_SUBSCRIPTIONS, combined{"stream","data"}frames. - MT5 semantics: lots, bid/ask, tickets, SL/TP on the position, swaps. No mark price, no funding, no liquidation engine.
- Hedging only — many position tickets per symbol, no
positionSide. - A mandatory
loginon every account-scoped call — one key trades many MT5 accounts. The one deliberate departure from Binance's key-is-an-account model. newClientOrderIdis the idempotency key. A retry with the same id never creates a second order.- Order lifecycle:
newOrderRespTypeACK(default) /RESULT, withACCEPTED,FILLED,REJECTEDandIN_DOUBTstatuses for market executions. mt5RetCodepassthrough on execution errors.- Sandbox is demo-group MT5 logins on the same endpoints — there is no separate testnet host.
Known limits in v1
- No account provisioning. Accounts are created by the broker.
- No deep tick history —
GET /v1/ticksserves an in-memory ring buffer. - No
1w/1Mkline intervals;1dbuckets are UTC-aligned, not broker-session aligned. ACCOUNT_UPDATEcarries balance and credit only; equity and margin needGET /v1/account.- No commission on an open position. Commission is booked on deals — read it from
GET /v1/userTradesor theDEALevent'snfield.GET /v1/positionscarriesprofitandswaponly. - The trading surface can be switched off independently of market data and account reads;
TRADEendpoints and the user data stream then return-1017. bookTickersizes are always"0"— MT5 quotes carry no top-of-book size.@depthis off unless the broker enables it for the symbol. Subscribing always succeeds and then delivers nothing — silence means "not enabled", not "not subscribed".GET /v1/exchangeInfois not filtered to your key's scope. Sending your key changesrateLimits[]only; the symbol list is every instrument on the trade server, because the Manager API has no bulk per-group symbol read.GET /v1/userTradesreturns closing deals only (entryisOUT,INOUTorOUT_BY, neverIN), and itssideis the direction as stored by the broker's history writer, which is not always the deal's own direction. Use theDEALevent'sSfor an unambiguous deal direction.- On
ORDER_UPDATE,tifis inferred (GTDwhen an expiration is set,GTCotherwise —DAYandGTD_DAYare not distinguishable),spis always"0", andotmay beBUY/SELLfor a market order passing through the book. ticker/24hr.priceChangePercent(and@ticker'sP) has two provenances — the trade server's own statistic on the read path, derived from open/last on the streamed path. They agree to rounding.- A market-data or account read that cannot reach the trade server returns
-5015with nomt5RetCode.


