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

# Errors and limits

> Status codes, error shapes, and what is rate limited.

Errors are JSON, always with an `error` string:

```json theme={null}
{ "error": "Not found" }
```

Validation failures add the details:

```json theme={null}
{
  "error": "Validation failed",
  "details": [
    {
      "code": "too_small",
      "minimum": 1,
      "path": ["name"],
      "message": "String must contain at least 1 character(s)"
    }
  ]
}
```

## Status codes

| Code  | Meaning           | What to do                                                   |
| ----- | ----------------- | ------------------------------------------------------------ |
| `200` | Success           | —                                                            |
| `201` | Created           | The response body is the new resource, including its `id`    |
| `204` | Deleted           | No body                                                      |
| `400` | Bad request       | Malformed JSON, or a parameter the endpoint rejects outright |
| `401` | Unauthorized      | Missing, malformed, expired, or revoked credential           |
| `404` | Not found         | The id does not exist **or** is not yours — see below        |
| `413` | Payload too large | Chat message over the size cap                               |
| `422` | Validation failed | The body parsed but failed schema validation; see `details`  |
| `429` | Rate limited      | Daily AI budget exhausted                                    |
| `500` | Server error      | Retry; if it persists, report it                             |
| `503` | AI not configured | The AI endpoints are unavailable on this deployment          |

<Note>
  **There is no `403`.** Requesting a resource that belongs to another account
  returns `404`, identical to one that never existed. A `403` would confirm the
  row exists, which is information the caller is not entitled to. Do not write
  code that distinguishes "gone" from "not yours" — it cannot.
</Note>

## Validation

Request bodies are validated against a schema before anything is written.
Unknown fields are ignored rather than rejected, so a client sending a field the
API does not know about will not break — but that field will not be stored
either. If a value you sent is not coming back, check that the field name
matches the schema.

Defaults are applied on create. Omitting `efficiency` on a new recipe gives you
`0.72`, not `null`.

## AI limits

The AI endpoints are metered per account per day:

| Limit    | Value     |
| -------- | --------- |
| Messages | 200       |
| Tokens   | 2,000,000 |

Both reset at midnight UTC. Exceeding either returns `429` with a message
saying which limit you hit. Check where you stand:

```bash theme={null}
curl https://brewgravity.com/v1/ai/usage \
  -H "X-API-Key: $GRAVITY_API_KEY"
```

The chat endpoint also caps a single user message at 8,000 characters and
returns `413` above that.

## Retries

`500` responses are safe to retry with backoff. `429` is not worth retrying
until the limit resets. `4xx` other than `429` will fail identically on retry —
fix the request instead.

Writes are not idempotent: retrying a `POST` that actually succeeded but whose
response you missed will create a second resource. If that matters to your
script, list and check before retrying a create.
