PATCH /orders/{orderId}, no need to cancel and re-place, and the order keeps its orderId. Like cancelling, updating requires a wallet signature in addition to your API key: you construct a short plaintext message, sign it with the funder wallet, and send both with the new price(s). The update signature is offchain and gasless; no transaction is sent, and the original order signature and token approval stay untouched.
What can be updated
An update carries a new limit price, a new trigger price, or both, depending on the order type:
A
bracket cannot be updated: the request returns 422. Cancel it and place a new one.
Limit price — send exactly one of limitNotionalPrice (USD price of the target asset) or limitCrossPrice (pair rate, target / contra). You are not restricted to the basis the order was placed with; the order carries whichever basis was set last. On the trigger types the limit is the post-trigger execution limit: the price the order fills at once the trigger has fired. See Pricing basis.
Trigger price — send a trigger object with the same shape as submit’s: exactly one of notionalPrice or crossPrice, plus triggerType (lower or upper). A trigger update moves the threshold only:
To change any other parameter of an order, cancel it and place a new one.
The update message
Construct this exact UTF-8 string — a three-line header followed by one price line per updated value, joined by single newlines:- The separator in the header is an em dash (
—, U+2014), not a hyphen. Unlike the cancel header, there is nov1— don’t copy the header from your cancel flow. - Line breaks are single
\ncharacters. CRLF, blank lines, and a trailing newline are all rejected. <orderId>is the order’s UUID exactly as returned byPOST /order.Issued Atis an RFC3339 UTC timestamp and must be within 1 minute of server time — construct and sign the message immediately before sending. The stamp is what stops a captured signature from being replayed later to revert a newer price. Sub-second precision (e.g.new Date().toISOString()) is supported and recommended: two updates on the same order in the same second need distinct stamps to produce distinct signed bytes.- The Limit line is exactly one of
Limit Cross Price: <decimal>orLimit Notional Price: <decimal>, matching the limit field you send in the request body. - The Trigger line is
Trigger <Lower|Upper> <Cross|Notional> Price: <decimal>— direction matching thetrigger.triggerTypeyou send (lower→Lower,upper→Upper), kind matching which trigger price field is set. - Include only the lines for values you are updating, each at most once, with at least one present; when both are present the Limit line comes first.
- Every decimal must be byte-identical to the request value — if the body says
"4000", the message must say4000, not4000.0. No normalization is applied.
updateMessage in the request body. The message is plaintext by design: a wallet’s message-signing prompt shows the user precisely which order is being repriced, and to what.
Signing the message
Sign with the funder wallet — the same wallet that signed the order. A signature from any other key is rejected.On EVM, the signature is verified onchain against the funder address using ERC-1271 with ERC-6492 support. EOAs, deployed smart accounts, and counterfactual (not-yet-deployed) smart accounts all work — sign with whatever
personal_sign flow the wallet provides.Examples
Move a stop-loss
The headline use case: raise a resting stop-loss’s trigger to $1,800 (notional basis) without touching anything else. Shown for EVM; on Solana only the signing primitive differs, exactly as in the limit examples below.take-profit update is identical with triggerType: "upper" and a Trigger Upper ... line. On a stop-limit or take-profit-limit you can move the limit in the same request: add the limit field to the body and its Limit ... Price: line to the message, above the trigger line.
Reprice a resting limit
Both examples move a resting limit order’s price to $4,000 (notional basis). To price in the pair rate instead, useLimit Cross Price: in the message and limitCrossPrice in the body.
EVM
EVM
SVM (Solana)
SVM (Solana)
What an update does
An accepted update is executed as a cancel-and-replace under the sameorderId: the remaining quantity is re-placed with the new price(s), and the order’s identity is stable everywhere — GET /orders/{orderId}, the Orders WebSocket, and any state you key by orderId.
Partial fills are kept. Fills that already settled onchain are final; only the unfilled remainder is re-placed.
The update is visible on the WebSocket. While the update is in flight, order frames carry pendingUpdate: true; once applied, the flag clears and the frames carry the new limitNotionalPrice / limitCrossPrice and trigger. If the flag clears and the prices are unchanged, the update was rejected downstream.
Which orders can be updated
An order is updatable while it is live and unfilled under itsorderId — status ORDER_STATUS_ACCEPTED or ORDER_STATUS_PARTIALLY_FILLED, whether it is resting at a limit or armed waiting on a trigger. See Order statuses.
For the trigger types, what is updatable depends on whether the trigger has fired:
- Before the trigger fires, the trigger price can move, and on
stop-limit/take-profit-limitthe post-trigger execution limit can move with it — either or both in one update. - After the trigger fires, a
stop-limit/take-profit-limitorder is an ordinary resting limit order; a limit update reprices it in flight — cancelled and re-placed at the new price under the sameorderId. A trigger update at that point is rejected: there is no trigger left to move. (stopandtake-profitexecute at market on firing, so there is nothing to update after the fire.)
- One update at a time. While an update is in flight, another
PATCHreturns422(order already has a pending update). Wait for the WebSocket frame with the new price, or re-read the order, before sending the next one. - Terminal orders can’t be updated. Orders in
ORDER_STATUS_FILLED,ORDER_STATUS_CANCELLED,ORDER_STATUS_REJECTED, orORDER_STATUS_TERMINATEDreturn422. - A trigger order that fires on entry has nothing to reprice. If the market already satisfies the trigger the instant the order is placed, it executes without ever resting; an update for it returns
404, the same as anorderIdthat never existed. - An update can race a fill. If the order fills before the update lands, the request returns
422— treat that as the order having executed at the old price, not as a failure to retry. 404covers both a missing order and a failed signature. If you get a404for an order you know exists, check the signature and the message bytes.