Managing Orders
Read order state, then modify, pause, resume, cancel, or retry — and what each order type supports.
Once an order is active, five operations are available: modify, pause, resume, cancel and retry. Support varies by order type.
Operation
dca
Trigger orders
slice
Pause / resume
✅
✅
❌ 400 PAUSE_NOT_SUPPORTED
Cancel
✅
✅
❌ 400 CANCEL_NOT_SUPPORTED
Retry a failed order
✅ (brief window)
❌ 400 RETRY_NOT_SUPPORTED
❌ 400 RETRY_NOT_SUPPORTED
Slice Orders are fire-and-forget once confirmed; a failed one auto-returns its unspent input. See Slice Orders.
Read order state
GET /me/orders?status=&type=
All of the user's orders, optionally filtered.
GET /me/orders/active
Currently running orders.
GET /me/orders/history
Terminal orders (completed / cancelled / failed / expired).
GET /dca/{orderId}
One DCA order with full cycle progress.
GET /stop-loss/{orderId} · /take-profit/{orderId} · /oco/{orderId}
One trigger order with its type-specific fields.
GET /slice/{orderId}
One Slice Order with its confirmed slices.
GET /orders/{orderId}/executions
Execution history, most recent first. Capped at 500 rows.
type accepts dca, stop_loss, take_profit, oco or slice; status accepts any value from the status enum.
Both filters are exact-match and unvalidated. A typo or an unknown value returns { "success": true, "data": [] } — a success with an empty list, not an error. Don't read an empty response as "this user has no orders" without checking your filter string first.
The per-type detail endpoints return 404 NOT_FOUND when the id exists but belongs to a different orderType, so route off the orderType field in the list response rather than probing each endpoint in turn. Every field is documented in Order & Execution Schema.
Three more pending-order views exist for the window between intent and confirm: GET /orders/pending (awaiting confirmation), GET /orders/pending/failed (timed out or failed before activating), and GET /orders/pending/history (every pending row, any status, capped at 50 rather than 500).
Modify a trigger order
Edits an active or paused trigger order in place. There is no transaction, no signing step and no lock: amount, mints, priceDecimals, priceBasis, outputRecipientAddress and onFillOco are immutable, so no funds move and the change applies atomically. A patch carrying any immutable field returns 400 VALIDATION_ERROR.
Editable fields
Field
stop_loss
take_profit
oco
null clears
triggerPrice
✅
✅
—
No
takeProfitPrice / stopLossPrice
—
—
✅
No
minOutputAmount
✅
✅
—
Yes
expiresAt
✅
✅
✅
Yes
trailingStopBps
✅
✅
✅
Yes
trailingMode
✅
—
—
Yes
Omitted fields are unchanged. At least one field is required.
Validation
Validation runs on the merged result — the stored order plus the patch — with the same rules as create:
OCO ordering
stopLossPrice < takeProfitPrice. With a trailing stop leg, takeProfitPrice must also stay above the leg's live ratcheted trigger (currentTriggerPrice). Lowering the target below a ratcheted stop is rejected unless the trail is widened in the same patch.
Trailing mode
trailingMode requires a trail. Clearing trailingStopBps also clears trailingMode.
Limit take-profit
A take-profit created with createdAs: "limit" cannot be given a trail.
OTOCO entry expiry
An entry's expiresAt, when set, must stay before its onFillOco.expiresAt. Clearing it is allowed, as at create.
Expiry
expiresAt must be in the future.
Unfillable configurations
Both MIN_OUTPUT_UNSATISFIABLE checks, with the same details as create. The instant-fire check uses the current ratcheted trigger, not the base. Run only when the patch touches triggerPrice, minOutputAmount or trailingStopBps.
Moving a trigger past the current market is allowed and fires on the next evaluation, as at create.
Trailing state
Trailing state is recomputed, not reset.
Change trailingStopBps on a trailing stop
The observed peak is kept and the live trigger is re-derived as max(newStop, peak × (1 − newBps/10000)). Widening the trail moves the live trigger down; narrowing it moves it up.
Lower triggerPrice on a trailing stop
Does not loosen a stop the trail has already ratcheted above it. Widen trailingStopBps instead.
Raise the stop above the observed peak
Clears the peak. If the market is already below the new stop, the order fires rather than ratchets.
Remove the trail
Resets the live trigger to the stop price.
Raise a trailing take-profit's triggerPrice above the observed peak
Disarms the trail. Otherwise it would floor-fire below the new target on the next tick. A trailing take-profit stays armed only if the observed peak still reaches the new triggerPrice.
Response
The order is nested under data.order. The per-type GET returns it as data directly; the object itself has the same shape.
HTTP
error.code
When
400
VALIDATION_ERROR
Invalid or immutable field, no fields, merged-invariant violation, or a retired take-profit shape (entryPrice, minProfitBps, scaleSteps).
400
MIN_OUTPUT_UNSATISFIABLE
The same two cases and details as create.
400
INVALID_STATE
The order is in any status other than active or paused — terminal, or a transient lock state.
404
NOT_FOUND
Missing, not yours, or a different order type from the path.
409
EXECUTION_IN_FLIGHT
A fill is executing, or the order changed during the request — a claim that was then released, or a ratchet on an OCO. Retry in a few seconds.
Pause and resume
POST /orders/{orderId}/pause stops an active order; POST /orders/{orderId}/resume restarts a paused one. Each returns the updated order, or 400 INVALID_STATE if the order isn't in the right state or a withdrawal is in flight. 404 NOT_FOUND if it isn't the user's.
What pausing means depends on the type. A paused DCA order stops running cycles. A paused trigger order stops being price-watched entirely — it can't fire, and a trailing trigger can't ratchet. On resume it re-arms immediately, keeping whatever trailing state it had: a trailing stop keeps its ratcheted trigger, a trailing take-profit keeps its armed state and peak.
Cancel
POST /orders/{orderId}/cancel takes a discriminated body on the withdraw flag:
If you omit the body entirely, withdraw defaults to true — which still requires userPubkey. An empty body therefore fails with 400 VALIDATION_ERROR. Always send one of the two shapes above explicitly.
With withdraw: true, the response includes a transaction and a withdrawalAmounts array — the per-mint amounts the transaction will move, which is what you show the user before they sign. Submit the signed transaction to POST /orders/{orderId}/withdraw/confirm. If there's nothing to withdraw, the response omits transaction and sets a message instead.
To change a trigger order's price, use modify. To change its size, cancel and create a new order.
HTTP
error.code
When
400
VALIDATION_ERROR
Invalid body — including withdraw: true without userPubkey, or an empty body.
400
NOT_CANCELLABLE
The order can't be cancelled in its current state (already terminal, or a lost race).
400
CANCEL_NOT_SUPPORTED
The order is a Slice Order.
404
NOT_FOUND
Order missing or not yours.
409
EXECUTION_IN_FLIGHT
A swap attempt is still being reconciled. Self-resolving — retry shortly.
500
WITHDRAWAL_BUILD_FAILED
The cancel succeeded but the withdrawal tx failed to build. The order is cancelled; call POST /orders/{orderId}/withdraw to retry just the withdrawal leg.
Retry a failed order
POST /orders/{orderId}/retry flips a failed DCA order back to active so Titan keeps trying. Use it when execution exhausted its in-cycle retries but the user still wants the schedule to continue.
A failed order's unspent input is auto-returned to the user's external wallet shortly after it fails. Retry only succeeds in the brief window before that return runs — once it's in progress or done you get 409 WITHDRAWAL_IN_PROGRESS or 400 ALREADY_WITHDRAWN, and the user has to create a new order.
Trigger orders and Slice Orders can't be retried. POST /orders/{orderId}/retry on one returns 400 RETRY_NOT_SUPPORTED — though in practice you'll see 400 ALREADY_WITHDRAWN first, because that check runs earlier and auto-return typically completes within a minute. Hide the retry button for both: the supported path is fail → auto-return → create a new order.
HTTP
error.code
When
400
ALREADY_WITHDRAWN
withdrawalStatus = completed — funds already returned. Checked before RETRY_NOT_SUPPORTED.
400
RETRY_NOT_SUPPORTED
The order is a trigger order or a Slice Order.
400
ORDER_NOT_FAILED
The order isn't failed. details.status echoes the current status.
400
INSUFFICIENT_FUNDS
The manager no longer holds enough input mint. details: mint, required, currentBalance, gap.
400
INVALID_STATE
The atomic transition lost a race. Refetch and decide.
409
WITHDRAWAL_IN_PROGRESS
withdrawalStatus = pending — finish or abandon it before retrying.
Related pages
Creating Orders — the two-step flow that got you here
DCA — the DCA modify flow, which can require a transaction
Lifecycle & Polling — every status and how to keep your UI in sync
Last updated

