Skip to content

Authentication and API keys

Create an API key, choose its scopes and authenticate with a Bearer token. Covers revocation, limits and testing safely.

Updated Oct 10, 2026 · 6 min read

Every v2 API request needs an API key. Create one in the app, send it as a Bearer token, and give it only the scopes it needs. Every plan includes API access. Free and Starter allow 1 key each, Ultra allows 5. Free allows 200 requests a day, Starter 1,000 and Ultra 50,000.

Keys are:

  • Org-scoped: a key can only reach data in the org it was created in.
  • Shown once: the plaintext key is displayed at creation and can't be recovered.
  • Hashed at rest: trackagoat stores only a SHA-256 hash of the key, never the plaintext.
  • Acting as one member: a key acts on behalf of the person who created it, or of the member an org admin picked under Acts as. Every call is attributed to that member and can never do more than they can in the app. If they leave or are removed from the org, the key stops working. If they stop being an org admin, the key loses the admin scope and admin-only actions.

Creating an API key#

  1. Open org settings

    Go to Org settings → API keys (org admins only).

  2. Click + New API key

    Give the key a descriptive name, such as Claude MCP access or Analytics script, choose who it acts as (you, by default, or any member of the org) and choose its scopes.

  3. Copy your key immediately

    After you click Create, the full key (tga_<64 hex chars>) is shown once. Copy it now.

Using the key#

Include the key as a Bearer token on every request:

bash
Authorization: Bearer tga_<your-key>

Example:

bash
curl -H "Authorization: Bearer tga_abc123" \
  https://www.trackagoat.com/api/v2/projects

The one endpoint that needs no key is GET /api/v2/changelog: the changelog is public.

Key format#

tga_<64 lowercase hex characters>

Example: tga_a1b2c3d4e5f6... (64 hex chars after the prefix).

Org scoping#

Keys are org-scoped: all data returned is limited to the organization the key belongs to. A key can only read and write data inside its own org.

Scoping stops at the org boundary; it does not go down to the project level. A key grants access to every project in its org, including ones created after the key was issued. There is no way to issue a key that is limited to a single project.

Testing against the API#

Because keys are org-wide, do not run integration tests with a key from an org that holds real data: a test POST or DELETE will hit production records.

Create a separate organization for testing and use a key from that org. It gives you complete isolation: separate creators, campaigns, conversions, and analytics, with no path back to your live org. Ask support to disable scraping on it, which also guarantees test conversions can never generate payout accruals.

This is how you get a sandbox on trackagoat: there is no separate sandbox host or test-mode key prefix. The base URL and key format are the same; the org is what separates test from live.

Permission scopes#

Each key carries one or more permission scopes, chosen at creation time. The scope controls which HTTP methods the key may use:

ScopeGrants
readAll GET endpoints
writeAll POST, PATCH, and DELETE endpoints (in addition to reads if read is also granted)
adminOrg administration: projects, members, invitations, API keys and creating organizations; also entrance-PIN reads and hard deletes. Platform-admin endpoints under /api/v2/admin/* additionally need the owner to be a platform admin

New keys default to ['read', 'write'] unless you narrow the scopes at creation.

Who a key acts as#

A key acts on behalf of one member of the org. By default that is the org admin who created it. An admin can instead pick another member under Acts as, for example for a script that a teammate runs. Every request is attributed to that member: change logs, notes signatures, the audit log and GET /api/v2/me all show them. The keys list shows each key as "Acts as name · created by admin".

The key can never do more than that member can do in the app. Its scopes are a ceiling rather than a grant, and every request is checked against the member's current role in the org:

  • Member is an org admin: the key gets all of its scopes.
  • Member is not an org admin (for example, demoted after the key was created): admin is dropped, and everything only org admins can do or see in the app returns 403 insufficient_role: payments and payout setup, a creator's payout account, removing or re-enabling creators, removing accounts or videos, stopping video tracking, manual scrapes, share pages, comment settings, and organization and project documents. Everything else that read and write allow still works. The OpenAPI spec marks each of these endpoints "Requires an org admin".
  • Member left or was removed from the org: the key is rejected with 401 key_member_removed. Removing a member also deactivates the keys that act as them.
  • The key was made for someone else, and the admin who created it lost access: the admin has seen the key, so it only works while they are still an org admin of this org. If they leave or are removed, the key is rejected with 401 key_creator_removed; if they are changed to member, 401 key_creator_not_admin; if their account is suspended, 401 key_creator_banned. Removing, demoting or suspending that person also deactivates those keys. Keys a person created for themselves keep working after they are changed to member, limited to what a member can do.

Deactivated keys stay in Org settings → API keys with the reason: revoked, the member it acts as left or was suspended, the admin who created it left, was changed to member or was suspended, or the organization was suspended. To keep a script running after its key's creator loses access, an org admin creates a new key for it.

Creating keys over the API#

POST /api/v2/organizations/{orgId}/api-keys needs the admin scope, and a key can only create keys whose scopes it holds itself. Asking for a scope the calling key lacks returns 403 insufficient_scope with meta.required listing the missing scopes. Pass acts_as_user_id to create a key that acts as another member; it must be a current member of the org (400 acts_as_not_member otherwise), and the admin scope needs that member to be an org admin. The response includes acts_as and created_by.

A write request made with a read-only key is rejected with 403 and meta.code = "insufficient_scope":

JSON
{
  "data": null,
  "error": "This action requires the 'write' scope. Granted: [read]",
  "meta": { "code": "insufficient_scope", "required": "write", "granted": ["read"] }
}

This applies to every mutating endpoint, including all payout writes (payout-methods, payout-structures, payout-payments, payout-accruals, their [id] sub-routes, and annotation writes).

Errors#

Statusmeta.codeCause
401invalid_api_keyMissing, malformed, invalid, revoked or expired key
401key_member_removedThe member the key acts as is no longer in the org
401key_creator_removedThe key was made for someone else, and the admin who created it is no longer in the org
401key_creator_not_adminThe key was made for someone else, and the admin who created it is no longer an org admin
401key_creator_bannedThe key was made for someone else, and the account that created it is suspended
403insufficient_scopeKey is valid but lacks the scope required for this endpoint (or admin was dropped because its member is no longer an org admin)
403insufficient_roleOnly org admins can do this in the app, and the key acts as a member who isn't one
403NoneKey is valid but the org or user is banned
429rate_limit_exceededPer-key sliding-window (60 req/min) or daily quota exceeded
JSON
{
  "data": null,
  "error": "Invalid or expired API key",
  "meta": { "code": "invalid_api_key" }
}

Revoking a key#

Go to Org settings → API keys and revoke the key. Revocation is immediate: requests with that key get 401 invalid_api_key. The key stays in the list, marked Revoked.

Removing a member from the org (or a member leaving) deactivates every key that acts as them and every key they created in that org. Changing an admin to member deactivates the keys they created for someone else. For integrations, have an admin who will stay in the org create the key, acting as a member who will stay too.

Limits#

  • Number of keys: your plan sets max_api_keys_per_org. Delete unused keys if you reach it.
  • Rate limit: 60 requests a minute per key (sliding window).
  • Daily quota: max_api_requests_per_day per org, set by your plan.

See Plans and limits for current values and Errors and limits for the 402 and 429 responses.