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

# Authentication

> Create API keys and authenticate requests to the Kualia API

The API uses personal API keys as bearer tokens. Keys are tied to your Kualia account and can act on every workspace your account has access to (including family-shared workspaces).

## Creating a key

1. Open the web app and go to **Settings → API Keys**.
2. Click **Create Key**, give it a name, and optionally mark it **Read-only**.
3. Copy the key immediately — it is shown exactly once and never again. Kualia stores only a hash of it.

You can have up to 20 active keys. Use separate keys per integration so you can revoke one without breaking the others.

## Using a key

Send the key in the `Authorization` header of every request:

```bash theme={null}
curl https://api.kualia.com/v1/user \
  -H "Authorization: Bearer kualia_a1b2c3d4..."
```

A missing or invalid key returns `401 unauthorized`.

## Scopes

| Scope   | Granted by                         | Allows                                      |
| ------- | ---------------------------------- | ------------------------------------------- |
| `read`  | Every key                          | All `GET` endpoints                         |
| `write` | Keys created without **Read-only** | All `POST`, `PATCH`, and `DELETE` endpoints |

A read-only key calling a write endpoint gets `403 forbidden`.

## Revoking a key

In **Settings → API Keys**, click **Revoke** next to a key. Revocation is immediate and permanent — requests with that key start failing with `401` right away.

<Warning>
  Treat API keys like passwords. Anyone who has a key can read and change your budget data. Never commit keys to source
  control or share them in messages.
</Warning>

## Rate limits

Each key may make **200 requests per hour** (fixed window). Exceeding the limit returns `429 rate_limit_exceeded` with a `Retry-After` header (seconds until the window resets).

## Review status of API writes

Transactions created through the API land in the in-app **review queue** (`review_status: "needs_review"`) by default, so you can verify programmatic writes before treating them as final. Pass `"review_status": "reviewed"` on create if you want to skip the queue. Updates through the API never silently change a transaction's review status — it only changes when you send `review_status` explicitly.
