Skip to content

API overview

Base URL, response envelope, pagination, plan access, the OpenAPI spec and API versioning.

Updated Oct 10, 2026 · 9 min read

The trackagoat API is a REST API over HTTPS. Authenticate with a Bearer API key, send and receive JSON, and every response has the same shape: { data, error, meta }. Every plan includes API access: Free allows 200 requests a day, Starter 1,000 and Ultra 50,000, with a per-key limit of 60 a minute. See Plans and limits for the live numbers.

Base URL: https://www.trackagoat.com/api/v2

Machine-readable spec#

This is the one place these locations are documented; other pages link here.

The multi-platform model#

Trackagoat 2.0 is multi-platform. A creator is a person or brand, and an account is one of their presences on a platform (tiktok or instagram; the platform enum also accepts youtube, reserved for YouTube tracking, which isn't available yet). A creator owns one or more accounts, and videos hang off accounts.

  • Creators embed their accounts[] array and expose a derived top-level handle (the primary account's handle: TikTok first, else earliest-created).
  • Tracking configuration (tracking_mode, start/end dates, the handle) lives on the account, not the creator.
  • Plan limits count accounts: the thing that gets scraped: not creators.

See the Creators and accounts guide for the full concept.

Authentication#

See Authentication for how to generate and use API keys.

Response envelope#

Every endpoint returns JSON with this shape:

JSON
{
  "data": <payload or null>,
  "error": <error string or null>,
  "meta": <pagination info or null>
}

Successful responses have data set and error: null. Error responses have data: null and error set to a message string.

Pagination#

List endpoints use cursor-based pagination:

bash
GET /api/v2/creators?limit=50&cursor=<value>
ParameterDefaultMaxDescription
limit50100Items per page
cursorNoneNonePass meta.nextCursor from the previous response

The meta object on list responses:

JSON
{
  "hasMore": true,
  "nextCursor": "2026-03-15T10:00:00Z"
}

Keep fetching until meta.hasMore is false.

Date ranges#

Analytics and stats endpoints accept ?from=YYYY-MM-DD&to=YYYY-MM-DD. Both default to the last 30 days if omitted.

bash
GET /api/v2/analytics?entity=creator&entity_id=<uuid>&metric=views&from=2026-01-01&to=2026-03-31

API key scopes#

Keys carry explicit permission scopes set at creation time:

ScopeGrants access to
readAll GET endpoints
writeAll POST, PATCH, and DELETE endpoints
adminOrg-administration endpoints (projects, members, invitations, API keys, creating orgs), PIN reads and hard deletes. Only effective while the key's owner is an org admin

Write endpoints reject keys that only have read scope with 403 insufficient_scope.

A key acts on behalf of one member: the person who created it, or the member an org admin picked under Acts as. It can never do more than that member can in the app. Its scopes are a ceiling, checked against the member's current org role on every request: if they are demoted from org admin the key loses admin and admin-only actions (403 insufficient_role), and if they leave or are removed from the org the key stops working (401 key_member_removed). A key made for someone else also stops working if the admin who created it leaves, is changed to member or is suspended (401 key_creator_removed, key_creator_not_admin, key_creator_banned). GET /api/v2/me shows who a key acts as.

Idempotency#

POST endpoints that create resources accept an Idempotency-Key header (≤ 255 characters). Send a fresh UUID per logical request; if the call times out or the connection drops, retry with the same key and the same body. The action runs at most once.

You send the key again…You get
after the first request finished, with the same bodyThe original status and body, plus an Idempotency-Replay: true header. Nothing runs again.
while the first request is still running409 idempotency_in_progress with a Retry-After header (seconds). Wait, then retry with the same key.
with a different body422 idempotency_key_reused. A key belongs to one request; use a new key for a new request.
on a different endpoint409 idempotency_conflict
more than 24 hours after its last useTreated as a new key: the request runs.

Which outcomes are replayed:

  • 2xx and 4xx are stored and replayed for 24 hours, whether the request succeeded or was rejected (for example a 400 invalid_body or a 404 on one item in a batch). Fix the request and send it with a new key.
  • 5xx and 429 are not stored. Retry with the same key and the request runs again.
  • A few retryable conflicts are not stored either, such as the 409 notes_conflict / notes_busy on the notes endpoint.

Body comparison ignores key order and whitespace in the JSON.

Secrets are never stored in the replay cache. A replayed API-key creation returns key: null, and a replayed share-link creation returns pin: null; fetch a PIN with GET /api/v2/creators/{id}/share-link?include_pin=true and a write-scope key.

bash
curl -X POST \
  -H "Authorization: Bearer tga_<key>" \
  -H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000" \
  -H "Content-Type: application/json" \
  -d '{"accounts": [{"platform": "tiktok", "handle": "charlidamelio"}]}' \
  "https://www.trackagoat.com/api/v2/projects/<id>/creators"

API versioning#

The current version is v2. All endpoints live under /api/v2/.

v1 has been removed. Every /api/v1/* path now returns 410 Gone with a pointer to its successor:

JSON
{
  "data": null,
  "error": "API v1 has been removed. Use /api/v2 (see /docs/api-reference/overview).",
  "meta": { "code": "api_version_removed", "successor": "/api/v2" }
}

The response also carries a Link: </api/v2>; rel="successor-version" header. If you are migrating from v1, the biggest change is the accounts model: a creator no longer has a tiktok_handle. It carries an accounts[] array, and you create creators with a list of accounts.

Available endpoints#

For the full machine-readable spec, download /api/v2/openapi.json.

Creators#

MethodPathScopeDescription
GET/api/v2/creatorsreadList creators (accounts embedded)
POST/api/v2/creatorswriteCreate a creator with one or more accounts
POST/api/v2/projects/{id}/creatorswriteAdd creator(s) to a project; bulk up to 50
GET/api/v2/creators/{id}readGet a creator
PATCH/api/v2/creators/{id}writeUpdate creator-level fields
DELETE/api/v2/creators/{id}writeSoft-delete creator
POST/api/v2/creators/{id}/scrapewriteTrigger manual scrape (primary account, or one via ?account_id=)

Accounts#

MethodPathScopeDescription
GET/api/v2/accountsreadList accounts
GET/api/v2/creators/{id}/accountsreadList a creator's accounts
POST/api/v2/creators/{id}/accountswriteAdd an account to a creator
GET/api/v2/accounts/{id}readGet an account
PATCH/api/v2/accounts/{id}writeRename handle / change tracking config
DELETE/api/v2/accounts/{id}writeSoft-delete account
POST/api/v2/accounts/{id}/scrapewriteTrigger a scrape for a single account
GET/api/v2/accounts/{id}/statsreadFollower/stat snapshot history

Videos#

MethodPathScopeDescription
GET/api/v2/videosreadList videos (filter by platform / account / content group)
POST/api/v2/projects/{id}/videoswriteAdd video(s) by URL; bulk up to 50
PATCH/api/v2/videos/{id}writeUpdate title, readme, tracking_status
DELETE/api/v2/videos/{id}writeRemove video from tracking (sets tracking_status: excluded; the row is kept)
POST/api/v2/videos/{id}/scrapewriteRefresh this video's stats
POST/api/v2/videos/{id}/tracking-disablewriteDisable tracking
POST/api/v2/videos/{id}/tracking-enablewriteRe-enable tracking
POST/api/v2/videos/{id}/tracking-unexemptwriteRemove exemption flag

Content Groups#

MethodPathScopeDescription
GET/api/v2/content-groupsreadList content groups
POST/api/v2/content-groupswriteCreate a content group
GET/api/v2/content-groups/{id}readGet a content group
PATCH/api/v2/content-groups/{id}writeRename / edit notes / add or remove members
DELETE/api/v2/content-groups/{id}writeDelete a content group
GET/api/v2/content-groups/{id}/statsreadCombined stats across the group

Campaigns, Projects, Goals#

MethodPathScopeDescription
GET/api/v2/campaignsreadList campaigns
POST/api/v2/projects/{id}/campaignswriteCreate campaign
PATCH/api/v2/campaigns/{id}writeUpdate campaign
DELETE/api/v2/campaigns/{id}writeDelete campaign
POST/api/v2/campaigns/{id}/itemswriteAdd item to campaign
DELETE/api/v2/campaigns/{id}/itemswriteRemove item from campaign
GET/api/v2/projectsreadList projects
POST/api/v2/organizations/{id}/projectsadminCreate project
PATCH/api/v2/organizations/{id}/projects/{pid}adminUpdate project
PATCH/api/v2/projects/{id}/inboxwriteApprove/exclude inbox videos
POST/api/v2/creators/{id}/goalswriteCreate goal (platform-scoped)
PATCH/api/v2/creators/{id}/goals/{gid}writeUpdate goal
DELETE/api/v2/creators/{id}/goals/{gid}writeDelete goal

Organizations, Members, Invitations, API Keys#

MethodPathScopeDescription
POST/api/v2/user/organizationsadminCreate organization
POST/api/v2/organizations/{id}/membersadminAdd member
PATCH/api/v2/organizations/{id}/members/{uid}adminChange member role
DELETE/api/v2/organizations/{id}/members/{uid}adminRemove member
POST/api/v2/organizations/{id}/invitationsadminSend invitation
DELETE/api/v2/organizations/{id}/invitations/{iid}adminRevoke invitation
POST/api/v2/organizations/{id}/api-keysadminCreate API key (only with scopes the calling key holds)
DELETE/api/v2/organizations/{id}/api-keys/{kid}adminRevoke API key

Payouts#

MethodPathScopeDescription
GET/POST/api/v2/payout-structuresread/writeList / create payout structures
GET/PATCH/DELETE/api/v2/payout-structures/{id}read/writeRead / update / delete structure
GET/POST/DELETE/api/v2/payout-structures/{id}/assignmentsread/writeManage creator assignments
GET/POST/api/v2/payout-methodsread/writeList / create payout methods
GET/PATCH/DELETE/api/v2/payout-methods/{id}read/writeRead / update / delete method
GET/POST/api/v2/payout-paymentsread/writeList / create payments
GET/PATCH/api/v2/payout-payments/{id}read/writeRead / update payment
GET/PATCH/api/v2/payout-accruals/{id}read/writeRead / update accrual
GET/POST/api/v2/projects/{projectId}/conversion-eventsread/writeList / create conversion event types
GET/PATCH/DELETE/api/v2/projects/{projectId}/conversion-events/{id}read/writeRead / update / deactivate an event type (?mode=hard needs admin)
GET/POST/api/v2/projects/{projectId}/conversionsread/writeList / record conversions (single or batch up to 500)
GET/DELETE/api/v2/projects/{projectId}/conversions/{id}read/writeRead / void a conversion (?mode=hard needs admin)
POST/api/v2/payouts/payment-receipts/upload-urlwriteGet signed receipt upload URL

Analytics#

MethodPathScopeDescription
GET/api/v2/analyticsreadUnified analytics (time-series + aggregates)
GET/api/v2/schemareadMachine-readable data model

Notes and documents#

MethodPathScopeDescription
GET/api/v2/notesreadEvery document with text in the org, with previews (filter by type, project or text)
GET/api/v2/notes/{entity_type}/{id}readOne document in full, with its readme_version
POST/api/v2/notes/{entity_type}/{id}writeAppend to or replace a document (organization, project and payout documents need an org admin)
GET/api/v2/mereadWho the key acts as, and their personalization document
PATCH/api/v2/mewriteReplace that person's personalization document
GET/api/v2/membersreadThe org's members and whether each has a personalization document

See Notes and documents API.

CSV exports#

MethodPathScopeDescription
GET/api/v2/exports/{dataset}readThe same CSV as the app's Export buttons: creators, videos, campaigns, goals, campaign leaderboard, payouts tracker, payments, accruals or analytics

See CSV exports.

Changelog#

MethodPathScopeDescription
GET/api/v2/changelognone (public)trackagoat's changelog, newest first; filter by since and q