Every error from the API, heartbeat pings and badges is an [RFC 9457](https://www.rfc-editor.org/rfc/rfc9457) problem detail, sent as `application/problem+json`:

```json
{"type": "about:blank", "title": "Not Found", "status": 404}
```

| Member | Content |
|---|---|
| `type` | A link to the problem type's page below, or `about:blank` when the status says it all |
| `title` | The same for every occurrence of the type. With `about:blank`, the HTTP status phrase |
| `status` | The HTTP status code |
| `detail` | Sometimes: what went wrong this time, written to help you fix the request |
| `errors` | Validation problems only: each invalid field with its messages |

Branch on `status`, and on `type` when it isn't `about:blank`. Don't parse `title` or `detail`: their wording can change.

## Statuses
| Status | When | Do |
|---|---|---|
| `401` | There is no token, or it is invalid or revoked | See [Authentication](https://monitor.agilepixel.io/docs/api/authentication) |
| `402` | The team has as many monitors as its plan allows | See [Monitor limit reached](https://monitor.agilepixel.io/docs/api/problems/monitor-limit-reached) |
| `403` | The token may not do this | Use a token made by an Owner or Admin of the right team |
| `404` | Nothing with that ID belongs to the team, or the path doesn't exist | Check the ID and the team the token belongs to |
| `405` | The path exists but not with that method | Check the method |
| `422` | The body or query is invalid | See [Validation failed](https://monitor.agilepixel.io/docs/api/problems/validation-failed) |
| `429` | The rate limit is used up | Wait for `Retry-After` seconds, then retry |
| `500` | Something went wrong on our side | Retry with a backoff; if it persists, contact support |

A `403` caused by the token itself says why in `detail`:

```json
{"type": "about:blank", "title": "Forbidden", "status": 403, "detail": "This token is not scoped to a team."}
```

## Problem types
These problems have their own `type` and a page explaining them:

| `type` | Status | Means |
|---|---|---|
| [`https://monitor.agilepixel.io/docs/api/problems/validation-failed`](https://monitor.agilepixel.io/docs/api/problems/validation-failed) | `422` | The body or query is invalid |
| [`https://monitor.agilepixel.io/docs/api/problems/monitor-limit-reached`](https://monitor.agilepixel.io/docs/api/problems/monitor-limit-reached) | `402` | The plan has no room for another monitor |

## MCP errors
The [MCP server](https://monitor.agilepixel.io/docs/api/mcp) speaks JSON-RPC. A tool that fails returns a tool error with a message for the assistant, not a problem detail. Authentication and rate-limit failures are plain JSON with a `message`.
