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

# Errors

> Every status code ACAAS can return, what it means, and how to recover.

ACAAS uses standard HTTP status codes. Successful requests return `200`.
Anything else falls into one of the categories below. All error responses are
JSON.

## Error response shape

Validation errors follow FastAPI's standard envelope: a top-level `detail`
array describing each problem.

```json theme={"dark"}
{
  "detail": [
    {
      "loc": ["body", "intensity"],
      "msg": "Input should be less than or equal to 10",
      "type": "less_than_equal"
    }
  ]
}
```

* `loc` — path to the offending field, from the request root.
* `msg` — human-readable message.
* `type` — machine-readable error type, suitable for branching logic.
* `input` *(optional)* — the rejected value, when the server can echo it back.
* `ctx` *(optional)* — extra context, such as the boundary that was violated.

Non-validation errors (`401`, `413`, `429`, `5xx`) return a simpler shape with
a single `detail` string.

```json theme={"dark"}
{
  "detail": "Invalid API key"
}
```

## Status codes

### 200 OK

The request succeeded. Every capitalization endpoint returns the
[shout response envelope](/api-reference/shout); `/v1/emphasize` returns the
[emphasis envelope](/experimental-emphasis#response-shape).

### 401 Unauthorized

The `X-API-Key` header is missing, malformed, or revoked. The demo key
`acaas_banned_demo_key` always returns `401` — it had its bullhorn revoked.

```json theme={"dark"}
{ "detail": "Invalid API key" }
```

**How to recover.** Confirm the header is present and spelled exactly
`X-API-Key`. Confirm the value is non-empty. In production, rotate the key
from the dashboard.

### 413 Payload Too Large

The `text` field exceeds 10,000 characters. ACAAS will not amplify what it
cannot lift.

```json theme={"dark"}
{ "detail": "Text exceeds 10000 character limit" }
```

**How to recover.** Chunk the input client-side, call `/v1/shout` (or any
capitalization endpoint) per chunk, and concatenate the results. Case
conversion is per-character, so chunked output equals single-call output.

### 422 Unprocessable Entity

The body is valid JSON but failed schema validation. Common causes:

* `text` is missing or empty.
* `intensity` (on `/v1/scream`) is outside `1..10`.
* `emphasis_ratio` (on `/v1/emphasize`) is outside `(0, 1]`.

```json theme={"dark"}
{
  "detail": [
    {
      "loc": ["body", "text"],
      "msg": "String should have at least 1 character",
      "type": "string_too_short"
    }
  ]
}
```

**How to recover.** Read `loc` to find the bad field, surface `msg` to the
user (or log it), and resubmit with a valid value. Treat `type` as a stable
key for client-side branching.

### 429 Too Many Requests

You have exhausted your quota for the current rate limit window. ACAAS does
not serve another request until the window resets.

```json theme={"dark"}
{ "detail": "Rate limit exceeded" }
```

**How to recover.** Call [`/v1/rate-limits`](/api-reference/rate-limits) to
see how long until the window resets, then retry after that interval. For
guidance on graceful backoff, see [Rate limiting](/rate-limiting).

### 5xx Server Errors

Something went wrong on the ACAAS side. These are rare but possible during
deployments or upstream model incidents (the latter affecting `/v1/emphasize`
specifically).

**How to recover.** Retry with exponential backoff — start at one second,
double on each attempt, cap at sixty seconds. Stop after five attempts and
surface the failure. Check the [status page](https://status.acaas.example.com)
if retries continue to fail.

## Handling errors in code

A defensive pattern that handles all the above:

<CodeGroup>
  ```python Python theme={"dark"}
  import time
  import requests

  def shout(text: str, *, api_key: str, max_attempts: int = 5) -> str:
      backoff = 1.0
      for attempt in range(max_attempts):
          resp = requests.post(
              "https://api.acaas.example.com/v1/shout",
              headers={"X-API-Key": api_key},
              json={"text": text},
          )

          if resp.status_code == 200:
              return resp.json()["result"]

          if resp.status_code in (401, 413, 422):
              # Client errors are not retryable.
              raise ValueError(resp.json().get("detail"))

          if resp.status_code == 429:
              # Honor the rate limit window.
              status = requests.get(
                  "https://api.acaas.example.com/v1/rate-limits",
                  headers={"X-API-Key": api_key},
              ).json()
              time.sleep(status["resets_in_seconds"])
              continue

          # 5xx — exponential backoff.
          time.sleep(backoff)
          backoff = min(backoff * 2, 60)

      raise RuntimeError("ACAAS unavailable after retries")
  ```

  ```javascript Node theme={"dark"}
  async function shout(text, { apiKey, maxAttempts = 5 } = {}) {
    let backoff = 1000;

    for (let attempt = 0; attempt < maxAttempts; attempt++) {
      const resp = await fetch("https://api.acaas.example.com/v1/shout", {
        method: "POST",
        headers: {
          "X-API-Key": apiKey,
          "Content-Type": "application/json",
        },
        body: JSON.stringify({ text }),
      });

      if (resp.ok) {
        const { result } = await resp.json();
        return result;
      }

      if ([401, 413, 422].includes(resp.status)) {
        const { detail } = await resp.json();
        throw new Error(typeof detail === "string" ? detail : JSON.stringify(detail));
      }

      if (resp.status === 429) {
        const limits = await fetch("https://api.acaas.example.com/v1/rate-limits", {
          headers: { "X-API-Key": apiKey },
        }).then((r) => r.json());
        await new Promise((r) => setTimeout(r, limits.resets_in_seconds * 1000));
        continue;
      }

      await new Promise((r) => setTimeout(r, backoff));
      backoff = Math.min(backoff * 2, 60_000);
    }

    throw new Error("ACAAS unavailable after retries");
  }
  ```
</CodeGroup>

## Next steps

<CardGroup cols={2}>
  <Card title="Rate limiting" icon="gauge-high" href="/rate-limiting">
    Quota mechanics, the `status` ladder, and graceful backoff.
  </Card>

  <Card title="Quickstart" icon="rocket" href="/quickstart">
    Make your first ACAAS request in under a minute.
  </Card>
</CardGroup>
