> ## 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.

## 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.


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