
How to authenticate with the trackagoat v1 API using API key Bearer tokens.
All v1 API requests require an API key. Keys are scoped to the organization of the user who created them.
Generate a key in the app: Org settings → API keys → + New API key.
One-time reveal
The full key (tga_<64 hex chars>) is shown once at creation. Copy it immediately: trackagoat stores only a hash and cannot recover the plaintext.
See API keys guide for step-by-step instructions.
Include the key as a Bearer token on every request:
Authorization: Bearer tga_<your-key>Example:
curl -H "Authorization: Bearer tga_abc123" \
https://www.trackagoat.com/api/v1/projectstga_<64 lowercase hex characters>Example: tga_a1b2c3d4e5f6... (64 hex chars after the prefix).
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.
Each key carries one or more permission scopes, chosen at creation time. The scope controls which HTTP methods the key may use:
| Scope | Grants |
|---|---|
read | All GET endpoints |
write | All POST, PATCH, and DELETE endpoints (in addition to reads if read is also granted) |
admin | Platform-admin-only endpoints under /api/v1/admin/* (the key owner must also be a platform admin) |
New keys default to ['read', 'write'] unless you narrow the scopes at creation.
A write request made with a read-only key is rejected with 403 and meta.code = "insufficient_scope":
{
"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).
| Status | meta.code | Cause |
|---|---|---|
401 | invalid_api_key | Missing, malformed, invalid, or expired Authorization header / key |
403 | insufficient_scope | Key is valid but lacks the scope required for this method |
403 | : | Key is valid but the org or user is banned |
429 | rate_limit_exceeded | Per-key sliding-window (60 req/min) or daily quota exceeded |
{
"data": null,
"error": "Invalid or expired API key",
"meta": { "code": "invalid_api_key" }
}