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

# Errors

> HTTP status codes the API returns and what they mean.

The API uses standard HTTP status codes. Every error response shares a single
envelope — an `error` object describing the problem.

| Status | Meaning | Common cause |
| - | - | - |
| `200` | OK | Request succeeded. |
| `400` | Bad request | The request was malformed. |
| `401` | Unauthorized | Missing, malformed, unknown, revoked, or expired API key. |
| `403` | Forbidden | The key lacks the scope required for this endpoint. |
| `404` | Not found | The record doesn't exist **or belongs to another organisation**. |
| `409` | Conflict | The request conflicts with the current state (e.g. a duplicate). |
| `422` | Unprocessable entity | A query parameter or field failed validation (e.g. `limit` over 100). |
| `429` | Too many requests | You exceeded the [rate limit](/rate-limits). |
| `500` | Internal error | Something went wrong on our side. |

## A note on `404`

Requesting a record that belongs to a **different organisation** returns `404`, not `403`.
This is deliberate: it prevents callers from probing which IDs exist outside their own org.
From your key's perspective, anything outside your organisation simply does not exist.

## The error envelope

Every error — at any status — returns the same shape:

```json theme={null}
{
  "error": {
    "code": "not_found",
    "message": "Session not found",
    "status": 404,
    "details": {}
  }
}
```

`code` is a stable machine-readable string, `message` is a human-readable
description, `status` mirrors the HTTP status, and `details` carries any extra
context (empty by default).

## Error codes

| `code` | Status |
| - | - |
| `bad_request` | `400` |
| `unauthorized` | `401` |
| `forbidden` | `403` |
| `not_found` | `404` |
| `conflict` | `409` |
| `validation_error` | `422` |
| `rate_limited` | `429` |
| `internal_error` | `500` |

## Validation errors

A `422 validation_error` carries the field-level failures in `details.errors`:

```json theme={null}
{
  "error": {
    "code": "validation_error",
    "message": "Validation failed",
    "status": 422,
    "details": {
      "errors": [
        { "loc": ["query", "limit"], "msg": "must be 100 or less", "type": "value_error" }
      ]
    }
  }
}
```

## Rate limit errors

A `429 rate_limited` sets `details.retry_after_seconds`, and the response still
carries a `Retry-After` header with the same value. See [rate limits](/rate-limits)
for the headers on every response.

```json theme={null}
{
  "error": {
    "code": "rate_limited",
    "message": "Rate limit exceeded",
    "status": 429,
    "details": { "retry_after_seconds": 30 }
  }
}
```

<Tip>
  A `401` right after creating a key usually means the `Authorization` header is wrong.
  It must be exactly `Token token=ei_live_...` — not `Bearer ...`.
</Tip>


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