Guide
Errors & limits
Every response has the same shape, every error carries a stable machine-readable code, and limits are reported in headers — so your integration can react without parsing messages.
Response format
Successful responses wrap the result in data. Lists add meta with paging details.
{
"data": [
{
"id": "6650a4c2e1b3d5f7a9c1e301",
"name": "Acme Retail"
}
],
"meta": {
"page": 1,
"limit": 25,
"total": 2
}
}
Errors return a non-2xx status and an error object. Branch on code; message is for people and may change. Some errors add fields, such as maxProjects or retryAfter.
{
"error": {
"code": "max-projects",
"message": "Plan allows at most 3 project(s)",
"maxProjects": 3
}
}
Errors any request can return
These come from the key, the plan or the account, before an endpoint runs.
| Status | error.code | Meaning |
|---|---|---|
| 401 | api-key-missing | No Authorization: Bearer <key> header was sent. |
| 401 | api-key-invalid | The key is not a valid Tracker API key, or its owner is no longer a customer account. |
| 401 | api-key-revoked | The key was revoked — by you, or automatically when the account password changed. |
| 401 | api-key-expired | The key passed its expiry date. Create a new one. |
| 403 | plan-required | Your plan does not include API access. |
| 403 | api-key-over-plan-limit | You have more active keys than your plan allows; only the newest ones work. |
| 403 | insufficient-scope | A read-only key called an endpoint that changes data. |
| 402 / 403 | payment-required / forbidden | The account is locked (billing hold returns 402) or closed; error.accountStatus says which. |
| 429 | rate-limited | Too many requests for your plan, or too many invalid-key attempts from your IP. Wait for Retry-After seconds. |
All error codes
Each endpoint page lists the codes it can return. A few codes depend on your role in the project: flag-… means your membership is missing that permission (see project permissions).
| Status | error.code | Meaning |
|---|---|---|
| 400 | invalid-request | A parameter or body field is missing or invalid; error.message says which. |
| 404 | not-found | The resource does not exist or you cannot open it. Tracker does not reveal which. |
| 409 | conflict | You already have a project for that domain. |
| 400 | too-many-urls | More than 200 URLs in one request. Split them into batches. |
| 400 | invalid-url | The webhook URL is not HTTPS, contains credentials, or points at a private address. |
| 403 | plan-required | Start a trial or choose a plan before adding projects. |
| 403 | max-projects | Your plan’s project limit is reached; error.maxProjects gives the limit. |
| 403 | plan-gate | This check is not included in your plan. |
| 403 | paused-by-plan | The project is over your plan’s project limit and paused. It resumes automatically when your plan has room again; trackingStatus cannot be changed until then. |
| 403 | forbidden | The account is restricted: reads still work, but changes that add or modify projects, pages or monitors are blocked (error.accountStatus is restricted). |
| 403 | owner-only | Only the project owner can do this. |
| 403 | flag-viewHealth | Your project membership does not include viewing health. |
| 403 | flag-viewPages | Your project membership does not include viewing pages. |
| 403 | flag-editPages | Your project membership does not include editing pages. |
| 403 | flag-changeSettings | Your project membership does not include changing settings. |
| 403 | flag-viewPerformance | Your project membership does not include viewing performance. |
| 403 | flag-acceptFindings | Your project membership does not include accepting findings. |
| 429 | probe-cooldown | This project was probed in the last 30 seconds. Retry after Retry-After seconds. |
| 403 | check-budget | The owner’s monthly check budget is used up. |
| 403 | tracking-inactive | Tracking is turned off for this project. |
| 403 | phase-off | Uptime monitoring is turned off for this project. |
| 403 | too-many-endpoints | You already have the maximum of 10 webhook endpoints. |
| 429 | send-cooldown | A test or redelivery was sent to this endpoint in the last 10 seconds. |
| 429 | send-rate-limited | More than 20 test sends and redeliveries in the last minute on your account. |
Rate limits
Your plan sets how many requests your account can make per rolling minute, shared across all your keys (see plans). Every response tells you where you stand:
| Header | Meaning |
|---|---|
RateLimit-Limit | Requests allowed in the current window |
RateLimit-Remaining | Requests left in the window |
RateLimit-Reset | Seconds until the window resets |
Retry-After | On a 429: seconds to wait before trying again |
Some actions have their own short limits, because they cost more than a read:
- Uptime probes: one per project every 30 seconds (
probe-cooldown). - Webhook test sends and redeliveries: one per endpoint every 10 seconds, 20 per minute per account.
- Requests with an invalid key are limited per IP address.
Pagination
Lists of projects, pages and findings take page (from 1) and limit (up to 100). meta.total is the number of matching items, so the last page is ceil(total / limit).
Uptime history is newest first and uses a cursor instead, because new checks arrive all the time: pass meta.nextBefore as before to get the next page, and stop when it is null. See uptime check history.
When to retry
| Response | What to do |
|---|---|
429 | Wait Retry-After seconds, then retry. |
5xx or a network error | Retry with backoff (for example 1s, 2s, 4s). Queued actions are safe to retry — an identical queued job is returned instead of a new one. |
Other 4xx | Do not retry unchanged; fix the request, key or permissions using error.code. |