Skip to navigation

Cancel order

Name the order by orderId or by clientOrderId, exactly one.

URL — No public environment serves this socket yet.

Op cancelOrder

Neither is refused — there is nothing to cancel; both is refused too, for the same reason account and accountId are.

clientOrderId exists for the window where a submit has been offered but its QUEUED fact has not reached this member yet, so you hold no orderId. In that window the ack’s orderId is null and the owner resolves the order itself; any refusal then arrives as orderRejected carrying your clientOrderId, so the command is correlatable either way.

Switch on command, not on clientOrderId alone. A refused cancel arrives as orderRejected carrying the order’s clientOrderId — the same key a refused submit would carry — so a client matching on the key alone will show a cancel’s refusal as though the order had never been placed. orderRejected.command is SUBMIT or CANCEL and is what tells them apart.

A cancel can also fail a second way: the venue rejects it, which arrives on the order channel as an orderUpdate with transition: CANCEL_REJECTED rather than as an orderRejected. The owner’s refusal and the venue’s are different events; handle both or a failed cancel will sometimes look like silence.

Request parameters

ParameterTypeRequiredDescription
opstringYescancelOrder
reqIdstringYesEchoed byte-exact on the answer. Printable ASCII, escape-free; anything else answers MALFORMED.
paramsobjectYes
> orderIdstringNoThe order’s id — a decimal string, the same form this API renders it in. A JSON number is refused: an int64 does not survive one in a JavaScript client, so the id you read off an orderUpdate is the id you hand back.
> clientOrderIdstringNoYour idempotency key and your correlation handle, 1-36 characters. Every answer about an order before it has an orderId carries it back — the submitOrder ack does not, because none has been minted, so this is the only handle you hold until the owner admits it. The bound is the platform’s own (OrdersView.CLIENT_ORDER_ID_MAX_LENGTH), not this edge’s, and a contract test holds the two equal. It is 36 rather than 64 because a canonical hyphenated UUID fits in 36 and the owner refuses longer as INVALID_FIELD; an id over it is refused here first, as INVALID_CLIENT_ORDER_ID, so the refusal names the field rather than arriving from the owner a round trip later. What the key deduplicates against, exactly. It is scoped to (organization, clientOrderId) and held for as long as the platform retains the order — the retention window, not merely while the order is live. Re-sending a submit under a key you already used restates the existing order’s outcome and never places a second order, which is what makes it safe to retry. CLIENT_ORDER_ID_CONFLICT does not mean “you reused your own key”: it means another user of your organization holds that key, and your submit was not applied. Recovering an outcome you never saw. If the socket drops after a submitOrder ack and you cannot tell whether the order was admitted — it is absent from the order image, which reads the same for “refused” and “not folded here yet” — re-send the identical submit under the same clientOrderId. That is the recovery procedure, not a risk: you get the original order’s outcome if it was admitted, and a fresh attempt if it was not. Minting a new key instead is what risks two orders. Separately, a refusal answer to a write guarantees that nothing reached the stream — the command was never published — so re-sending is always safe.

Response parameters

Offered, like a submit. orderId echoes the order this edge resolved, and is null when you named a clientOrderId this member has not folded yet — the owner resolves it from its own pending book. A null here is not a failure.

ParameterTypeRequiredDescription
opstringYescancelOrder
reqIdstringYesEchoed byte-exact on the answer. Printable ASCII, escape-free; anything else answers MALFORMED.
successbooleanYestrue
orderIdstring, nullableYesThe resolved order as a decimal string, or null.

Refusal parameters

ParameterTypeRequiredDescription
opstringYesThe op being answered, or “error” when it could not be read.
reqIdstring, nullableYes
successbooleanYesfalse
codestringYesA closed enum, but tolerate an unknown value: codes are appended as the surface grows, and retryable tells you what to do whatever the code says. The door’s codes — INVALID_*, UNKNOWN_INSTRUMENT, UNKNOWN_ACCOUNT, UNKNOWN_ORDER, NOT_SERVING, OWNER_ABSENT, BACKPRESSURE — arrived in 1.1.0 beside the ops that write, and are the whole of what that version added here. A client generated against 1.0.0 meets them the first time it sends a write. OWNER_ABSENT is reserved and not emitted by this version: when the orders owner is not established, a write refuses NOT_SERVING today. It is published so that a client’s handling of it is written once rather than added later, but do not expect to observe it before a release says otherwise. One of NOT_PRIMED, UNAUTHENTICATED, SESSION_EXPIRED, RATE_LIMITED, MALFORMED, UNKNOWN_OP, INVALID_TOKEN, FORBIDDEN_PRINCIPAL, ORG_NOT_ACTIVE, AWAITING_ADMISSION, FORBIDDEN_CAPABILITY, UNKNOWN_TOPIC, TOPIC_NOT_ACTIVE, TOO_MANY_TOPICS, INVALID_FIELD, INVALID_PRICE, INVALID_QTY, INVALID_CLIENT_ORDER_ID, UNKNOWN_INSTRUMENT, UNKNOWN_ACCOUNT, UNKNOWN_ORDER, NOT_SERVING, OWNER_ABSENT, BACKPRESSURE.
messagestringYesDisplay text. May change between versions; never parse it.
retryablebooleanYes
failedTopicIndexintegerNoPresent on a topic refusal: the zero-based index into params.topics AS SENT of the entry that caused it.