MCP server
Connect Claude, Cursor and other MCP clients to trackagoat with the hosted MCP server.
Overview#
trackagoat runs a hosted Model Context Protocol server. Connect Claude.ai or Claude Desktop by signing in with your trackagoat account, or point any MCP client at it with an API key. Your agent can then check a program's health, browse projects, creators, videos, campaigns, goals, conversions and payouts, pull analytics, and (with write access) do what the REST API does: add, change and remove creators, accounts, videos, campaigns, goals and content groups, record conversions, set up payout structures, assign creators to them, and record or void payments. It can also read and write the Markdown documents on every record and export any CSV the app exports.
| URL | https://www.trackagoat.com/api/mcp |
| Transport | Streamable HTTP (stateless). The legacy HTTP+SSE transport is not supported; use mcp-remote for clients that only speak stdio. |
| Auth | Either sign in with trackagoat (OAuth 2.1, for Claude.ai and Claude Desktop and other OAuth-capable clients), or Authorization: Bearer tga_<key> with the same org API keys as the REST API |
| Data scope | The organization you pick when you sign in, or the one that owns the API key. Other organizations' data is never visible. |
Every tool is a thin adapter over one /api/v2 endpoint, so MCP and REST return the same data and enforce the same permissions and limits.
A connection always acts as one member of the organization: the person who signed in, or the member an API key acts as. Everything the agent does is attributed to them, and it can never do more than they can do in the app. When the agent connects, the server sends that person's personalization document along with its instructions, so the agent starts out knowing who it is helping and how they want help.
New to trackagoat? Set up with a coding agent also covers sign-up and plan limits.
Claude.ai and Claude Desktop (custom connector)#
Claude connects natively: no API key, no config file, no mcp-remote. You sign in with your trackagoat account and choose what Claude may do.
Add the connector
In Claude, open Settings → Connectors (on claude.ai: Customize → Connectors) and choose Add custom connector. Enter:
- Name:
trackagoat - Remote MCP server URL:
https://www.trackagoat.com/api/mcp
Leave the advanced OAuth client ID and secret fields empty. On Team and Enterprise plans, an Owner adds the connector once for the organization and each person then connects their own account.
- Name:
Sign in and approve
Click Connect. A trackagoat window opens. Sign in if you aren't already, then:
- pick the organization Claude may see (one per connection), and
- choose View data (always on) and, optionally, Make changes for the write tools.
Click Allow access. You're returned to Claude and the trackagoat tools appear in the connector list.
Use it
Enable the connector in a chat (the + / tools menu) and ask about your creators. Claude Desktop, Claude mobile and claude.ai share the same connection.
Good to know:
- Claude acts as you, limited to what you allowed and to your current role. If your role changes or you leave the organization, its access changes or stops at once.
- If you allowed only View data and later ask Claude to change something, Claude asks you to reconnect and approve Make changes.
- To use a second organization, add the connector again and pick the other organization.
- To disconnect, remove the connector in Claude, or go to Settings → Connected Apps in trackagoat. Org admins can also disconnect any member's app under Org settings → API keys → Connected apps.
- Connected apps don't use up your plan's API key limit, but every tool call counts toward the org's daily API requests, like a key. Every plan can connect apps; Free allows 200 requests a day.
The same sign-in works for other MCP clients that support OAuth, including Claude Code, Codex, Cursor and VS Code: give them the URL above and they discover everything else from it. See Connect a client.
Get an API key#
Use an API key for scripts, and for clients that can't sign in with OAuth. In trackagoat, go to Org settings → API keys → + New API key. Name it after the client (e.g. Claude Code laptop) and choose scopes:
read: required for every read tool.write: required for the write tools. Leave it off if the agent should only read.
Copy the key: it's shown once. See Authentication and API keys for expiry and revocation. A key acts on behalf of one member: the admin who created it, or the member picked under Acts as. It can never do more than that member can in the app, and it stops working if they leave the org. A key made for someone else also stops working if the admin who created it leaves, is changed to member or is suspended (see Who a key acts as).
Connect a client#
Each client below can sign in (no key) or send an API key. Keep keys in an environment variable such as TRACKAGOAT_API_KEY, never in a committed file.
Claude Code#
Sign in:
claude mcp add --transport http trackagoat https://www.trackagoat.com/api/mcpThen run /mcp in Claude Code, select trackagoat and sign in. With an API key instead:
claude mcp add --transport http trackagoat https://www.trackagoat.com/api/mcp \
--header "Authorization: Bearer $TRACKAGOAT_API_KEY"Add --scope user to make it available in every project. To share the setup with your team without committing a key, put this in the repo's .mcp.json and have each person export TRACKAGOAT_API_KEY:
{
"mcpServers": {
"trackagoat": {
"type": "http",
"url": "https://www.trackagoat.com/api/mcp",
"headers": { "Authorization": "Bearer ${TRACKAGOAT_API_KEY}" }
}
}
}Run /mcp in Claude Code to confirm trackagoat shows as connected.
Codex CLI#
Sign in:
codex mcp add trackagoat --url https://www.trackagoat.com/api/mcp
codex mcp login trackagoatWith an API key instead, Codex reads the variable each time it starts:
codex mcp add trackagoat --url https://www.trackagoat.com/api/mcp \
--bearer-token-env-var TRACKAGOAT_API_KEYCursor#
Add to ~/.cursor/mcp.json (all projects) or .cursor/mcp.json (one project). To sign in, leave out headers and sign in from Cursor's MCP settings. With an API key:
{
"mcpServers": {
"trackagoat": {
"url": "https://www.trackagoat.com/api/mcp",
"headers": { "Authorization": "Bearer ${env:TRACKAGOAT_API_KEY}" }
}
}
}VS Code#
Add to .vscode/mcp.json, then start the server. Without headers (and inputs), VS Code asks you to sign in. With an API key, VS Code prompts for it once and stores it securely:
{
"inputs": [
{ "type": "promptString", "id": "trackagoat-key", "description": "trackagoat API key", "password": true }
],
"servers": {
"trackagoat": {
"type": "http",
"url": "https://www.trackagoat.com/api/mcp",
"headers": { "Authorization": "Bearer ${input:trackagoat-key}" }
}
}
}Stdio-only clients#
For clients that only launch local (stdio) servers, bridge with mcp-remote (requires Node.js 18+). For example, in Claude Desktop's claude_desktop_config.json (Settings → Developer → Edit config), though the custom connector is simpler there:
{
"mcpServers": {
"trackagoat": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://www.trackagoat.com/api/mcp",
"--header",
"Authorization:${TRACKAGOAT_AUTH}"
],
"env": { "TRACKAGOAT_AUTH": "Bearer tga_<key>" }
}
}
}Keep Authorization:${TRACKAGOAT_AUTH} without spaces: some clients split arguments on spaces, so the Bearer prefix goes in the env var.
Other clients#
Any client that supports Streamable HTTP works: either let it sign in with OAuth (it discovers the authorization server from the 401 response, per the MCP authorization spec), or send Authorization: Bearer tga_<key> on every request.
Tools#
Each tool's description and input schema are served to your client, so the agent sees parameter docs directly. Schemas are strict: a parameter a tool doesn't have (say range on get_analytics, which takes from and to) is rejected with unknown_parameter instead of being silently ignored. Tool results are compact JSON: image URLs are dropped, and list tools preview long readme notes (call the matching get_* tool for the full text).
Read tools#
All require the read scope, except get_changelog, which works on any connection. Tools marked Org admin only also need the connection to act as an org admin, like the matching page in the app; for anyone else they return insufficient_role. Each tool's description says the same.
Projects, creators, accounts and videos
| Tool | What it does | REST equivalent |
|---|---|---|
list_projects | Projects in the org, with their readme | GET /api/v2/projects |
list_creators | Creators with accounts and totals; filter by project, platform, search | GET /api/v2/creators |
get_creator | One creator: full readme and its readme_version, metadata, every account's stats, tracking config and last_scraped_at | GET /api/v2/creators/{id} |
list_accounts | Platform accounts with counts and tracking mode; filter by project, creator, platform, handle | GET /api/v2/accounts |
get_account | One platform account in full | GET /api/v2/accounts/{id} |
get_account_stats | Follower, following, like and video-count snapshots over time for one account | GET /api/v2/accounts/{id}/stats |
list_videos | Tracked videos, newest added first, with counts and the start of each caption; filter by project, creator, account, platform, content group | GET /api/v2/videos |
get_video_stats | One video's latest counts, caption, notes (readme + readme_version), tracking status and flags | GET /api/v2/videos/{id} |
list_content_groups | Content groups: the same content posted on several platforms, linked as one | GET /api/v2/content-groups |
get_content_group | One content group and its video ids | GET /api/v2/content-groups/{id} |
get_content_group_stats | Views, likes, comments and shares summed across a content group, and per platform | GET /api/v2/content-groups/{id}/stats |
get_share_link | A creator's shareable page: url, enabled, sections shown. Pass include_pin: true to also get the entrance PIN, which needs the write scope. Org admin only. | GET /api/v2/creators/{id}/share-link |
get_schema | The data model: entities, fields, relationships | GET /api/v2/schema |
Comments (paid plans; 403 plan_feature_unavailable on Free)
| Tool | What it does | REST equivalent |
|---|---|---|
list_comments | Comments collected on a project's videos, most liked first: text, likes, sentiment and signals (app_question, signup_intent, ad_disclosure, risk, pay_talk, referral_spam, brand_mention, competitor). Filter by signal (flagged = ad doubts or brand-safety words), sentiment, creator, campaign, platform, dates, text. Paginate with next_cursor | GET /api/v2/projects/{id}/comments |
list_video_comments | One video's Comments tab: every collected comment with sentiment and signals, the sentiment split and per-signal counts, and coverage (platform count vs collected, last collected). Filter by signal, sentiment, text; paginate with next_offset | GET /api/v2/videos/{id}/comments |
get_comment_signals_summary | Comment Insights in one call: coverage, sentiment and signal counts, a row per creator (comments per 1,000 views, positive share, app questions, sign-ups, flagged, top comment) and positive share over time. creator_sort ranks creators (e.g. app_question_count for "who gets the most app questions"), creator_limit keeps the top N | GET /api/v2/projects/{id}/comment-signals |
get_comment_flags | The weekly flag digest on demand: comments in the last days (default 7) asking if a post is an ad or using words like scam, the most-liked of them, and creators whose positive share fell 20+ points against the 30 days before | GET /api/v2/projects/{id}/comment-flags |
get_comment_settings | The org's minimum comment count and brand / competitor terms (Org settings → Comments), and whether the plan collects comments. Works on every plan. Org admin only. | GET /api/v2/comment-settings |
Program health, goals and campaigns
| Tool | What it does | REST equivalent |
|---|---|---|
get_program_health | A project's (or one campaign's) health in one call: healthy / at-risk / degraded verdict and the signals behind it, KPIs, creators who stopped posting, goal compliance, alerts (sudden view drops, tracking gaps, private accounts, disabled creators, over-posting, flagged comments), top and under-performers. Optional campaign_id and range (7d, 14d, 30d default, 90d) | GET /api/v2/projects/{id}/program-health |
get_goal_compliance | Goal target vs actual and status per creator in a project | GET /api/v2/projects/{id}/goal-compliance |
get_goal_compliance_summary | Count of a project's goals by status (on track, at risk, missed) | GET /api/v2/analytics/aggregate/goal-compliance |
list_campaigns | Campaigns with their readme | GET /api/v2/campaigns |
get_campaign_stats | Per-campaign totals for tracked posts posted in a date range (default the last 30 days including today, org time zone), with prior-period delta. Don't add rows up (shared videos appear in several rows): use get_metric_totals with campaigns=all. Pass campaign_id for one campaign (project_id is then optional: it comes from the campaign), or project_id alone to compare every campaign in the project | GET /api/v2/analytics/aggregate/campaign-leaderboard |
get_metric_totals | Headline totals for a project, one campaign or every campaign at once (campaigns=all, each video counted once): tracked posts, views, likes, comments, shares, saves, weighted engagement rate, creators who posted, followers and follower growth, posts awaiting review, and stats freshness. The same numbers as the dashboard and Insights. Default window: the last 30 days including today, org time zone | GET /api/v2/analytics/aggregate/summary |
get_campaign_progress | Each campaign's view target, current views, percent done, days left and status | GET /api/v2/analytics/aggregate/campaign-progress |
get_campaign_trends | Views gained, posts, creators posting and first-time creators per day, week, month or year, for one campaign or the whole project | GET /api/v2/analytics/aggregate/campaign-timeseries |
get_member_overlap | Creators or videos that are in more than one campaign | GET /api/v2/analytics/aggregate/member-overlap |
Analytics
| Tool | What it does | REST equivalent |
|---|---|---|
get_analytics | Time series for a video, creator or campaign: any metric, granularity, prior-period comparison, top-N breakdown | GET /api/v2/analytics |
list_top_videos | Rank a project's videos by views, likes, comments, shares, saves or posted date; filter by posted date range, platform, campaign | GET /api/v2/analytics/aggregate/video-leaderboard |
list_top_creators | Rank creators by views on videos posted in a range, with follower change, posts per week and engagement | GET /api/v2/analytics/aggregate/creator-leaderboard |
list_top_accounts | The same ranking per platform account; filter by platform or campaign | GET /api/v2/analytics/aggregate/account-leaderboard |
list_outlier_videos | Videos that beat their creator's median views by a multiple (default 1.5×) | GET /api/v2/analytics/aggregate/outliers |
get_creator_scatter | Follower change vs engagement rate per creator | GET /api/v2/analytics/aggregate/creator-scatter |
get_posting_heatmap | Posts and average views by weekday and hour | GET /api/v2/analytics/aggregate/posting-heatmap |
get_posting_consistency | Posts per creator per day | GET /api/v2/analytics/aggregate/posting-consistency |
get_over_posting_risks | Days a creator posted so often that some videos were held back from tracking | GET /api/v2/analytics/aggregate/over-posting-risks |
get_view_distribution | Histogram and percentiles of video views | GET /api/v2/analytics/aggregate/view-distribution |
list_annotations | Dated notes on a creator's, campaign's or video's charts, added by people or automatically | GET /api/v2/analytics/annotations |
The heatmap, consistency, over-posting, view-distribution and campaign-trend tools default to the last 30 days when from and to are left out.
Conversions
| Tool | What it does | REST equivalent |
|---|---|---|
list_conversion_events | A project's conversion events (e.g. signup, purchase) and their default values | GET /api/v2/projects/{id}/conversion-events |
get_conversion_event | One conversion event | GET /api/v2/projects/{id}/conversion-events/{eventId} |
list_conversions | Recorded conversions; filter by event, creator, account, video, source, status and time | GET /api/v2/projects/{id}/conversions |
get_conversion | One recorded conversion | GET /api/v2/projects/{id}/conversions/{conversionId} |
get_conversion_summary | Count and value of conversions in a range, one row per currency | GET /api/v2/analytics/aggregate/conversion-summary |
list_top_converters | Creators ranked by conversion value | GET /api/v2/analytics/aggregate/conversion-leaderboard |
get_conversion_timeseries | Conversions per day, one row per day and currency | GET /api/v2/analytics/aggregate/conversion-timeseries |
Payouts
| Tool | What it does | REST equivalent |
|---|---|---|
list_payout_structures | Payout structures with their current rule: type, period, amount and criteria_params (for CPM: tiers, minimum, cap and view_lifetime_days); filter by project and active state | GET /api/v2/payout-structures |
get_payout_structure | One structure with its current rule, earlier versions and assignment count | GET /api/v2/payout-structures/{id} |
list_payout_assignments | Creators assigned to a structure | GET /api/v2/payout-structures/{id}/assignments |
list_payout_accruals | Earned / paid / rejected / voided payout accruals; filter by project, creator, structure, status, period | GET /api/v2/payout-accruals |
get_payout_accrual | One accrual, including how it was calculated (inputs_snapshot) | GET /api/v2/payout-accruals/{id} |
list_payout_methods | The org's payout methods (PayPal, Venmo, …) | GET /api/v2/payout-methods |
get_payout_method | One payout method | GET /api/v2/payout-methods/{id} |
list_payout_payments | Recorded payments and the accruals each settled; filter by project, creator, status, date | GET /api/v2/payout-payments |
get_payout_payment | One recorded payment | GET /api/v2/payout-payments/{id} |
get_payout_account | Whether a creator can be paid through the connected provider (Dots), who they're paid as, and the org's agent-payment switch and limits. Org admin only. | GET /api/v2/creators/{id}/payee-links |
Notes and documents
| Tool | What it does | REST equivalent |
|---|---|---|
list_notes | Every document with text in the org (organization, projects, campaigns, creators, videos, payout methods, structures, payments and members), with a preview; filter by type, project or text | GET /api/v2/notes |
get_notes | One document in full with its readme_version; entity_type=me is the person you're helping, member a teammate | GET /api/v2/notes/{entity_type}/{id} |
get_my_profile | Who the connection acts as: name, org and role, scopes, and their personalization document | GET /api/v2/me |
list_members | The org's members and whether each has a personalization document | GET /api/v2/members |
Exports
| Tool | What it does | REST equivalent |
|---|---|---|
export_csv | Any CSV the app exports (creators, videos, campaigns, goals, the campaign leaderboard, the payouts tracker, payments, accruals and Insights charts) with the same columns and filters, as a file for the agent to save. See Exporting CSVs | GET /api/v2/exports/{dataset} |
What's new in trackagoat
| Tool | What it does | REST equivalent |
|---|---|---|
get_changelog | Changelog entries, newest first: date, title, link to the entry in the docs and its text as Markdown. Filter by since (a date) and q (search words). Needs no scope and doesn't count toward the daily request limit. Ask your agent "what's new in trackagoat?" and it uses this tool | GET /api/v2/changelog |
The data model is also available as the MCP resource trackagoat://schema.
Write tools#
All require the write scope (Make changes when connecting with sign-in). A key without it gets an insufficient_scope error and nothing is changed; a signed-in client is asked to reconnect with Make changes. Tools marked can't be undone are annotated destructiveHint: true, so most clients ask before running them. Tools marked Org admin only need the connection to act as an org admin (insufficient_role otherwise).
Creators and accounts
| Tool | What it does | REST equivalent |
|---|---|---|
add_creator | Track a creator with one or more platform accounts; starts a profile + video-discovery scrape | POST /api/v2/creators |
add_creators | Track up to 50 creators in one project in one call | POST /api/v2/projects/{id}/creators |
add_account | Add another platform account to an existing creator | POST /api/v2/creators/{id}/accounts |
update_creator | Rename a creator or replace their metadata | PATCH /api/v2/creators/{id} |
update_account | Rename an account's handle, change its tracking mode, hashtags or tracking dates | PATCH /api/v2/accounts/{id} |
reenable_creators | Turn tracking back on for creators trackagoat disabled automatically. Org admin only. | POST /api/v2/projects/{id}/creators/bulk-reenable |
remove_creator | Stop tracking a creator and all their accounts. Can't be undone through MCP or the API. Org admin only. | DELETE /api/v2/creators/{id} |
bulk_remove_creators | The same for up to 100 creators. Can't be undone. Org admin only. | POST /api/v2/projects/{id}/creators/bulk-remove |
remove_account | Stop tracking one account of a creator. Can't be undone (re-add with add_account). Org admin only. | DELETE /api/v2/accounts/{id} |
trigger_scrape | Refresh one account (profile, video stats or new-video discovery), a creator's primary account, or one video now. Org admin only. | POST /api/v2/accounts/{id}/scrape, POST /api/v2/creators/{id}/scrape, POST /api/v2/videos/{id}/scrape |
update_notes | Add to or replace any document (readme) without overwriting human edits: creators, videos, campaigns, projects, the organization, payout records, or me. Organization, project and payout documents are org admin only. See Notes and documents | POST /api/v2/notes/{entity_type}/{id} (creators and videos: POST /api/v2/creators/{id}/notes, POST /api/v2/videos/{id}/notes) |
update_my_readme | Save the personalization document of the person you're helping, after they approve the draft. Needs expected_readme_version | PATCH /api/v2/me |
Videos
| Tool | What it does | REST equivalent |
|---|---|---|
add_video_by_url | Track 1 to 50 videos by URL (TikTok or Instagram; YouTube isn't live yet) | POST /api/v2/projects/{id}/videos |
update_video | Change a video's title or tracking status (notes go through update_notes) | PATCH /api/v2/videos/{id} |
review_inbox | Include or exclude videos waiting in the Tracking Inbox, by id or for a whole creator | PATCH /api/v2/projects/{id}/inbox |
set_video_tracking | Stop or resume stats tracking for one video, or clear its age-rule exemption. Org admin only. | POST /api/v2/videos/{id}/tracking-disable, …/tracking-enable, …/tracking-unexempt |
bulk_set_video_tracking | Stop or resume tracking for up to 200 videos (optionally exempting them from age rules). Org admin only. | POST /api/v2/projects/{id}/videos/bulk-tracking-disable, …/bulk-tracking-enable |
Campaigns, goals, content groups and share pages
| Tool | What it does | REST equivalent |
|---|---|---|
create_campaign | Create an empty campaign in a project | POST /api/v2/projects/{id}/campaigns |
update_campaign | Rename a campaign, replace its readme (pass expected_readme_version to get notes_conflict instead of overwriting a newer edit), or set its view target and deadline | PATCH /api/v2/campaigns/{id} |
add_to_campaign | Add a creator, video or sub-campaign to a campaign | POST /api/v2/campaigns/{id}/items |
remove_from_campaign | Take a creator, video or sub-campaign out of a campaign (the item itself is kept) | DELETE /api/v2/campaigns/{id}/items |
delete_campaign | Permanently delete a campaign and its membership list. Can't be undone. Org admin only. | DELETE /api/v2/campaigns/{id} |
create_goal | Give a creator a posts / views / engagement / followers goal per day, week or month | POST /api/v2/creators/{id}/goals |
update_goal | Change a goal's metric, period, target or dates, or pause it (is_active: false) | PATCH /api/v2/creators/{id}/goals/{goalId} |
delete_goal | Permanently delete a goal. Can't be undone, and goal-based payouts for periods not yet calculated are judged without it; ending it with update_goal (end_date) is safer | DELETE /api/v2/creators/{id}/goals/{goalId} |
create_content_group | Link the same content posted on several platforms | POST /api/v2/content-groups |
update_content_group | Rename a content group, change its notes, add or remove videos | PATCH /api/v2/content-groups/{id} |
delete_content_group | Permanently delete a content group (its videos are kept). Can't be undone | DELETE /api/v2/content-groups/{id} |
create_share_link | Create or replace a creator's PIN-protected page; returns the url and PIN. Org admin only. | POST /api/v2/creators/{id}/share-link |
update_share_link | Turn a share page off or on, change its sections, or set a new PIN. Org admin only. | PATCH /api/v2/creators/{id}/share-link |
bulk_create_share_links | Create share pages for up to 200 creators; returns every url and PIN. Org admin only. | POST /api/v2/share-links/bulk |
delete_share_link | Permanently delete a creator's share page. Can't be undone; prefer update_share_link with enabled: false. Org admin only. | DELETE /api/v2/creators/{id}/share-link |
create_annotation | Add a dated note to a creator's, campaign's or video's charts | POST /api/v2/analytics/annotations |
update_annotation | Change an annotation someone added | PATCH /api/v2/analytics/annotations/{id} |
delete_annotation | Permanently delete an annotation someone added. Can't be undone | DELETE /api/v2/analytics/annotations/{id} |
Comment settings
| Tool | What it does | REST equivalent |
|---|---|---|
update_comment_settings | Set the minimum comment count and replace the brand or competitor terms behind the brand_mention and competitor signals. Org admin only. | PATCH /api/v2/comment-settings |
Conversions
| Tool | What it does | REST equivalent |
|---|---|---|
create_conversion_event | Define a kind of conversion (e.g. signup) with a default value | POST /api/v2/projects/{id}/conversion-events |
update_conversion_event | Change an event's name, description, default value or metadata, or deactivate / reactivate it | PATCH /api/v2/projects/{id}/conversion-events/{eventId} (deactivating is the same as DELETE …/{eventId}) |
record_conversions | Record 1 to 500 conversions credited to creators, accounts or videos; external_id dedupes repeats | POST /api/v2/projects/{id}/conversions |
void_conversion | Void a conversion (refund, chargeback, fraud): excluded from totals, kept for audit. Can't be undone. Org admin only. | DELETE /api/v2/projects/{id}/conversions/{conversionId} (mode=void) |
Payouts
| Tool | What it does | REST equivalent |
|---|---|---|
create_payout_structure | Create a payout rule: recurring, goals, CPM, view-threshold bonus or per conversion. Org admin only. | POST /api/v2/payout-structures |
update_payout_rule | Replace a structure's rule with a new version, effective from the period in progress. Org admin only. | PATCH /api/v2/payout-structures/{id} (kind: "rule") |
set_cpm_view_lifetime | Set how long after posting a video keeps earning on a CPM structure (view_lifetime_days, or null for forever). Saves a new version with nothing else changed, effective from the period in progress. Counts as two API requests. Org admin only. | GET then PATCH /api/v2/payout-structures/{id} |
update_payout_structure | Rename a structure, replace its notes or metadata, or un-archive it. Org admin only. | PATCH /api/v2/payout-structures/{id} (kind: "cosmetic") |
archive_payout_structure | Stop a structure earning and end every assignment; past accruals stay payable. Un-archiving doesn't bring the assignments back. Org admin only. | DELETE /api/v2/payout-structures/{id} (mode=archive) |
delete_payout_structure | Permanently delete a structure that never produced an accrual. Can't be undone. Org admin only. | DELETE /api/v2/payout-structures/{id}?mode=hard |
assign_payout_structure | Put creators on a structure, from now or a later date. Org admin only. | POST /api/v2/payout-structures/{id}/assignments |
unassign_payout_structure | Take creators off a structure; what they earned stays payable. Org admin only. | DELETE /api/v2/payout-structures/{id}/assignments |
set_accrual_status | Reject or void an earned accrual so it is no longer owed. Can't be undone. Org admin only. | PATCH /api/v2/payout-accruals/{id} |
create_payout_method | Add a payout method (e.g. Wise). Org admin only. | POST /api/v2/payout-methods |
update_payout_method | Rename a method, replace its notes or metadata, set or remove its icon (icon_path), or disable / re-enable it. Org admin only. | PATCH /api/v2/payout-methods/{id} |
delete_payout_method | Permanently delete a payout method. Can't be undone; prefer disabling it. Org admin only. | DELETE /api/v2/payout-methods/{id} |
record_payout_payment | Record a payment made outside trackagoat and mark the accruals it covers as paid, optionally with a receipt (payment_id + attachment_path). It doesn't send money. Requires idempotency_key. Org admin only. | POST /api/v2/payout-payments |
update_payout_payment | Replace a payment's notes or metadata. Org admin only. | PATCH /api/v2/payout-payments/{id} |
send_payout | Sends real money through the org's connected provider (Dots) and records the payment. Only works after an org admin turns on agent payments, within the org's limits. Supports a note to the creator, SMS text, description and 1099 exemption. Requires idempotency_key. Org admin only. | POST /api/v2/payout-payments/send |
void_payout_payment | Void a payment; its accruals and supplemental amounts go back to owed. Can't be undone. Org admin only. | PATCH /api/v2/payout-payments/{id} (status: "voided") |
get_payouts_tracker | Per-creator earned, paid, adjustments and outstanding for a project, with totals (earned − paid + adjustments = outstanding) | GET /api/v2/payouts/tracker |
list_payout_supplementals | List supplemental amounts (owed corrections on top of paid accruals) | GET /api/v2/payout-supplementals |
create_payout_supplemental | Record that a creator is owed more for a paid accrual; settled by record_payout_payment. Requires idempotency_key. Org admin only. | POST /api/v2/payout-supplementals |
void_payout_supplemental | Void an owed supplemental amount. Can't be undone. Org admin only. | PATCH /api/v2/payout-supplementals/{id} (status: "void") |
Receipts and method icons
| Tool | What it does | REST equivalent |
|---|---|---|
upload_receipt | Upload a payment receipt (up to 3 MB) as base64; returns the path to pass to record_payout_payment. Org admin only. | POST /api/v2/payouts/payment-receipts |
get_receipt_upload_url | Get a signed URL to PUT a receipt of up to 5 MB to (valid 2 hours), and the path to pass back. Org admin only. | POST /api/v2/payouts/payment-receipts/upload-url |
upload_payout_method_icon | Upload a PNG, JPEG or WebP icon (up to 1 MB) as base64 and set it on a payout method. Org admin only. | POST /api/v2/payout-methods/{id}/icon |
get_payout_method_icon_upload_url | Get a signed URL to PUT an icon to, and the path to set with update_payout_method. Org admin only. | POST /api/v2/payout-methods/{id}/icon/upload-url |
To attach a receipt, the agent generates a UUID as payment_id, uploads the file under it (upload_receipt, or get_receipt_upload_url and a PUT of the raw bytes with the same Content-Type), then calls record_payout_payment with that payment_id and attachment_path set to the returned path. A receipt can only be attached when the payment is recorded, as in the app. Allowed receipt types: PNG, JPEG, WebP, PDF, CSV, Word and Excel. Inline uploads are checked: the file's contents must match content_type.
Tools that create something or act in bulk accept an optional idempotency_key (it is sent as the REST Idempotency-Key header). Have the agent pass a fresh UUID per logical write: if a call times out and is retried with the same key and arguments within 24 hours, you get the original result (marked "replayed": true) instead of a duplicate. A retry while the first call is still running fails with idempotency_in_progress (try again in a couple of seconds), and reusing a key with different arguments fails with idempotency_key_reused. record_payout_payment, send_payout and create_payout_supplemental require a key. Tools that set a value (update_*, set_*, deletes, voids, assignments) have no key because repeating them has the same effect; set_cpm_view_lifetime takes one anyway. Three creates have no key because their REST endpoints don't support one: create_payout_structure and create_annotation (check the list before retrying) and create_payout_method (names are unique, so a repeat fails with conflict_name). trigger_scrape has no key: it's limited by the manual-scrape limits instead. The upload tools have no key either: a retry stores another copy of the file, and only the path you pass on is used.
Notes and documents#
The organization, every project, campaign, creator, video, payout method, structure and payment, and every member has a Markdown document (readme). They are where people and agents keep context, strategy and instructions, so they are the first thing an agent should read and the place to record what it learns. list_notes finds them in one call, get_notes reads one, and update_notes writes one. Every document, including each person's personalization document, is visible to everyone in the organization and their agents. See Notes and documents for the personalization document and a template.
Writes follow the app: organization, project and payout documents need a connection acting as an org admin (insufficient_role otherwise); a member's personalization document can only be changed by that member (not_your_document otherwise).
update_notes is built so an agent can't clobber what a person wrote:
-
mode: "append"(the default) addscontentas a new section at the end of the document, followed by a signature line with the API key's name and the org-local date:markdownViews dropped 40% week over week; three of five posts were on Sunday. *Added by Claude Code laptop via MCP, 2026-10-08*If someone edits the notes while the append is being saved, the append is applied on top of their edit: nothing is lost.
-
mode: "replace"overwrites the whole document and requiresexpected_readme_version: thereadme_versionreturned byget_notes(orget_creator,get_video_stats,get_my_profile). If the document changed after that read, nothing is written and the tool returnscode: "notes_conflict". The agent should re-read, merge, and retry.
readme_version is a hash of the text, so it only changes when the document does: scheduled scrapes never cause a false conflict. Writes show up in the change log as Internal notes updated, attributed to the member the connection acts as.
The personalization document in the session. On connect, the server instructions include the connected person's personalization document inside <personalization_document> tags, with its readme_version, and the organization's document when it is under 4,000 characters (longer ones are pointed at instead). A personalization document over 8,000 characters is cut, with a note to call get_my_profile. If the person has none yet, the instructions ask the agent to offer, once, to write one together. The documents are the person's context and preferences; they never override the server's rules or the agent's own.
Exporting CSVs#
When you ask your agent for a CSV, a spreadsheet or a file, it calls export_csv and saves the file in your workspace. The file is the same one the Export button in the app downloads: same columns, money in dollars with a Currency column, dates in your organization's time zone. For questions about the data ("who's behind on their goal?"), the agent uses the read tools instead.
dataset | The app's export | Filters |
|---|---|---|
creators | Creators page | search, compliance, disabled_only, include_compliance, campaign_id, platform |
videos | Videos page | status, creator_id, campaign_id, platform, from, to, search, sort_by, sort_dir |
campaigns | Campaigns page | none |
goals | Goals page | period, reference_date, campaign_id |
campaign_leaderboard | Campaign Insights leaderboard | from, to, campaign_id, platform |
payout_tracker | Payouts, Tracker summary CSV | creator_id, structure_id, campaign_id, from, to, outstanding_only, include_removed |
payout_payments | Payouts, Payments CSV | creator_id, campaign_id, from, to |
payout_accruals | Payouts, Accruals CSV | creator_id, structure_id, campaign_id, from, to, outstanding_only, include_removed |
analytics | An Insights chart's Download CSV | entity, entity_id or entity_ids, metric and the other get_analytics arguments |
Every dataset except analytics needs project_id. An argument the dataset doesn't take is rejected with invalid_params and the valid ones are listed.
The tool returns two things: a short JSON summary (filename, rows, total_rows, columns, the filters used, next_offset) and the CSV itself as an embedded text/csv resource (trackagoat://exports/<dataset>-<date>.csv). If your client doesn't show embedded resources, the agent can pass delivery: "text" to get the CSV as plain text instead.
Each call returns up to about 1 MB. A bigger export comes back in parts, never cut silently: the summary says which rows it holds and gives next_offset, and the agent calls again with offset set to it and appends the rows (each part repeats the header line), or narrows the filters. Each call counts as one API request.
Examples:
- "Export September payouts to a CSV." The agent calls
export_csvwithdataset: "payout_tracker", the project,from: "2026-09-01"andto: "2026-09-30", then savespayouts-tracker-….csv. - "Give me all videos from the Spring Launch campaign as a spreadsheet." The agent finds the campaign with
list_campaigns, then callsexport_csvwithdataset: "videos"and itscampaign_id.
What the MCP server doesn't do#
Everything an organization's API key can do through /api/v2 can also be done over MCP, except the following, which are left out on purpose:
| Not available over MCP | Why |
|---|---|
Creating and revoking API keys (/api/v2/organizations/{orgId}/api-keys) | Keys are credentials. An agent shouldn't mint or revoke them; an org admin does that in Org settings → API keys. |
Organization administration: creating an organization, creating or renaming projects, inviting, changing or removing members, cancelling invitations (/api/v2/user/organizations, /api/v2/organizations/{orgId}/…) | These need the admin scope. Sign-in connections never get it, and MCP tools only use read and write. Creating an organization also acts outside the connected organization. |
Permanently deleting a conversion or conversion event (mode=hard) | Needs the admin scope, because it erases revenue history. Use void_conversion or update_conversion_event with is_active: false. |
Removing a video (DELETE /api/v2/videos/{id}) | Use set_video_tracking or review_inbox to stop counting a video (or update_video with tracking_status: "excluded", which is what the REST DELETE does). |
trackagoat staff endpoints (/api/v2/admin/…) | Platform administration, not part of an organization's data. |
The OpenAPI documents (/api/v2/openapi.json, /api/v2/analytics/schema) | They describe the REST API itself; MCP clients get each tool's schema from the server, and get_schema describes the data model. |
The retired /api/v2/creators/{id}/stats and /api/v2/campaigns/{id}/stats | They return 410 Gone. Use get_analytics. |
Limits#
- Each tool call counts as one API request toward your org's daily
max_api_requests_per_daylimit and the per-key limit of 60 requests per minute, the same as a REST call. Connecting and listing tools are free. A signed-in connection is limited like one key. get_changelogis the exception: it reads public content, so it never counts toward the daily limit. It has its own limit of 60 calls per minute per key or connection.- Protocol traffic (connect, list tools, ping) is capped at 120 requests per minute per key or connection.
trigger_scrapealso counts against your plan's daily manual-scrape limit.add_creator,add_creators,add_accountandadd_video_by_urlcount against your plan's account and video limits;create_campaign,create_conversion_event,create_payout_structureandcreate_payout_methodcount against their plan limits.set_cpm_view_lifetimecounts as two API requests (it reads the structure, then saves it).- Analytics ranges can't start before your plan's data-retention window.
When a limit is hit the tool returns an error with code: "rate_limit_exceeded" and retry_after_seconds. See Limits & plan tiers.
Errors#
Tool failures come back as MCP tool errors (isError: true) whose text is JSON:
{
"error": "add_creator requires the 'write' scope. Granted: [read]",
"code": "insufficient_scope",
"status": 403,
"hint": "This API key lacks the 'write' scope. An org admin can create a key with that scope in Org settings → API keys."
}code and status match the REST error codes; every error has a code, so an agent can branch on it instead of parsing error. When the route returns extra context, it's in details. Codes you'll see most:
| Code | Status | Meaning |
|---|---|---|
unknown_parameter | 400 | The call passed a parameter the tool doesn't have. error names it and lists the valid ones; details has unknown_parameters, valid_parameters and, for near-misses like projectId, did_you_mean. Nothing ran. |
invalid_params | 400 | A parameter has the wrong type or value; details lists the fields. |
already_tracked | 409 | add_creator: a handle is already tracked in the project. error names the handle and the creator; details has creator_id and account_id. Nothing was created. |
duplicate_account | 400 | add_creator: the same platform + handle appears twice in accounts. |
not_found | 404 | No such id in your organization. |
insufficient_scope | 403 | The key or connection lacks the scope the tool needs. |
insufficient_role | 403 | Only org admins can do this in the app, and the connection acts as a member who isn't one: for example payments and payout setup, removing or re-enabling creators, removing accounts, stopping or resuming video tracking, trigger_scrape, organization and project documents, share pages, send_payout, get_payout_account and the comment settings. Every such tool says Org admin only above and in its description. |
not_your_document | 403 | update_notes on another member's personalization document. Only its owner can change it; read it with get_notes. |
notes_conflict | 409 | A replace whose expected_readme_version is out of date. Nothing was written: re-read, merge, retry. |
plan_feature_unavailable | 403 | The organization's plan doesn't include the feature: Comment Insights tools on the Free plan. Retrying won't help. |
limit_reached | 402 | A plan limit; details has the limit and current usage. |
rate_limit_exceeded | 429 | Wait retry_after_seconds. |
{
"error": "Unknown parameter 'range'. Valid parameters: entity, entity_id, entity_ids, metric, granularity, bucket_days, mode, from, to, compare, breakdown, top_n, base_metric.",
"code": "unknown_parameter",
"status": 400,
"hint": "get_analytics accepts only the parameters listed above; unknown ones are rejected rather than ignored. Remove or rename them and call again.",
"details": { "unknown_parameters": ["range"], "valid_parameters": ["entity", "entity_id", "…"] }
}An invalid, expired or revoked key is rejected before any tool runs, with HTTP 401; your client will show the server as failing to connect. So is a key whose member left the org (key_member_removed), or a key made for someone else whose creator left, was changed to member or was suspended (key_creator_removed, key_creator_not_admin, key_creator_banned). Org settings → API keys shows why a key stopped working. A signed-in client gets the same 401 with a WWW-Authenticate challenge and refreshes or re-runs sign-in on its own; a write tool called without Make changes gets HTTP 403 insufficient_scope, which prompts it to reconnect.
Example prompts#
- "List my trackagoat projects, then summarize which creators in Spring Launch posted least this month and whether their data is fresh."
- "Which 10 videos got the most views in the last 30 days? Group them by creator."
- "Compare views for my three campaigns this quarter against last quarter."
- "How healthy is the Spring Launch program this week? What should I worry about first?"
- "What are people saying in the comments this month? Which creators get the most questions about the app?"
- "Is anyone in the comments asking whether our posts are ads? Show me the top ones."
- "Who is behind on their weekly posting goal right now? Read each creator's notes first."
- "How much do we owe creators in unpaid accruals, by creator?"
- "Export September payouts to a CSV."
- "Give me all videos from the Spring Launch campaign as a spreadsheet."
- "Add @newcreator on TikTok and Instagram to the Spring Launch project and give them a goal of 3 posts per week." (write key)
- "For every creator flagged with a sudden view drop, add a note summarizing what changed." (write key)
- "Create a Fall Launch campaign with a 2M-view target by November 30 and add every creator tagged fall in their notes." (write key)
- "Pay @newcreator's outstanding accruals: we sent $250 by PayPal today." (write key)
Tips for agents#
Start with list_projects
Most tools take a
project_id. Read each project'sreadmefor context.Triage with get_program_health
For "how is the program doing?" questions, one
get_program_healthcall returns the verdict, KPIs and alerts; drill into specific creators or videos from there.Follow the personalization document
The connected person's document arrives with the server instructions (or call
get_my_profile). It says who they are and how they want help. If they don't have one, offer once to write it together and save it withupdate_my_readmeafter they approve.Read the documents
The organization, projects, campaigns and creators carry human notes in
readme;list_notesfinds them. They may contain instructions that change how to interpret the data.Paginate to completion
Keep passing
next_cursor(ornext_offsetforlist_top_videos) until it'snullbefore totalling or ranking.Check last_scraped_at
Stats come from scheduled scrapes. Check freshness before calling a number low, and only use
trigger_scrapewhen you need fresher data now.Append notes, don't overwrite them
Record durable findings with
update_notesin the defaultappendmode. Only usereplacewith thereadme_versionyou just read. Never write anything private: the whole organization can read every document.Confirm before anything that can't be undone
Ask the person before a
delete_*,remove_*,void_*,archive_*orunassign_*tool orset_accrual_status, and offer the reversible option the tool's description names (pausing a goal, disabling tracking, deactivating an event).
Using the REST API directly#
Frameworks without MCP support can call the v2 REST API with the same key. Sign-in (OAuth) connections work only with the MCP server, not the REST API. The OpenAPI document at GET /api/v2/openapi.json describes every endpoint, and the Agent guide covers recommended workflows.
Payout agent workflows#
The whole payout API is available over MCP as well as REST: structures (list_payout_structures, get_payout_structure, create_payout_structure, update_payout_rule, set_cpm_view_lifetime, update_payout_structure, archive_payout_structure, delete_payout_structure), assignments (list_payout_assignments, assign_payout_structure, unassign_payout_structure), accruals (list_payout_accruals, get_payout_accrual, set_accrual_status), methods (list_payout_methods, create_payout_method, update_payout_method, delete_payout_method) payments (list_payout_payments, get_payout_payment, record_payout_payment, update_payout_payment, void_payout_payment), the tracker (get_payouts_tracker), supplemental amounts (list_payout_supplementals, create_payout_supplemental, void_payout_supplemental), sending payouts through Dots (get_payout_account, send_payout; see Paying with Dots), and receipts and method icons (upload_receipt, get_receipt_upload_url, upload_payout_method_icon, get_payout_method_icon_upload_url). The workflows below show the REST calls; each step names the MCP tool that does the same. Reads need the read scope; writes (recording payments, voiding, assigning structures) need the write scope: a read-only key gets 403 insufficient_scope on any mutation. See the Payouts API reference for full endpoint documentation.
Workflow 1: Weekly payout review#
Goal: find all creators with outstanding accruals, summarize total owed, and surface any that have been outstanding more than 30 days.
Over MCP: list_projects, then list_payout_accruals with status: "earned".
Discover the project
bashcurl -s -H "Authorization: Bearer $TGA_KEY" \ "https://www.trackagoat.com/api/v2/projects" | jq '.data[0].id'Store the project ID as
$PROJECT_ID.List outstanding accruals
bashcurl -s -H "Authorization: Bearer $TGA_KEY" \ "https://www.trackagoat.com/api/v2/payout-accruals?project_id=$PROJECT_ID&status=earned" \ | jq '{total: (.data | length), creators: [.data[] | .creator_id] | unique | length}'Paginate using
meta.nextCursoruntilmeta.hasMoreis false.Flag stale accruals
Filter
data[].period_end_atolder than 30 days ago. Report creator handle + amount + how many days outstanding.Expected response shape:
JSON{ "data": [{ "id": "uuid", "creator_id": "uuid", "structure_id": "uuid", "amount_cents": 5000, "currency": "USD", "status": "earned", "period_start_at": "2026-04-07T00:00:00Z", "period_end_at": "2026-04-13T23:59:59Z" }], "meta": { "hasMore": false, "nextCursor": null } }
Workflow 2: Audit unpaid creators across an org#
Goal: identify which creators have earned money but received zero payments, broken down by project.
Over MCP: list_projects, list_payout_structures, list_payout_accruals and list_payout_payments.
List all projects
bashcurl -s -H "Authorization: Bearer $TGA_KEY" \ "https://www.trackagoat.com/api/v2/projects" | jq '[.data[] | {id, name}]'For each project, fetch payout structures
bashcurl -s -H "Authorization: Bearer $TGA_KEY" \ "https://www.trackagoat.com/api/v2/payout-structures?project_id=$PROJECT_ID&is_active=true"Fetch earned accruals per project
bashcurl -s -H "Authorization: Bearer $TGA_KEY" \ "https://www.trackagoat.com/api/v2/payout-accruals?project_id=$PROJECT_ID&status=earned"Fetch all payments
bashcurl -s -H "Authorization: Bearer $TGA_KEY" \ "https://www.trackagoat.com/api/v2/payout-payments?project_id=$PROJECT_ID"Compute the gap
Group accruals by
creator_id. For each creator, sumamount_centsofearnedaccruals. Compare againsttotal_amount_centsofpaidpayments. Report the delta.
Workflow 3: Record a payment for a creator via Venmo#
Goal: settle outstanding accruals for a specific creator and record the payment against the Venmo method.
Over MCP: list_creators with search, list_payout_accruals, list_payout_methods, optionally upload_receipt, then record_payout_payment with a fresh idempotency_key (the tool requires one).
Find the creator
bashcurl -s -H "Authorization: Bearer $TGA_KEY" \ "https://www.trackagoat.com/api/v2/creators?project_id=$PROJECT_ID&search=creatorhandle" \ | jq '.data[0].id'List outstanding accruals for this creator
bashcurl -s -H "Authorization: Bearer $TGA_KEY" \ "https://www.trackagoat.com/api/v2/payout-accruals?project_id=$PROJECT_ID&status=earned" \ | jq '[.data[] | select(.creator_id == $CREATOR_ID)]'Sum the
amount_centsvalues to gettotal_amount_cents.Find the Venmo method ID
bashcurl -s -H "Authorization: Bearer $TGA_KEY" \ "https://www.trackagoat.com/api/v2/payout-methods" \ | jq '.data[] | select(.name == "Venmo") | .id'Record the payment
bashcurl -s -X POST -H "Authorization: Bearer $TGA_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: $(uuidgen)" \ "https://www.trackagoat.com/api/v2/payout-payments" \ -d '{ "creator_id": "CREATOR_UUID", "method_id": "VENMO_METHOD_UUID", "total_amount_cents": 5000, "currency": "USD", "accrual_ids": ["ACCRUAL_UUID_1", "ACCRUAL_UUID_2"], "note": "Recorded by automated weekly review agent", "paid_at": "2026-05-07T15:00:00Z" }'Expected 201 response:
JSON{ "data": { "id": "payment-uuid", "creator_id": "...", "total_amount_cents": 5000, "status": "paid", "paid_at": "2026-05-07T15:00:00Z" } }
Workflow 4: Set up a new creator with a goal-based payout structure#
Goal: assign an existing payout structure to a newly-tracked creator and confirm the assignment is active.
Over MCP: list_payout_structures, assign_payout_structure, then list_payout_assignments.
Confirm the structure exists and is active
bashcurl -s -H "Authorization: Bearer $TGA_KEY" \ "https://www.trackagoat.com/api/v2/payout-structures?project_id=$PROJECT_ID&is_active=true" \ | jq '[.data[] | select(.criteria_type == "goals") | {id, name, period, amount_cents}]'Pick the structure ID you want to assign.
Assign the creator
bashcurl -s -X POST -H "Authorization: Bearer $TGA_KEY" \ -H "Content-Type: application/json" \ "https://www.trackagoat.com/api/v2/payout-structures/$STRUCTURE_ID/assignments" \ -d '{"creator_ids": ["CREATOR_UUID"]}'Expected 201 response:
JSON{ "data": { "assigned": 1, "already_assigned": 0, "not_in_project": 0, "results": [{ "creator_id": "...", "status": "assigned", "assignment_id": "..." }] } }Verify the assignment is active
bashcurl -s -H "Authorization: Bearer $TGA_KEY" \ "https://www.trackagoat.com/api/v2/payout-structures/$STRUCTURE_ID/assignments" \ | jq '[.data[] | select(.unassigned_at == null) | .creator_id]'