Authentication & Keys
Every Reporting API request is authenticated with a client API key. Keys are managed from the API page in your dashboard.
Passing the key
Send the key in a request header — never in the query string, where it would leak into logs and browser history. Either header is accepted:
X-Api-Key: axk_live_xxxxxxxxxxxxxxxx
Authorization: Bearer axk_live_xxxxxxxxxxxxxxxx
A request with no key, or an invalid/expired/revoked key, returns 401 Unauthorized.
How keys work
- Shown once. The raw key is returned a single time, at creation. AppLixir stores only a SHA-256 hash — we can't show it to you again, so copy it immediately. If you lose it, revoke it and create a new one.
- Multiple per account. Create a separate key per integration (BI pipeline, finance export, partner feed) so you can revoke one without disrupting the others.
- No automatic expiry. Self-serve keys don't expire on their own — rotate them by creating a new key and revoking the old one. (Need a key with a fixed expiry date? Ask support@applixir.com to provision one.)
- Revocable. Revoke a key anytime from the dashboard — it stops working immediately.
- Resolves to your account. A key acts on behalf of the account that owns it and only ever sees that account's data.
Key scope: account-level vs. site-scoped
When you create a key you can optionally restrict it to a subset of your sites.
| Scope | Behavior |
|---|---|
| Account-level (no sites selected) | Can read every site on the account. |
| Site-scoped (one or more sites selected) | Can only read the listed sites. A request for a siteId outside the allow-list returns 403 Forbidden. |
A site is identified by its siteId — get the list from GET /api/v1/sites.
/reports/countries feed needs an account-level keyGET /api/v1/reports/countries does not yet support per-site filtering, so a site-scoped key is rejected (403) on that endpoint. Use an account-level key for it, or use /reports/by-country for filterable country data.
Rate limits
Each key is limited to 120 requests per minute (fixed window). Every response includes:
| Header | Meaning |
|---|---|
X-RateLimit-Limit | The ceiling (120) |
X-RateLimit-Remaining | Requests left in the current window |
Exceeding the limit returns 429 Too Many Requests with a Retry-After header (seconds to wait). Back off and retry after that interval.
Error responses
| Status | Meaning |
|---|---|
200 OK | Success |
401 Unauthorized | Missing, invalid, expired, or revoked key |
403 Forbidden | Key is not allowed to read a requested site (or a site-scoped key hit /reports/countries) |
400 Bad Request | Invalid parameter (e.g. an unknown sortBy column or malformed filter) |
429 Too Many Requests | Rate limit exceeded — see Retry-After |
Migrating from the legacy query-param feed
The older feed GET /api/v1/revenues/countries?apiKey=<key> still works but is deprecated. It now returns RFC 8594 deprecation headers:
Deprecation: true
Link: </api/v1/reports/countries>; rel="successor-version"
To migrate, switch to GET /api/v1/reports/countries and move your key from the ?apiKey= query parameter into the X-Api-Key header. The response shape is identical, so no parsing changes are needed.