Yellow BoxTrading APIv1 · pre-release

Trade

Order Lifecycle

Base URL https://trade-api.yellowboxmarkets.com. Conventions, signing and error format: General Info.

Every endpoint on this page takes a mandatory login — the MT5 account the call applies to. See the login parameter model.

Endpoint Security Weight Counts against ORDERS
POST /v1/order TRADE 1 1
PUT /v1/order TRADE 1 1
DELETE /v1/order TRADE 1 1
GET /v1/order USER_DATA 1 —
GET /v1/openOrders USER_DATA 1 —
GET /v1/allOrders USER_DATA 5 —
GET /v1/positions USER_DATA 1 —
PUT /v1/position TRADE 1 1
DELETE /v1/position TRADE 1 1
DELETE /v1/allOpenPositions TRADE 5 1
POST /v1/batchOrders TRADE 1 per item 1 per item

Every TRADE endpoint answers -1017 while the trading surface is switched off, and -5015 when the execution path is not running — both before anything is queued and before the ORDERS bucket is charged. The USER_DATA reads on this page stay available in both cases.

Order lifecycle

Read this before writing any order code. The execution model is the one part of this API that has no Binance equivalent.

How an order reaches the market

An order is not executed inside the HTTP request. The API validates it, assigns it a client order id, and writes it to a durable queue. A trade executor drains that queue and issues the operation against the MT5 trade server. The fill is confirmed from the deal record the trade server produces.

That means the HTTP response tells you how far the order got by the time we answered — not necessarily its final state.

newOrderRespType

Value Behaviour
ACK Default. Recommended. Returns as soon as the order is durably queued. status is ACCEPTED for a market order and NEW for a pending order.
RESULT Waits up to 5 seconds for the trade server's answer, then returns the terminal state if it arrived.

newOrderRespType is accepted by POST /v1/order, DELETE /v1/position and POST /v1/batchOrders only; any other value than ACK or RESULT is -1130. PUT /v1/order, DELETE /v1/order and PUT /v1/position take no newOrderRespType and always behave like RESULT — they wait up to 5 seconds and then answer with whatever status the operation has reached. DELETE /v1/allOpenPositions always behaves like ACK.

With RESULT there are three outcomes:

Outcome HTTP Body
The server filled it 200 status: "FILLED" with dealId, orderId, positionId, price, executedVolume.
The server rejected it 4XX The error envelope plus status: "REJECTED", clientOrderId, login, and mt5RetCode.
No answer within 5 s 200 status: "ACCEPTED". The order has very likely executed. Confirm on the user data stream or with GET /v1/order.

Use ACK for bursts. One signal fanned across many accounts should be POST /v1/batchOrders with ACK; the fills arrive as DEAL and POSITION_UPDATE events.

Status values

Market execution (POST /v1/order with type=MARKET, DELETE /v1/position, DELETE /v1/allOpenPositions):

Status Meaning Terminal
ACCEPTED Durably queued. Not yet confirmed by the trade server. no
PARTIALLY_FILLED Part of the requested volume executed. executedVolume is what has filled so far; more DEAL events may follow. no
FILLED Executed. dealId / positionId are populated and executedVolume equals volume. yes
REJECTED The trade server refused it. mt5RetCode says why. yes
IN_DOUBT The operation may or may not have reached the trade server, and the service cannot determine which. Do not retry with a new client order id. Check GET /v1/positions and the user data stream; retrying the same newClientOrderId is safe. no

Pending orders (type other than MARKET):

Status Meaning Terminal
NEW Accepted. Reported from the moment the placement is durably queued, and while the order rests on the server. NEW alone does not prove the order reached the book — an ORDER_UPDATE with its orderId, or GET /v1/openOrders, does. no
PARTIALLY_FILLED Part of the volume has executed; the remainder is still resting. no
FILLED Fully executed. A position now exists. yes
CANCELED Cancelled by you or by the broker. yes
EXPIRED Reached its expiration. yes
REJECTED Refused at placement. yes

New status values may be added. Treat an unrecognised status as non-terminal and keep polling GET /v1/order.

executedVolume accumulates across deals. MT5 may fill one order with several deals. Each one arrives as its own DEAL event, and executedVolume on GET /v1/order is their sum while price is their volume-weighted average. Until the sum reaches the requested volume the status is PARTIALLY_FILLED; a redelivered deal never double-counts.

Idempotency

newClientOrderId is the idempotency key.

  • It must be unique per API key, up to 36 characters, [A-Za-z0-9-_.].
  • Resending a request with a newClientOrderId the key has already used never creates a second order. You get back the stored outcome — ACCEPTED if it is still in flight, or the terminal result if it has one.
  • This is what makes a retry after a timeout, a 503, or a dropped connection safe.

A retry is answered from the stored record, not re-validated. This matters most on the operations whose target moves: retrying a DELETE /v1/position whose position has since closed returns the stored FILLED outcome rather than -2023, and retrying a PUT /v1/order or PUT /v1/position whose change has already been applied returns the stored outcome rather than -5005. The same holds for POST /v1/order and every batchOrders item: a retried BUY_LIMIT whose price the market has since crossed returns its stored NEW (or later) outcome, not -2021. The response is built from the record, so a field the first response read from a live snapshot may be absent on the replay. A newClientOrderId this key already used for a different kind of operation (an id that placed an order, sent on a close) or for a different login is refused with -1133 on every endpoint — in a batch, as the error object in that item's slot — and is neither replayed as this operation nor executed again.

Always set it. If you omit it the service generates one, and you lose the ability to retry safely, because a retry then looks like a brand new order — including on DELETE /v1/position, PUT /v1/order, PUT /v1/position and DELETE /v1/allOpenPositions.

Idempotency records are retained for at least 24 hours. After that a reused id is treated as new.

What to do on each failure mode

Situation Do
Connection dropped, no response Retry the identical request, same newClientOrderId.
503 with "execution status is UNKNOWN" (-5009) Same: retry identically, or check GET /v1/order?origClientOrderId=. This also covers a failure to queue the order — it may still have been queued, so it is recorded as open, not rejected.
503 with -5015 "no connection to the trade server" on a TRADE endpoint The execution path is not running; nothing was queued and no order exists. Retry with backoff.
200 with status: "ACCEPTED" and no fill event after a few seconds GET /v1/order?origClientOrderId=. Do not send a second order.
GET /v1/order shows REJECTED with -1000 "Service is currently unavailable" The service could not queue the order within about a minute of accepting it (for example the trade executor was down), so it expired it unexecuted rather than send it late at a different price. Nothing executed. Retrying the same newClientOrderId sends it as a fresh order — decide against the current market first.
status: "IN_DOUBT" Reconcile against GET /v1/positions before doing anything else.
4XX with a validation code (-11xx, -40xx) Fix the request. The order does not exist.
4XX with -5001 (requote) or -5002 (price changed) The order did not execute. Re-price and send a new newClientOrderId.

Comments and deal attribution

The MT5 comment field is how an execution is traced back to the request that caused it, so the service reserves part of it.

  • Your comment may be up to 24 characters.
  • The service appends a short correlation tag, making the stored MT5 comment <your comment><tag>. The tag is 7 characters and is not documented as a parseable format — do not build against it.
  • On the user data stream, DEAL.c is the MT5 comment as stored, tag included. Strip the last 7 characters to recover what you sent, or simply ignore c and use C.
  • DEAL.C is the resolved clientOrderId — the field to route on. The service resolves it from the tag, or directly from the trade server's answer when the server provides one.
  • The tag is also set on closes and SL/TP modifications this API issues, so DEAL.c on an API-initiated close carries a tag too, and that close is attributable to the newClientOrderId you sent on DELETE /v1/position.

A deal produced by the account holder, the broker, or a stop loss or take profit firing carries no tag. Those deals arrive with no C, which is how you tell them apart from your own.

Hedging

Positions are hedged. A BUY on a symbol that already has a SELL position opens a second, independent position with its own positionId; it does not net against the first. Closing is always by positionId.

There is no positionSide parameter and no netting mode.