Pixel API errors and retries
When a request fails, the HTTP status tells you the kind of problem and error.code gives you a stable string to branch on. Fix and resend 4xx errors; retry 429 and most 5xx errors after a pause.
Stable error codes · Retry rules · Troubleshooting
What an error looks like
Errors from an endpoint use this envelope:
{
"status": "error",
"error": {
"code": "website_id_required",
"message": "website_id is required for this endpoint"
},
"meta": { "request_id": "req_9c41e7b2-3f58-4a6d-b1e0-5d7c2a8f4b96" }
}
error.details is added when there's more to say — for example the field problems on invalid_body, or the supported filters on unsupported_filter. Two other shapes exist:
- Key, permission and rate-limit errors are returned before the request reaches an endpoint, so the body is only the
errorobject — nostatusand nometa. - A request body that isn't valid JSON is rejected with
400and a singlemessagefield, before any endpoint runs.
Branch on the HTTP status and error.code. Don't parse message — it's written for people and can change.
Error codes
Keys and permissions
| HTTP | Code | Meaning | Fix |
|---|---|---|---|
| 401 | not_authenticated | No Authorization header on a Pixel API endpoint. | Add Authorization: Bearer wk_…. |
| 401 | missing_authorization | No Authorization header on GET /me. | Add the header. |
| 401 | invalid_authorization_format | The header isn't Bearer, one space, then the key. | Fix the header format. |
| 401 | invalid_api_key | The key isn't recognised — usually a typo or a truncated paste. | Copy the key again, or create a new one. |
| 401 | api_key_revoked | The key was revoked. | Create a new key. |
| 401 | api_key_expired | The key is past its expiry date. Keys created in Settings don't expire, so you shouldn't see this. | Create a new key. |
| 403 | insufficient_scope | The key lacks the scope this endpoint needs. details.required names it; details.available lists the key's scopes. | Create a key with that scope ticked and switch to it. |
Rate limit
| HTTP | Code | Meaning | Fix |
|---|---|---|---|
| 429 | rate_limit_exceeded | Your workspace has used its 60 requests for the current minute. | Wait Retry-After seconds, then retry. See Rate limits. |
Problems with the request
| HTTP | Code | Meaning | Fix |
|---|---|---|---|
| 400 | website_id_required | A report, visitor-history or goal-metadata call has no website_id. | Add your admx_ website ID. |
| 403 | forbidden | The website_id isn't one of your workspace's websites — usually a typo, or an ID from another workspace. | Copy websiteId from GET /pixel/websites. |
| 400 | from_date_and_to_date_required | This report needs both from_date and to_date. | Send both as YYYY-MM-DD. |
| 400 | unsupported_filter | A filter the API can't apply, such as region. details.filter names it and details.supported lists the filters that work. | Use a supported filter — see Endpoints. |
| 400 | invalid_metric | The time-series metric isn't one of the supported values. | Use a metric listed on the endpoints page. |
| 400 | invalid_pipe | GET /pixel/metrics/{report} was given an unknown report name. | Use one of the named analytics endpoints. |
| 400 | invalid_body | A write body failed validation. details.fieldErrors lists each bad field; details.formErrors covers the body as a whole. | Fix the listed fields and resend. |
| 400 | invalid_visitor, invalid_goal, invalid_id | The visitor ID, goal name or segment ID in the path is blank. | Fill in the path segment. |
| 400 | invalid_website | GET /pixel/segments was called without website_id. | Add the website's id. |
| 400 | empty_patch | A segment update had neither name nor filters. | Send at least one of them. |
| 404 | not_found | The segment doesn't exist in your workspace — or, when creating one, the website doesn't. | Check the ID. |
| 409 | duplicate_name | That website already has a segment with this name. | Choose another name. |
Any other 400 code names the specific parameter that's missing or invalid.
Problems on our side
| HTTP | Code | Meaning | Fix |
|---|---|---|---|
| 503 | upstream_unavailable | Reports are temporarily unavailable. | Retry with backoff. The exception is /pixel/analytics/regions and /pixel/analytics/cities, which always return this because location is recorded at country level — don't retry those. |
| 500 | analytics_error | A report failed unexpectedly. | Retry with backoff. |
| 500 | internal_error | Something failed on our side, including while checking your key. | Retry with backoff, and contact support if it keeps happening. |
Which errors to retry
- Don't retry
400,401,403,404or409. The request has to change first. 429: wait the number of seconds inRetry-After, then retry.500and503: retry with exponential backoff — for example after 1, 2, 4, 8 and 16 seconds — then stop and alert someone. Skip the region and city endpoints; their503is permanent.- Retry writes with care. Payments are de-duplicated on
transaction_id, so re-sending one is safe. Goals, events and identify calls aren't de-duplicated: if a request timed out after it reached Admaxxer, a retry can record it twice.
Common problems
- Every request returns
401. Check the header is exactlyAuthorization: Bearer wk_…, that the key wasn't truncated when you pasted it, and that it hasn't been revoked.GET /meis the quickest test. 403 insufficient_scopeon a write. The key is read-only. Create one with Write analytics ticked in Settings › API Keys.403 forbiddenon a report. Thewebsite_idis mistyped or belongs to another workspace. Use thewebsiteIdfromGET /pixel/websites.- A report comes back empty. The site had no tracked traffic in that range, the range starts before your plan's data retention (it then begins at the earliest day kept), or a filter matched nothing — filter values are case-sensitive.
- A server-side record never shows up. Write calls don't check
website_id, so a mistyped ID is accepted and lands where no report looks. Compare it withGET /pixel/websites. GET /pixel/segmentsfails. Segment calls take the website'sid(a UUID), not itsadmx_website ID.
Contacting support
Email support@admaxxer.com with the method and endpoint, the time of the request in UTC, the HTTP status, the error.code, and the meta.request_id if the response had one. Never send your API key.
Frequently asked questions
Q: Why don't some errors include a request_id?
Key, permission and rate-limit errors are returned before the request reaches an endpoint, and so is the 400 for a body that isn't valid JSON. Those responses don't include meta.
Q: Should I branch on the error message?
No. Use the HTTP status and error.code. Messages are written for people and can change.
Q: Which 5xx errors are safe to retry?
500 and 503, with exponential backoff — except the region and city breakdowns, which always return 503. Remember that retrying a goal, event or identify call can record it twice if the first attempt got through.
Q: What's in details on an invalid_body error?
fieldErrors maps each field to the problems found with it, and formErrors lists problems with the body as a whole — for example a missing website_id appears under fieldErrors.website_id.
Related guides
- Pixel API overview — Base URL, first request and response format.
- Authentication — Fix 401 and 403 errors at the source.
- Rate limits — What triggers a 429 and how to avoid it.
- Endpoints — Parameters each endpoint expects.
- API keys guide — Step-by-step walkthrough of Settings › API Keys.
- Developer reference — The wider developer documentation for Admaxxer.