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

# Errors and status codes

> How Baato reports failures, and how your client should respond to each.

Baato uses conventional HTTP status codes, and echoes the status into the response body
alongside a human-readable `message`:

```json theme={null}
{
  "timestamp": "Thu May 14 07:35:16 NPT 2020",
  "status": 401,
  "message": "Invalid access token",
  "data": []
}
```

<Warning>
  Branch on the **HTTP status code**, not on the `status` field in the body. A network
  failure or a gateway error never produces a parseable body at all, so a client that only
  reads `status` will throw on the cases that matter most.
</Warning>

## Status codes

| Code  | Meaning                                                                       | What to do                                                                      |
| ----- | ----------------------------------------------------------------------------- | ------------------------------------------------------------------------------- |
| `200` | Success. `data` may still be an empty array — no results is not an error.     | Handle the empty case explicitly.                                               |
| `400` | A required parameter is missing or malformed.                                 | Fix the request; retrying will not help.                                        |
| `401` | The `key` parameter is missing, malformed, or the token has been deleted.     | Check the token in your [dashboard](https://baato.io/account).                  |
| `403` | The token is valid but the request origin is not in its allowed origins list. | Add the domain to the token's allowed origins.                                  |
| `404` | The path does not exist, or the requested `placeId` / style name is unknown.  | Check the endpoint path and the identifier.                                     |
| `429` | The account's monthly usage credit is exhausted.                              | Back off and retry — see below.                                                 |
| `5xx` | A fault on Baato's side.                                                      | Retry with backoff; if it persists, [contact support](mailto:support@baato.io). |

## Empty results are not errors

Search terms with no match, and reverse lookups over unmapped ground, both return `200` with
an empty `data` array. This is the most common source of "the API is broken" reports.

```javascript theme={null}
const { data } = await response.json();

if (data.length === 0) {
  showMessage("No results found");
  return;
}
```

## Rate limiting

When an account exhausts its monthly [usage credit](/resources/limits), requests fail until
the credit resets. Retry with exponential backoff and a jitter, rather than a fixed interval — a fleet of
clients retrying on the same schedule re-creates the spike that tripped the limit.

```javascript theme={null}
async function requestWithRetry(url, attempts = 4) {
  for (let attempt = 0; attempt < attempts; attempt++) {
    const response = await fetch(url);

    if (response.status !== 429 && response.status < 500) {
      return response;
    }

    // 1s, 2s, 4s, 8s — plus jitter to avoid a synchronised retry storm
    const backoff = 2 ** attempt * 1000 + Math.random() * 250;
    await new Promise((resolve) => setTimeout(resolve, backoff));
  }

  throw new Error("Baato request failed after retries");
}
```

Do not retry `400`, `401`, `403` or `404` — the request is wrong, and repeating it only
consumes credit.

## Reducing avoidable failures

<AccordionGroup>
  <Accordion title="Debounce autocomplete input" icon="keyboard">
    A request per keystroke is the fastest way to burn through your credit. Wait \~300 ms after the
    user stops typing, and cancel in-flight requests that have been superseded.
  </Accordion>

  <Accordion title="Cache what does not change" icon="database">
    Place details for a fixed location are stable. Caching them within the limits set out in
    [Pricing and limits](/resources/limits) cuts usage substantially.
  </Accordion>

  <Accordion title="Keep the token off the client where you can" icon="key">
    A token embedded in a shipped app can be extracted and used by others, and their traffic
    counts against your credit. Restrict the token by domain, or proxy through your own
    backend. See [Authentication](/about/authentication).
  </Accordion>
</AccordionGroup>
