> For the complete documentation index, see [llms.txt](https://titan-exchange.gitbook.io/titan/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://titan-exchange.gitbook.io/titan/developer-doc/special-order-types/guides/managing-orders.md).

# 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`                      |
| ---------------------- | ---------------------------------------------------------------------------------------------- | --------------------------------------------------- | ---------------------------- |
| Modify                 | ✅ [`PATCH /dca/{orderId}`](/titan/developer-doc/special-order-types/order-types/dca.md#modify) | ✅ [Parameter-only `PATCH`](#modify-a-trigger-order) | ❌                            |
| 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](/titan/developer-doc/special-order-types/order-types/slice.md#lifecycle).

## 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.

{% hint style="warning" %}
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.
{% endhint %}

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](/titan/developer-doc/special-order-types/reference/schema.md).

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

```
PATCH /stop-loss/{orderId}     PATCH /take-profit/{orderId}     PATCH /oco/{orderId}
```

```json
{ "config": { "triggerPrice": "48000000" } }
```

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`](/titan/developer-doc/special-order-types/order-types/stop-loss-take-profit.md#unfillable-configurations) 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

```json
{ "success": true, "data": { "order": { "…": "…" } } }
```

The order is nested under `data.order`. The per-type `GET` returns it as `data` directly; the object itself has the same shape.

{% hint style="info" %}
**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.
{% endhint %}

| 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:

```typescript
// Cancel only — no transaction built.
await callTitanDca(`/orders/${orderId}/cancel`, {
  method: 'POST', sub,
  body: { withdraw: false },
});

// Cancel and get an unsigned multi-token withdrawal tx back.
await callTitanDca(`/orders/${orderId}/cancel`, {
  method: 'POST', sub,
  body: { withdraw: true, userPubkey },
});
```

{% hint style="warning" %}
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.
{% endhint %}

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](#modify-a-trigger-order). 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.

{% hint style="danger" %}
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.
{% endhint %}

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](/titan/developer-doc/special-order-types/guides/creating-orders.md) — the two-step flow that got you here
* [DCA](/titan/developer-doc/special-order-types/order-types/dca.md#modify) — the DCA modify flow, which can require a transaction
* [Lifecycle & Polling](/titan/developer-doc/special-order-types/guides/lifecycle.md) — every status and how to keep your UI in sync
