For the complete documentation index, see llms.txt. This page is also available as Markdown.

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

Endpoint
Returns

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.

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:

Rule
Detail

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
Effect

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.

Once a 2xx returns, no fill is decided on the old parameters — the executor re-reads the order after every claim. If a fill was already claimed when the PATCH arrived, the response is 409 EXECUTION_IN_FLIGHT; poll the detail endpoint.

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:

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.

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.

Last updated