Skip to content

Attach a take-profit and stop-loss

A take-profit and a stop-loss have to behave as one unit — if the survivor outlives the leg that fired, it re-opens the exposure it was supposed to close. This attaches both to an already-open position as reduce-only legs sharing a single OCO group.

  1. The server resolves the position from your account plus the symbol you send, so that is the only thing you need off this read. No open position on that symbol gives 404 no_position_for_symbol.

    Terminal window
    curl -s https://api.troncharts.xyz/api/v1/accounts/$ACCOUNT_ID/positions \
    -H "authorization: Bearer $TOKEN" \
    -H "x-tenant-slug: $TC_TENANT_SLUG"
    # → { accountId, accountNumber, positions: [ { symbol, venue, side, qty, entryPrice, … } ] }
  2. At least one of tpPrice / slPrice must be present, or you get 400 no_legs_requested. Send them as JSON numbers — unlike the compose schema, this one does not coerce decimal strings.

    Terminal window
    curl -s https://api.troncharts.xyz/api/v1/oms/brackets/attach-to-position \
    -H "authorization: Bearer $TOKEN" \
    -H "x-tenant-slug: $TC_TENANT_SLUG" \
    -H 'content-type: application/json' \
    -H "idempotency-key: $(uuidgen)" \
    -d '{"symbol":"BTC.HL","tpPrice":72000,"slPrice":58500}'
  3. Both legs carry ocoGroupId as their parentIntentId; that linkage is what makes them one unit. side is the closing side (a long position gives sell), and qty is the full position size — each leg covers all of it.

    { "ok": true, "ocoGroupId": "9c41…", "tpIntentId": "1a2b…",
    "tpIntentIds": ["1a2b…"], "slIntentId": "7d8e…",
    "side": "sell", "qty": "0.01" }

    The legs dispatch immediately — a position already exists to reduce, so there is nothing to wait for. From here the server owns the lifecycle: when one leg fills it cancels the survivor, and when the position closes by any route it cancels both.

Next: Split a take-profit across several targets · Cancel an order or close a position · Order lifecycle & signing