> ## Documentation Index
> Fetch the complete documentation index at: https://docs.andteam.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Errors

> One refusal shape, and a stable type for each problem.

Every refusal is `application/problem+json` ([RFC 9457](https://www.rfc-editor.org/rfc/rfc9457)):

```json theme={null}
{
  "type": "https://docs.andteam.com/api/problems/field-group-required",
  "title": "The API key may not read this resource",
  "status": 403,
  "detail": "…",
  "instance": "…"
}
```

**Branch on `type`**, a stable URL, never on `title` or `detail`. `type` never changes meaning or
spelling; `title` and `detail` are prose for a log and may be reworded. Every type has a page at its
URL, listed below. `detail` and `instance` are present when they add something.

A 401 carries `WWW-Authenticate: Bearer realm="andteam"`. Every error response is `Cache-Control: no-store`.

## The problem types

| Status | Type | Meaning | Retry |
| - | - | - | - |
| 401 | [`missing-key`](https://docs.andteam.com/api/problems/missing-key) | No API key was sent | No |
| 401 | [`invalid-key`](https://docs.andteam.com/api/problems/invalid-key) | The API key is not valid | No |
| 401 | [`revoked-key`](https://docs.andteam.com/api/problems/revoked-key) | The API key has been revoked | No |
| 401 | [`expired-key`](https://docs.andteam.com/api/problems/expired-key) | The API key has expired | No |
| 401 | [`rolled-key-expired`](https://docs.andteam.com/api/problems/rolled-key-expired) | The API key was rolled and its 24 hours are over | No |
| 403 | [`pending-approval`](https://docs.andteam.com/api/problems/pending-approval) | The API key is waiting for the Information Officer's approval | Later |
| 403 | [`ip-not-allowed`](https://docs.andteam.com/api/problems/ip-not-allowed) | The request did not come from the key's allowed addresses | No |
| 403 | [`field-group-required`](https://docs.andteam.com/api/problems/field-group-required) | The API key may not read this resource | No |
| 403 | [`company-not-allowed`](https://docs.andteam.com/api/problems/company-not-allowed) | The API key may not read this company | No |
| 429 | [`rate-limited`](https://docs.andteam.com/api/problems/rate-limited) | Too many requests | After `Retry-After` |
| 400 | [`invalid-parameter`](https://docs.andteam.com/api/problems/invalid-parameter) | A query parameter is not valid | No |
| 404 | [`not-found`](https://docs.andteam.com/api/problems/not-found) | Not found | No |
| 409 | [`ambiguous-id`](https://docs.andteam.com/api/problems/ambiguous-id) | More than one of the key's companies holds this id | With `company_id` |
| 500 | [`internal-error`](https://docs.andteam.com/api/problems/internal-error) | Something went wrong | Yes, with a pause |

"Retry" says whether sending the **identical request** could succeed. A 4xx other than 429 will not
until something outside the request changes.

## Handling them

```javascript theme={null}
const res = await fetch(url, { headers });
if (!res.ok) {
  const problem = await res.json();           // application/problem+json
  switch (problem.type.split("/").pop()) {
    case "rate-limited":
      await sleep(Number(res.headers.get("Retry-After") ?? 1) * 1000);
      return retry();
    case "internal-error":
      return retryWithBackoff();
    default:
      throw new Error(`${problem.status} ${problem.type}`);
  }
}
```

Treat a 5xx whose body is not a problem as an `internal-error`: an unexpected failure may not have this
shape. A client should also treat a type it does not know as a failure to log, not a crash: new types
can be added. See [Versioning](https://docs.andteam.com/versioning.md).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.