Data model
Entity reference for AI agents: fields, relationships, and the readme documents agents read and write.
Hierarchy#
Trackagoat is multi-platform. A creator is a person or brand; each creator owns one or more accounts, where an account is a single presence on a platform (TikTok or Instagram; youtube is reserved for YouTube tracking, which isn't available yet). Videos hang off accounts. Tracking configuration (mode, start/end dates, follower stats, last_scraped_at) lives on the account, not the creator. A creator can have several accounts, even more than one on the same platform.
Organization : readme (the organization's document)
├── Member(s) : each with a personalization document (readme)
└── Project(s)
├── Creator(s) : a person/brand (1..n accounts)
│ └── Account(s) : one platform presence, tiktok | instagram | youtube
│ └── Video(s) : videos/posts from that account
├── Video(s) : standalone videos added by URL (carry platform + account_id)
├── Content Group(s) : link the same content across platforms
└── Campaign(s) : named groupings (can nest)
├── → Creator(s)
├── → Video(s)
└── → Campaign(s) (recursive)Data is scoped to the organization of the API key. A single API call fetches data across all projects unless you filter by project_id. Most list endpoints (/api/v2/creators, /api/v2/accounts, /api/v2/videos, the analytics aggregates) accept a platform filter.
The current API is /api/v2; the previous v1 API has been retired.
Entity reference#
Project#
| Field | Type | Notes |
|---|---|---|
id | uuid | |
name | string | |
readme | string | null | Agent context: the project's document. Read it before working in the project |
org_id | uuid | |
created_at | ISO 8601 | |
updated_at | ISO 8601 |
Creator#
A creator embeds its accounts[]. Creator-level counts are the aggregate across all its accounts; the top-level handle is the primary account's handle (the TikTok account if present, otherwise the earliest-added).
| Field | Type | Notes |
|---|---|---|
id | uuid | |
project_id | uuid | |
org_id | uuid | |
handle | string | null | Primary account's handle (without @) |
display_name | string | null | |
avatar_url | string | null | |
readme | string | null | Agent context: read before analyzing (the README on the Info tab; agents append with POST /api/v2/creators/{id}/notes) |
follower_count | number | null | Sum across the creator's accounts |
following_count | number | null | Sum across accounts |
total_likes_count | number | null | Sum across accounts |
video_count | number | null | Sum across accounts |
accounts | Account[] | Embedded platform accounts (see below) |
is_active | boolean | |
created_at | ISO 8601 | |
updated_at | ISO 8601 |
Creator-level writes (PATCH /api/v2/creators/{id}) accept only display_name, readme, is_active and metadata. The handle and tracking configuration live on the account: change them via PATCH /api/v2/accounts/{id}.
Account#
One platform presence owned by a creator. Tracking config and the raw follower/engagement snapshot live here.
| Field | Type | Notes |
|---|---|---|
id | uuid | |
creator_id | uuid | Owning creator |
project_id | uuid | |
org_id | uuid | |
platform | tiktok | instagram | youtube | |
handle | string | The account's handle (without @) |
platform_user_id | string | null | Stable platform-side ID |
display_name | string | null | |
avatar_url | string | null | |
bio_link | string | null | Link in the account's bio |
follower_count | number | Current snapshot (followers / subscribers) |
following_count | number | |
total_likes_count | number | |
video_count | number | |
tracking_mode | auto | selective | hashtag | Controls which discovered videos enter the system |
tracking_hashtags | string[] | Hashtag-mode only: tags matched against the video caption. Stored normalized (NFC, lowercase, no #, invalid characters stripped, deduped); max 50 |
hashtag_inbox_non_matching | boolean | Hashtag-mode only: inbox (true) vs exclude (false) for non-matching videos |
tracking_start_date | ISO date | null | Lower bound for this account's stats history |
tracking_end_date | ISO date | null | Last tracked day, inclusive. The window spans each date in both UTC and the org's analytics timezone (the wider of the two) |
is_active | boolean | false when auto-disabled |
last_scraped_at | ISO 8601 | null | When this account was last refreshed |
created_at | ISO 8601 | |
updated_at | ISO 8601 |
Fetch accounts via GET /api/v2/accounts (filter by creator_id, project_id, or platform), GET /api/v2/creators/{id}/accounts, or embedded in a creator. Per-account follower/stat history: GET /api/v2/accounts/{id}/stats.
Video#
| Field | Type | Notes |
|---|---|---|
id | uuid | |
creator_id | uuid | null | Null for direct-add videos with no matched creator |
account_id | uuid | null | The account this video belongs to |
platform | tiktok | instagram | youtube | |
platform_video_id | string | Platform-side video/post ID |
url | string | Full URL on the platform |
media_type | video | photo | photo = a TikTok photo carousel or Instagram image post/carousel; otherwise video |
title | string | null | Short title. TikTok: the caption's first line (up to 100 characters). Instagram: null |
caption | string | null | The post's text as posted on the platform (YouTube: the video description). Filled by scraping, read-only |
description | string | null | Deprecated. An old free-text field that nothing fills and that can't be written any more. Any text it had was copied into readme. Ignore it; it will be removed |
readme | string | null | Agent context / notes (agents append with POST /api/v2/videos/{id}/notes) |
thumbnail_url | string | null | |
view_count | number | null | Current snapshot (plays on Reels/Shorts) |
like_count | number | null | |
comment_count | number | null | |
share_count | number | null | |
tracking_status | string | auto_tracked, pending_review, included, excluded, direct_add |
posted_at | ISO 8601 | null | Original post date on the platform |
last_scraped_at | ISO 8601 | null |
Content Group#
Links the same logical content across platforms (e.g. the same clip posted as a TikTok, a Reel, and a Short) so its combined stats can be viewed together. A video belongs to at most one content group.
| Field | Type | Notes |
|---|---|---|
id | uuid | |
project_id | uuid | |
org_id | uuid | |
title | string | |
notes | string | null | Free-form notes |
created_by | uuid | null | |
video_ids | uuid[] | Member videos (across platforms) |
created_at | ISO 8601 | |
updated_at | ISO 8601 |
Manage via /api/v2/content-groups (list/create) and /api/v2/content-groups/{id} (get/patch/delete; add or remove members with add_video_ids / remove_video_ids). Combined stats: GET /api/v2/content-groups/{id}/stats returns summed totals plus a by_platform breakdown.
Campaign#
Campaigns are mixed-platform: the creators and videos they contain can be on any platform, and stats roll up across all of them with a per-platform breakdown.
| Field | Type | Notes |
|---|---|---|
id | uuid | |
project_id | uuid | |
name | string | |
readme | string | null | Agent context: strategy, benchmarks, instructions (campaigns use readme, not description) |
target_views | number | null | Optional total-view goal for the campaign |
created_at | ISO 8601 | |
updated_at | ISO 8601 |
Goal#
A per-creator performance target. Goals carry a platform scope so a target can apply to all of a creator's accounts, one platform, or one account.
| Field | Type | Notes |
|---|---|---|
id | uuid | |
metric | posts | views | engagement | followers | |
period | daily | weekly | monthly | |
target_value | number | |
platform_scope | all | platform | account | all = whole creator (default) |
platform | tiktok | instagram | youtube | null | Required when platform_scope is platform |
account_id | uuid | null | Required when platform_scope is account |
start_date | ISO date | null | |
end_date | ISO date | null | |
is_active | boolean |
Compliance is measured only over the accounts the scope includes. Create via POST /api/v2/creators/{id}/goals.
Context field conventions#
Humans write free-text context for agents to read. The context field is readme, a Markdown document on the organization, every project, campaign, creator, video, payout method, payout structure and payout payment, and every member (their personalization document). It is the README or Notes in the app. Find them with GET /api/v2/notes (MCP list_notes), read one with GET /api/v2/notes/{entity_type}/{id} (get_notes), and add to one with POST /api/v2/notes/{entity_type}/{id} (update_notes), which appends by default and never overwrites what people wrote. Everyone in the organization, and their agents, can read every document. See Notes and documents. On a video, caption holds the post's text from the platform (read-only, not a notes field); the old description field is deprecated. Common patterns:
# Campaign readme
"Q1 creator push for Product X. Target: 1M views by March 31.
Top performers from last quarter: @creator1, @creator2.
Exclude any videos not directly about Product X."
# Creator readme
"Fitness creator, 3x/week posting cadence. Best content: workout tutorials.
Posts on TikTok and Instagram; YouTube is dormant.
Known issue: also posts food content unrelated to program: use selective mode.
Last contract renewal: Jan 2026."
# Video readme
"Strong outlier: 10x normal views. Trending audio #fitnesscheck helped.
Not representative of creator's normal performance."When a context field contains explicit analysis instructions, follow them over your general analysis approach.
Conversion entities#
Conversion Event#
A project-scoped definition of an outcome worth tracking. Conversions reference it.
| Field | Type | Meaning |
|---|---|---|
key | string | Stable identifier, unique per project. Matches ^[a-z0-9][a-z0-9_.-]{0,62}$. Immutable after creation |
name | string | Human label |
default_value_cents | integer | Used when a conversion omits value_cents |
currency | string(3) | ISO code. Lives on the EVENT, not the conversion, so totals are always well defined. Immutable |
is_active | boolean | Inactive events reject new conversions but keep existing ones in all totals |
Plan limit max_conversion_events_per_project caps active event types (free 3, starter 25, ultra unlimited). Conversion volume is never capped.
Conversion#
| Field | Type | Meaning |
|---|---|---|
conversion_event_id | uuid | The event this records |
target_type | creator | account | video | What it was attributed to |
creator_id / account_id / video_id | uuid | null | Rollup. A video-target conversion also populates account and creator |
value_cents | integer | Falls back to the event's default_value_cents |
quantity | integer | Default 1 |
total_value_cents | integer | Generated: value_cents * quantity |
external_id | string | null | Your id. Permanently unique per project: a repeat returns the ORIGINAL with deduped: true |
status | recorded | voided | Voided conversions are excluded from totals but retained |
occurred_at | timestamp | ISO 8601 with offset required on write |
Attribution is frozen at receipt. Moving a video to another account later does not rewrite its past conversions. An org admin can explicitly override this per video.
Reading totals: filtering by creator_id returns conversions recorded against that creator's accounts and videos too. Do not sum across levels or you will double count.
Payout entities#
Payout Method#
| Field | Type | Notes |
|---|---|---|
id | uuid | |
org_id | uuid | |
name | string | e.g. "Venmo", "Cash App" |
icon_url | string | null | Public icon URL |
is_default | boolean | Auto-seeded defaults cannot be deleted |
is_active | boolean | Disabled methods won't appear in payment dialogs |
metadata | object | Agent-writable |
readme | string | null | Agent-writable notes |
Payout Structure#
| Field | Type | Notes |
|---|---|---|
id | uuid | |
project_id | uuid | |
name | string | |
is_active | boolean | Archived structures stop generating accruals |
current_version | object | Active rule snapshot: period, amount_cents, currency, criteria_type, criteria_params, proration_mode, platform_scope, platform, account_id |
versions | array | Full version history (GET by ID only) |
assignment_count | number | Currently assigned creators |
metadata | object | Agent-writable |
readme | string | null | Agent-writable notes |
criteria_type values: recurring (flat-rate every period), goals (pays when creator meets their period goals), cpm (pays per 1,000 views; each period pays for the views each video gained since it was last paid, for view_lifetime_days after posting or forever), view_threshold (one-time bonus when an individual video crosses a view-count milestone, period and top-level amount_cents are null; each threshold defines its own amount).
Platform scope: a version's platform_scope (all | platform | account, default all) limits which of an assigned creator's accounts contribute, CPM impressions, goal compliance, and view-threshold crossings are all measured only from accounts in scope. When scoped, platform or account_id is set accordingly.
Payout Accrual#
Computed by an hourly background job after relevant scrapers complete. Cannot be created via the API.
| Field | Type | Notes |
|---|---|---|
id | uuid | |
creator_id | uuid | |
structure_id | uuid | |
structure_version_id | uuid | The rule version active at period end (pinned) |
period_start_at | ISO 8601 | null | Inclusive, UTC. null for view_threshold accruals (no period) |
period_end_at | ISO 8601 | null | Exclusive, UTC. null for view_threshold accruals |
video_id | uuid | null | Set only for view_threshold accruals: the video that crossed the milestone |
threshold_views | number | null | Set only for view_threshold accruals: the milestone view count that fired |
amount_cents | number | Post-proration, in cents |
currency | string | Currently always USD |
status | string | earned → paid (via payment) or rejected/voided (manual) |
inputs_snapshot | object | null | Data used to compute (goals_met, impressions, etc.) |
Payout Payment#
| Field | Type | Notes |
|---|---|---|
id | uuid | |
project_id | uuid | |
creator_id | uuid | null | Null for ad-hoc payments |
method_id | uuid | null | |
method_name_snapshot | string | null | Captured at write time |
total_amount_cents | number | |
status | string | paid or voided |
paid_at | ISO 8601 | |
payout_payment_lines | array | M2M to accruals with applied_amount_cents |
payout_adjustments | array | Over/underpayment lines (positive = overpayment, negative = underpayment) |
metadata | object | Agent-writable |
readme | string | null | Agent-writable notes |