
HTTP status codes, error response format, rate limits, and limit-reached responses.
All errors use the same envelope shape:
{
"data": null,
"error": "Human-readable error message",
"meta": { /* optional error detail */ }
}| Status | Meaning |
|---|---|
400 | Bad request: invalid query parameters or request body (meta.code: invalid_query, invalid_body, invalid_params) |
401 | Unauthorized: missing, invalid, or expired API key (meta.code: invalid_api_key) |
402 | Limit reached: org has hit a count-based plan limit (meta.code: limit_reached), or a date range exceeds tier history retention (retention_exceeded) |
403 | Forbidden: key lacks the required scope (meta.code: insufficient_scope), or the org/user is banned |
404 | Not found: resource doesn't exist or isn't in your org |
409 | Conflict: idempotency key reused on a different route, duplicate, or a state conflict |
410 | Gone: removed endpoint (e.g. /creators/{id}/stats, /campaigns/{id}/stats) |
429 | Rate limited: daily API quota or per-key sliding-window exceeded (meta.code: rate_limit_exceeded) |
500 | Server error (meta.code: internal_error) |
Returned when a write operation would exceed a count-based plan limit. The meta field contains details:
{
"data": null,
"error": "Limit reached: max_creators_per_org",
"meta": {
"code": "limit_reached",
"limitKey": "max_creators_per_org",
"current": 5,
"max": 5
}
}See Limits & plan tiers for all limit keys.
Returned when a write request (POST/PATCH/DELETE) is made with a key that lacks the write scope, or an admin endpoint is called without the admin scope.
{
"data": null,
"error": "This action requires the 'write' scope. Granted: [read]",
"meta": {
"code": "insufficient_scope",
"required": "write",
"granted": ["read"]
}
}See Authentication for the scope model.
Two separate systems can produce 429s, and both use meta.code: "rate_limit_exceeded".
Per-key sliding window: more than 60 requests per minute from a single API key. The response carries a Retry-After header (seconds). Retry after a brief delay.
{
"data": null,
"error": "Rate limit exceeded",
"meta": {
"code": "rate_limit_exceeded",
"bucket": "v1Api",
"retryAfter": 7
}
}Daily quota: your org's daily api_requests allowance was exhausted. Resets at UTC midnight.
{
"data": null,
"error": "Daily API request limit exceeded",
"meta": {
"code": "rate_limit_exceeded"
}
}Always check meta
The meta field on error responses contains structured detail: use meta.code for programmatic error handling rather than parsing the error string.
const res = await fetch('https://www.trackagoat.com/api/v1/creators', {
headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();
if (!res.ok) {
if (res.status === 429) {
const retryAfter = body.meta?.retryAfter ?? 60;
// wait retryAfter seconds and retry
}