# Goals

> Goals and period progress snapshots: list, read, create, update, delete.
> Source: https://help.tradavity.com/api-docs/goals
> Category: Resources

---

Quantitative trading goals with period-by-period progress snapshots.

## GET /goals

**Scope:** `read:goals`

| Param | Type | Description |
| --- | --- | --- |
| `status` | enum | `active` (default), `paused`, `archived`, `all`. |
| `account_id` | int | Filter to one account. |

## GET /goals/{id}

**Scope:** `read:goals`

Single goal definition.

## GET /goals/{id}/snapshots

**Scope:** `read:goals`

Period-by-period progress snapshots (target, actual, achieved, raw `snapshot_data`). Pagination via `limit` (max 365) and `offset`; date filter via `from` and `to`.

---

## POST /goals

**Scope:** `write:goals`

| Field | Type | Required | Notes |
| --- | --- | --- | --- |
| `goal_name` | string (1–100) | yes |  |
| `metric` | string | yes | Valid metric key. Common values: `net_pnl`, `gross_pnl`, `max_drawdown`, `balance_target`, `win_rate`, `profit_factor`, `expectancy`, `rr_realized_avg`, `a_plus_rate`, `max_trades_per_day`, `protocol_completion_rate`. |
| `target_value` | number | yes | Must be non-zero except for `max_drawdown` (where `0` means “no drawdown allowed”). Negative values are allowed where semantically meaningful (e.g. `net_pnl` as a loss floor). |
| `direction` | enum | no | `at_least` or `at_most`. Defaults to the metric’s natural direction (`at_most` for `max_drawdown` and `max_trades_per_day`; `at_least` otherwise). Unknown values return `400` with `details.allowed`. |
| `timeframe` | enum | no | `daily`, `weekly`, `monthly` (default), `quarterly`, `custom`. Unknown values return `400` with `details.allowed`. |
| `custom_start` / `custom_end` | `YYYY-MM-DD` | only when `timeframe=custom` | Both required when `timeframe=custom`; otherwise sending either field returns `400` (not silently ignored). Each must be a valid date between `2000-01-01` and `2100-12-31`. `custom_end` must be on or after `custom_start`. |
| `account_id` | int | no | Mutually exclusive with `copy_group_id`. |
| `copy_group_id` | int | no |  |

```bash
curl -X POST https://app.tradavity.com/api/v1/goals \
  -H "Authorization: Bearer tvty_YOUR_KEY_HERE" \
  -H "Content-Type: application/json" \
  -d '{
    "goal_name": "Monthly profit target",
    "metric": "net_pnl",
    "target_value": 5000,
    "timeframe": "monthly"
  }'
```

## PATCH /goals/{id}

**Scope:** `write:goals`

Update `goal_name`, `metric`, `target_value`, `direction`, `timeframe` (with `custom_start`/`custom_end`), `status` (`active` / `paused` / `archived`), or `scope`. Validation rules (non-zero target, enum allow-lists, date format / range / ordering) are identical to POST — see the POST table above. To change the date window on an existing custom goal, send `timeframe: "custom"` together with the new `custom_start` and `custom_end` in the same PATCH (the helper only writes the dates when `timeframe` is in the body too).

The `scope` field is a structured string:

- `"account_42"` — bind to account 42.
- `"group_7"` — bind to copy group 7.
- `"all"` — global across all accounts.
- `""` (empty) — follow the user’s active selection in the UI.

## DELETE /goals/{id}

**Scope:** `write:goals`

Hard delete. Period snapshots cascade-delete via FK.
