> This page is for version API + Legacy Read.
> For other versions, use one of these documentation indexes:
> - API (default): https://docs.getthera.com/api/llms.txt
> - API + Legacy Read: https://docs.getthera.com/api-legacy-read/llms.txt
> - API + Legacy Full: https://docs.getthera.com/api-legacy-full/llms.txt

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.getthera.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.getthera.com/_mcp/server.

# Errors

Errors raised by the API come back as JSON in this shape.

```json
{
  "status": "UNAUTHORIZED",
  "timestamp": "17-09-2026 09:14:22",
  "message": "This API key is not valid. It may have been revoked or expired.",
  "displayMessage": "This API key is not valid. It may have been revoked or expired."
}
```

`message` is the one to log. `displayMessage` is safe to show a user. Some errors also carry
`debugMessage` or a `subErrors` list when a request failed validation on specific fields.

A request that matches no route at all never reaches the API, so it comes back in the web layer's
own plainer shape. Match on the status code rather than on the body.

## 401 Unauthorized

The key was missing, unknown, revoked or expired.

Send it as `X-Thera-API-Key`. Not as a bearer token, and not in the query string.

## 403 Forbidden

The key is valid but is not allowed to do this.

| What you get back                                       | Why                                                                        |
| ------------------------------------------------------- | -------------------------------------------------------------------------- |
| `An API key can only read. This endpoint changes data.` | Keys are read-only. Only `GET` is allowed.                                 |
| `This API key belongs to a different company.`          | The company in the URL is not the key's company.                           |
| `This endpoint cannot be used with an API key.`         | The endpoint acts on behalf of a single worker, or hands out a credential. |

A key is scoped to one company for its whole life. There is no way to widen it, so if you need
another company's data you need that company's own key.

## 404 Not Found

Nothing exists at that ID within your company.

Worth ruling out first: a mistyped path. Routes are flat and have no `/api` prefix, so it is
`/companies/{companyId}/teams`, not `/api/companies/{companyId}/teams`.

## 429 Too Many Requests

You went over 600 requests a minute.

The response carries a `Retry-After` header with the number of seconds to wait, and the message
repeats it:

```
Too many requests on this API key. Try again in 12 seconds.
```

The limit counts each key separately, and 600 is the floor rather than a guarantee, so treat
`Retry-After` as the thing to obey rather than pacing against the number.

## 5xx

Something broke on our side, and retrying is reasonable. Retries still count against your rate
limit, though, because a request is counted when it arrives rather than when it succeeds. Back off
between attempts.

If one persists, send us the `timestamp` from the body at
[support@getthera.com](mailto:support@getthera.com) and we can find the request.