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

OCO Brackets

One deposit, two triggers — a take-profit ceiling and a stop-loss floor where the first fill cancels the other.

An oco order brackets a position with one deposit: a take-profit above and a stop-loss below. Whichever leg fires first swaps the full amount and cancels the other. One-Cancels-Other — hence the name.

The alternative is two separate orders, which would lock the deposit twice. OCO reserves it once.

Leg
Fires when

Take-profit

price >= takeProfitPrice

Stop-loss

price <= stopLossPrice

Prices use the same fixed-point encoding and price basis as stop-loss and take-profit — a pair ratio by default, or USD per input token with priceBasis: "usd". Both legs share one priceDecimals and one priceBasis.

Config

POST /orders/intent
X-Titan-Key: <partner-api-key>
X-Titan-User: <your stable user id>
Content-Type: application/json

{
  "orderType": "oco",
  "userPubkey": "<user's external Solana wallet>",
  "config": {
    "inputMint":  "So11111111111111111111111111111111111111112",
    "outputMint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
    "amount": "1000000000",
    "takeProfitPrice": "200000000",
    "stopLossPrice": "50000000",
    "priceDecimals": 6,
    "expiresAt": 1767225600
  }
}
Field
Required
Notes

inputMint

✅

Must differ from outputMint.

outputMint

✅

amount

✅

String, > 0. One deposit, shared by both legs.

takeProfitPrice

✅

String, > 0. On the order's priceBasis, scaled by 10^priceDecimals.

stopLossPrice

✅

String, > 0, and strictly less than takeProfitPrice.

priceDecimals

✅

Integer 0–18, shared by both legs.

priceBasis

❌

"pair" (default) or "usd", shared by both legs. Same rules as stop-loss.

expiresAt

❌

Unix seconds, must be in the future. At expiry the deposit is auto-returned.

trailingStopBps

❌

Integer 1–9999. Makes the stop-loss leg trailing — see Trailing Stops.

Top-level fields (userPubkey, outputRecipientAddress, platformFee, onboardIfNeeded) and the confirm step are identical to every other order type — see Creating Orders. The minimum-notional floor applies to the full amount, as with any trigger order.

Read

GET /oco/{orderId} returns the base Order shape plus amount, takeProfitPrice, stopLossPrice, priceDecimals, priceBasis, expiresAt?, executedPrice?, executedPriceDecimals?, amountReceived?, pendingLeg?, parentOrderId?, and the stop-loss leg's trailing state (trailingStopBps?, currentTriggerPrice, highestObservedPrice?).

parentOrderId is set when the OCO was created automatically as the bracket of a conditional entry. Scale executedPrice by executedPriceDecimals — see executedPrice scale.

pendingLeg — values stop_loss or take_profit — labels which leg is mid-execution while the order is executing, and is absent otherwise. Use it to show the user which side is filling.

Returns 404 NOT_FOUND if the order doesn't exist, isn't this user's, or isn't an oco order.

Executions

An OCO fill is recorded under its leg's type — stop_loss or take_profit_full. There is no oco execution type. Read executionType on the single execution row to show which side fired.

Lifecycle

Identical to stop-loss and take-profit: active immediately after confirm, no retry, and auto-return on both failed and expired. Both legs' prices, expiry and trail can be changed in place with PATCH /oco/{orderId} — see Modify a trigger order. Cancelling before either leg fires leaves the deposit in the manager, so a cancelled OCO is the one case where order-level withdrawal matters.

Pausing stops both legs from being watched at once; resuming re-arms both.

Last updated