Errors and limits
Every error code the Omnipresence API returns, what each one means, the rate limit, and which failures are worth retrying.
Updated October 20, 2026
Conventional status codes, with a machine-readable code and a message on every failure. The code is the thing to branch on; the message is for whoever reads the log.
The codes
| Status | Code | Meaning |
|---|---|---|
| 401 | missing_key | No Authorization: Bearer omni_sk_... header. |
| 401 | invalid_key | The key is invalid, revoked or expired. |
| 403 | inactive | The account's subscription is not active. |
| 403 | no_api_access | The plan does not include the reporting API. |
| 403 | project_forbidden | The key is scoped to a different project. |
| 404 | not_found | No such project on this account. |
| 400 | bad_resource | Unknown resource name. The message lists the valid ones. |
| 400 | bad_metric | A timeseries request with a missing or unknown metric. The message lists them. |
| 429 | rate_limited | Over 120 requests a minute. |
Rate limit
120 requests a minute. Enough for a dashboard or a nightly sync, and not enough to page through a year of runs in a loop with no pause.
If you are hitting it, the usual cause is paging with a small limit. Ask for 200 rows a page instead of 20 and the same pull costs a tenth of the requests.
What to retry
| Status | Retry? |
|---|---|
| 429 | Yes, with backoff. Wait at least the rest of the minute. |
| 5xx | Yes, with backoff. |
| 401 | No. Fix the key. |
| 403 | No. It is a decision about access, not a transient failure. |
| 404 | No. |
| 400 | No. The message says what is wrong with the request. |
A retry loop that does not distinguish these is how a bad key turns into a rate limit: a few hundred retries of a 401 earn a 429, and then the real problem is hidden behind the wrong error.
Backoff that behaves
Exponential, starting around a second, capped at a minute, with a little randomness so several workers do not retry in lockstep. Give up after a handful of attempts and log the last response rather than retrying forever.
Reading a failure properly
The message is written to be actionable. no_api_access names the plans that include the API; bad_resource lists every valid resource name; bad_metric lists the metrics. When something does not work, the response usually contains the answer, which is faster than reading this page.
Every error is scoped to the key's own account, including a 404. There is no way to learn whether a project exists on another account, which is deliberate.
Questions about errors and limits
- What is the rate limit?
- 120 requests a minute. A limited request returns 429 and says so.
- Should I retry a 403?
- No. A 403 is a decision about access rather than a transient failure, so a retry fails identically.
- Why do I get a 403 rather than a 404 for another account's project?
- Because the key is scoped to a different project, and saying so is more useful than pretending the project does not exist.