# Strategies

> Strategies and setups: list, read, create, update with embedded setups upsert, and delete.
> Source: https://help.tradavity.com/api-docs/strategies
> Category: Resources

---

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

| Field | Type | Required | Notes |
| --- | --- | --- | --- |
| `name` | string (1–255) | yes | Unique per user. |
| `description` | string | no |  |
| `color_tag` | hex | no | Defaults to `#1d4ed8`. |
| `account_id` | int | no | Restrict the strategy to one account. Mutually exclusive with `copy_group_id`. |
| `copy_group_id` | int | no | Restrict the strategy to one copy group. |
| `risk_rules` | object | no | Free-form JSON; stored as-is. |
| `exit_rules` | object | no | Free-form JSON. |
| `optimal_conditions` | object | no | Free-form JSON. |
| `setups` | array | no | Up 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?}`). |

```bash
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_id`s (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.
