API
View as Markdown

Strategies

Manage your trading strategies and their setups. The PATCH endpoint upserts setups in one transaction so trades stay linked to the same setup row across renames.

GET /strategies

Scope: read:strategies

Your strategies with setup count. Optional filters: account_id, copy_group_id.

GET /strategies/{id}

Scope: read:strategies

Single strategy with full nested setups, plus risk_rules / exit_rules / optimal_conditions JSON.

GET /strategies/{id}/setups

Scope: read:strategies

Just the setups for one strategy.


POST /strategies

Scope: write:strategies

Create a strategy with optional embedded setups in one transaction. Subscription gate: bill_lim_canAddStrategy; over the per-plan max returns 429 limit_reached.

FieldTypeRequiredNotes
namestring (1–255)yesUnique per user.
descriptionstringno
color_taghexnoDefaults to #1d4ed8.
account_idintnoRestrict the strategy to one account. Mutually exclusive with copy_group_id.
copy_group_idintnoRestrict the strategy to one copy group.
risk_rulesobjectnoFree-form JSON; stored as-is.
exit_rulesobjectnoFree-form JSON.
optimal_conditionsobjectnoFree-form JSON.
setupsarraynoUp to 50. Each item: {name, description?, sort_order?, confirmations?} — the optional confirmations array on each setup defines the per-setup confirmation checklist (up to 100 entries, each {name, description?, sort_order?}).
curl -X POST https://app.tradavity.com/api/v1/strategies \
  -H "Authorization: Bearer tvty_YOUR_KEY_HERE" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Breakout Scalp",
    "description": "Bull / bear flag breaks on 5m.",
    "color_tag": "#ef4444",
    "setups": [
      {
        "name": "Bull Flag Break",
        "sort_order": 0,
        "confirmations": [
          {"name": "Pulled back to 9 EMA"},
          {"name": "Volume spike on break"}
        ]
      },
      {"name": "Bear Flag Break", "sort_order": 1},
      {"name": "Range Breakout",  "sort_order": 2}
    ]
  }'

PATCH /strategies/{id}

Scope: write:strategies

Update strategy fields and optionally replace the setups list. The setups array, if sent, becomes the canonical list:

  • Items with a setup_id matching an existing setup are updated in place — the row id is preserved so trades referencing it stay linked.
  • Items without setup_id are inserted fresh.
  • Existing setup_ids missing from the new list are hard-deleted; their confirmations cascade-delete via FK.
  • Foreign setup_ids (belonging to a different strategy) return 400 validation_error with error.details.unknown_setup_ids.
  • Nested confirmations on a setup: when present, the API diff-upserts against the setup’s existing confirmations (matches the strategy builder UI). Pass an existing confirmation_id to update in place — that preserves the id, so per-trade jrnl_trade_confirmations rows (the was_present / notes answers on every trade that ever used this confirmation) stay intact. Confirmations that exist in the DB but are absent from your payload are deleted; those rows DO cascade-delete the related per-trade answers, same as the website builder. When the key is absent, existing confirmations are left untouched; [] clears them all.
  • Foreign confirmation_ids (belonging to a different setup) return 400 validation_error with error.details.unknown_confirmation_ids.

GET /strategies/{id} and GET /strategies/{id}/setups include the full confirmations[] array inside each setup so you can read back what you wrote in one request. GET /strategies (the list endpoint) returns only setup_count, not the nested setups — call the single-strategy endpoint for the tree.

Pass account_id: null or copy_group_id: null to clear the corresponding scope. Setting one auto-clears the other.

DELETE /strategies/{id}

Scope: write:strategies

Hard delete. Trades that reference the strategy have their strategy_id and setup_id set to NULL first. Setups + confirmations cascade-delete via FK. The 204 response includes X-Trades-Unlinked with the count of trades that lost their strategy reference.