Skip to content

Responses & Errors

Response Envelope

Responses use one of three shapes depending on the endpoint:

ShapeEndpoints
Bare objectGET /me
{ "data": { … } }Single-resource endpoints (/projects/{id}, /countries/{id}, etc.)
{ "data": [ … ] }Collection endpoints (/projects, /reports, /keywords, etc.)

Paginated collections also include meta and links blocks (see Pagination below).

Cached endpoints include a cache_refreshed_at ISO 8601 timestamp at the top level alongside data. Non-cached endpoints do not include this field.


Errors

All errors follow the same envelope regardless of the HTTP status code:

json
{
  "error": {
    "code": "not_found",
    "message": "The requested resource was not found."
  }
}
HTTP statuscodeWhen
400bad_requestUnknown query parameter, out-of-range value, or malformed input
401unauthenticatedMissing or invalid Bearer token
403forbiddenToken is valid but cannot access this resource (wrong agency, IP not whitelisted, or insufficient scope)
404not_foundResource does not exist
405method_not_allowedWrong HTTP method used
422validation_errorInput failed validation; message names the first failing field
429rate_limit_exceededPer-minute or per-hour limit exceeded
500server_errorUnexpected server error - no internal details are exposed

Examples:

json
// 400 - unknown query parameter
{ "error": { "code": "bad_request", "message": "Unknown query parameter(s): statuss. Allowed: status, search, agency_id, page, per_page." } }

// 400 - out-of-range report number
{ "error": { "code": "bad_request", "message": "report_number must be between 1 and 26." } }

// 403 - project belongs to a different agency
{ "error": { "code": "forbidden", "message": "You do not have permission to access this resource." } }

// 403 - request from non-whitelisted IP
{ "error": { "code": "forbidden", "message": "Your IP address is not allowed to use this API key." } }

Pagination

Only GET /projects is paginated. All other list endpoints return the full set of results.

Add ?page=N to fetch subsequent pages (default: page 1, 100 results per page).

sh
curl -H "Authorization: Bearer YOUR_API_TOKEN" \
  "https://admin.trakk.ai/api/v1/projects?page=2"

Paginated responses include meta and links alongside data:

json
{
  "data": [ "…" ],
  "meta": {
    "current_page": 2,
    "from": 101,
    "to": 200,
    "per_page": 100,
    "total": 247,
    "last_page": 3
  },
  "links": {
    "first": "/api/v1/projects?page=1",
    "prev":  "/api/v1/projects?page=1",
    "next":  "/api/v1/projects?page=3",
    "last":  "/api/v1/projects?page=3"
  },
  "cache_refreshed_at": "2026-03-30T12:00:00.000000Z"
}

Out-of-range pages return an empty data array, not an error.


Caching

The following endpoints cache their responses server-side (TTL: 1 hour):

EndpointCached
GET /projectsYes
GET /projects/{project}Yes
GET /projects/{project}/reportsYes
GET /projects/{project}/reports/latestYes
GET /projects/{project}/reports/{report_number}/contentYes
GET /projects/{project}/keywordsYes
GET /me, /countries, /languages, /usersNo

Cached responses include cache_refreshed_at (ISO 8601) at the top level. The cache is invalidated automatically when project data, keywords, or report content changes - stale data is not served after a write.