# Goal compliance

> Create and manage creator goals, and read per-creator compliance results with data advisories.

## Managing goals (write endpoints)

### POST /api/v2/creators/{id}/goals

Create a goal for a creator. Requires the `write` scope.

```bash
curl -X POST \
  -H "Authorization: Bearer tga_<key>" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"metric": "views", "period": "weekly", "target_value": 500000}' \
  https://www.trackagoat.com/api/v2/creators/<creatorId>/goals
```

| Field | Type | Description |
|-------|------|-------------|
| `metric` | `posts` \| `views` \| `engagement` \| `followers` | What to measure. |
| `period` | `daily` \| `weekly` \| `monthly` | Evaluation window. |
| `target_value` | integer > 0 | Target number per period. |
| `start_date` | YYYY-MM-DD | Optional. The goal is first judged in the first period that starts on or after this date (org time zone). |
| `end_date` | YYYY-MM-DD | Optional. The goal is last judged in the last period that ends on or before this date. |
| `platform_scope` | `all` \| `platform` \| `account` | Optional, default `all`. Scopes the goal across the creator's platform accounts: `all` = the whole creator (every account), `platform` = one platform, `account` = a single account. |
| `platform` | `tiktok` \| `instagram` \| `youtube` \| null | Required when `platform_scope` is `platform`; must be omitted/null otherwise. |
| `account_id` | uuid \| null | Required when `platform_scope` is `account` (must belong to this creator); must be omitted/null otherwise. |

> **Note: Multi-platform scope**
>
> Trackagoat 2.0 creators own one or more platform accounts (TikTok, Instagram). `platform_scope` controls which of a creator's accounts a goal is measured against. The scope combination is validated: `all` → no `platform`/`account_id`; `platform` → `platform` only; `account` → `account_id` only. A mismatch returns **400**.

```bash
# A weekly TikTok-only posting goal
curl -X POST \
  -H "Authorization: Bearer tga_<key>" \
  -H "Content-Type: application/json" \
  -d '{"metric": "posts", "period": "weekly", "target_value": 5, "platform_scope": "platform", "platform": "tiktok"}' \
  https://www.trackagoat.com/api/v2/creators/<creatorId>/goals
```

### PATCH /api/v2/creators/{id}/goals/{goalId}

Update a goal. At least one field required. Requires the `write` scope. Accepts `metric`, `period`, `target_value`, `is_active`, `start_date`, and `end_date`. The platform scope (`platform_scope`, `platform`, `account_id`) is fixed at creation and cannot be changed; delete and recreate the goal to re-scope it.

### DELETE /api/v2/creators/{id}/goals/{goalId}

Permanently delete a goal. Requires the `write` scope.

---

## Compliance overview (read endpoint)

The goal compliance endpoint returns per-creator, per-goal progress results for a project. Each result includes:

- The goal's current **actual** value and **target**
- A **status** (`on_track`, `behind_pace`, `at_risk`, `missed`, `completed`)
- An **advisory** block explaining why the displayed progress may not be final
- The goal's **platform scope** (`platform_scope`, `platform`, `account_id`): `actual` is measured only against the accounts in scope

For a project-wide roll-up (counts only), use [`/aggregate/goal-compliance`](https://www.trackagoat.com/docs/api-reference/aggregate.md#get-aggregategoal-compliance) instead.

---

## GET `/api/v2/projects/:projectId/goal-compliance`

Returns compliance results for all active creators in a project, grouped by creator.

### Request

```bash
curl -H "Authorization: Bearer tga_<key>" \
  "https://www.trackagoat.com/api/v2/projects/<projectId>/goal-compliance"
```

### Query parameters

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `creator_id` | UUID | None | Restrict results to a single creator |
| `period` | `daily` \| `weekly` \| `monthly` | all | Filter to goals of this period type |
| `reference_date` | YYYY-MM-DD | today (org tz) | Evaluate goals as of this date |
| `platform` | `tiktok` \| `instagram` \| `youtube` | all | Restrict results to creators that have an account on this platform |

### Response

```json
{
  "data": [
    {
      "creator": {
        "id": "uuid",
        "handle": "sarah.b8520",
        "display_name": "SarahBD",
        "avatar_url": "https://..."
      },
      "compliance": [
        {
          "goal": {
            "id": "uuid",
            "creator_id": "uuid",
            "project_id": "uuid",
            "metric": "posts",
            "period": "weekly",
            "target_value": 15,
            "start_date": null,
            "end_date": null,
            "is_active": true,
            "platform_scope": "all",
            "platform": null,
            "account_id": null
          },
          "target": 15,
          "actual": 11,
          "percentage": 73,
          "status": "behind_pace",
          "advisory": {
            "period_in_progress": true,
            "period_recently_ended": false,
            "scrape_stale": false,
            "not_yet_started": false,
            "has_advisory": true,
            "period_start": "2026-05-18T05:00:00.000Z",
            "period_end": "2026-05-25T04:59:59.999Z",
            "hours_until_period_end": 89.4,
            "hours_since_period_end": null,
            "scrape_freshness": null,
            "goal_start_date": null,
            "messages": [
              "Period in progress. It closes in 3 days, so the final actual may be higher."
            ]
          }
        }
      ]
    }
  ],
  "error": null,
  "meta": {
    "org_tz": "America/Chicago",
    "reference_date": "2026-05-20"
  }
}
```

### Status values

| Status | Meaning |
|--------|---------|
| `on_track` | Projected to meet or exceed target by period end |
| `behind_pace` | Below projected pace but above the 70% at-risk threshold |
| `at_risk` | Significantly behind pace (below 70% of projected) |
| `completed` | Period has ended and target was met |
| `missed` | Period has ended and target was not met |

During the first 15% of the period an unmet goal is `on_track`. Posts goals compare whole posts, so a goal is behind only once a whole post is due. Followers goals add up the growth of each account in scope, and each account is measured from its own starting count.

---

## The `advisory` object

Every compliance result includes an `advisory` block. When `has_advisory` is `false`, the displayed progress is likely final and the object can be ignored. When `true`, the `messages` array contains one human-readable explanation per active flag.

### Advisory flags

| Field | Type | Condition |
|-------|------|-----------|
| `period_in_progress` | boolean | Current wall-clock time is before the period end. Actual counts will grow until period close. |
| `period_recently_ended` | boolean | Period ended within the last 48 hours. Late-period posts may still be processing through scrape. |
| `scrape_stale` | boolean | Creator's stats scrape is turning stale or overdue. Views, engagement, or follower counts may undercount until the next scrape runs. |
| `not_yet_started` | boolean | The goal has a `start_date` set in the future. No data has accrued yet. |
| `has_advisory` | boolean | `true` when `period_recently_ended` is true. Drives the UI caution icon. The other flags are available for programmatic use but do not set `has_advisory`. |

### Advisory context fields

| Field | Type | Description |
|-------|------|-------------|
| `period_start` | ISO timestamp | UTC start of the current period |
| `period_end` | ISO timestamp | UTC end of the current period |
| `hours_until_period_end` | number \| null | Hours remaining until period closes; `null` if period already ended |
| `hours_since_period_end` | number \| null | Hours elapsed since period closed; `null` if period is still open |
| `scrape_freshness` | object \| null | Full freshness summary (bucket, age, tooltip) when `scrape_stale` is true; `null` otherwise |
| `goal_start_date` | YYYY-MM-DD \| null | The goal's `start_date`, when `not_yet_started` is true |
| `messages` | string[] | One pre-formatted explanation string per active flag, safe to display directly |

---

## Relationship to aggregate endpoint

| Use case | Endpoint |
|----------|----------|
| Dashboard summary (counts only) | `GET /api/v2/analytics/aggregate/goal-compliance` |
| Per-creator, per-goal detail with advisories | `GET /api/v2/projects/:id/goal-compliance` |
| Single creator's goals | `GET /api/v2/projects/:id/goal-compliance?creator_id=<uuid>` |

---
Source: https://www.trackagoat.com/docs/api-reference/goals
