atrixANALYTICS
REST API

API overview

Tokens, scopes, errors, rate limits, dry runs and idempotency for the Atrix REST API.

Atrix has three HTTP surfaces:

SurfaceBase URLAuthFor
Control planehttps://app.analytics.atrix.dev/v1Bearer tokenProjects, keys, flags, experiments, integrations, region tokens
Region APIhttps://eu.api.analytics.atrix.devRegion token (short-lived JWT)Queries, SQL, persons, replays, Ask. See Region API.
Ingesthttps://eu.i.analytics.atrix.devPublic project keyEvents, replay, flags, revenue webhooks. See Capture API.

The control plane's OpenAPI document is served at app.analytics.atrix.dev/openapi.json, and a snapshot of it renders the reference.

Tokens

Create a personal access token in the console under Settings → Tokens. Tokens cannot create tokens.

  • Pick the scopes and, optionally, the projects (up to 100) and an expiry (1–365 days; none means it never expires).
  • You can only grant scopes your role already holds, and scopes are re-checked against your role on every call: if your role is reduced, your tokens lose reach immediately.
  • The secret is shown once. Only a SHA-256 hash is stored.
curl https://app.analytics.atrix.dev/v1/me -H "Authorization: Bearer atx_pat_…"

GET /v1/me returns the token, its user and its effective scopes. OAuth access tokens (atx_oat_…) from the MCP flow work on /v1 too.

Scopes

Scopes only ever narrow. There is no wildcard, and unknown scopes are rejected.

Domains, each with :read and :write (write implies read): projects, org, query, insights, dashboards, cohorts, catalog, flags, experiments, replays, persons, alerts, ai, annotations, usage.

Named scopes are never implied by anything else, and must be granted explicitly:

ScopeAllows
flags.productionMaking a production flag configuration live
experiments.shipShipping an experiment's winning variant
sql.rawRunning SQL against your data
persons.piiSeeing personal-data properties unmasked
persons.eraseErasure requests (admins and owners)
exportParquet exports to your bucket
billing.writePlan changes and the spend cap
members.writeInviting and removing members

Roles map to scopes: viewer has every read; member has read and write on everything except projects and the organisation, plus export and sql.raw; admin has everything except billing.write; owner has everything.

Errors

Errors have one shape:

{ "error": { "code": "missing_scope", "message": "requires scope `projects:write`" } }

Codes: validation, unauthorized, invalid_credentials, missing_scope, scope_not_held, not_found, rate_limited, unavailable, internal. A 401 carries WWW-Authenticate: Bearer realm="atrix-analytics".

Another tenant's resource is always 404, never 403, so ids cannot be probed. A 403 means you are in the right organisation but your role or token lacks a scope. A malformed id is also a 404.

Rate limits

Per token: 240 calls and 30 writes per minute. Dry runs do not count as writes. Over the limit you get 429 rate_limited with Retry-After. Request bodies are limited to 64 KB, and requests time out after 30 seconds.

Dry runs

Every /v1 write that changes something important accepts ?dry_run=true: the request is validated and the response describes what would happen, with status 200, and nothing changes.

curl -X POST "https://app.analytics.atrix.dev/v1/orgs/$ORG_ID/projects?dry_run=true" \
  -H "Authorization: Bearer $ATRIX_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{ "name": "Acme mobile", "region": "eu" }'

Idempotency

Send Idempotency-Key (1–255 visible ASCII characters) on POST, PATCH, PUT or DELETE to make a retry safe. Non-5xx responses are kept for 24 hours and replayed with Idempotent-Replayed: true. The same key with a different request answers 422 idempotency_key_reused; a key whose first request is still running answers 409 idempotency_in_progress.

What is on /v1

AreaRoutes
IdentityGET /v1/me
OrganisationsGET /v1/orgs, GET /v1/orgs/{org_id}
ProjectsGET, POST /v1/orgs/{org_id}/projects; GET /v1/projects; GET, PATCH, DELETE /v1/projects/{project_id}; GET …/environments
KeysGET …/keys; POST …/keys/{key_id}/rotate; POST …/keys/{key_id}/revoke
RegionPOST …/region-token; POST …/query
Revenue integrationsGET, POST …/integrations; GET, PATCH, DELETE …/integrations/{id}; POST …/integrations/{id}/rotate-token
Tracking planGET …/catalog/codegen
ErasureGET, POST …/erasure-requests; GET …/erasure-requests/{id}; GET …/erasure-requests/{id}/certificate; public POST /v1/erasure-certificates/verify and GET /v1/erasure-certificates/keys. See Erasure.
FlagsGET, POST …/flags; GET, PATCH, DELETE …/flags/{flag_id}; PATCH …/flags/{flag_id}/environments/{environment}; GET …/flags/publications
ExperimentsGET, POST …/experiments; GET, PATCH, DELETE …/experiments/{id}; POST …/{id}/launch, …/stop, …/ship; GET …/{id}/results; POST …/experiments/plan

… is /v1/projects/{project_id}. The flags and experiments routes on /v1 take the same bodies as their console equivalents under /app/projects/{project_id}/…, which are the ones listed in the console reference; the flags, experiments and erasure routes are not yet in the OpenAPI document. Insights, dashboards, cohorts and annotations are console-only today.

On this page