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

# Authentication

> API keys, permissions and the rules that apply to them.

Every request needs an API key. Send the key in the `Authorization` header:

```
Authorization: Bearer kai_live_...
```

A key belongs to one workspace. The key decides which workspace the request
reads and writes, so no request carries a workspace id.

## Make a key

In Kai, go to **Settings → API** and select **Create API key**. Only an owner
or an admin can make a key.

Kai shows the full key one time. Kai stores only a SHA-256 hash of the secret
half, so nobody can read the key again, not even Kai support. If you lose a
key, create another one and revoke the old one.

## Permissions

A key holds the permissions that you select when you make it. Each endpoint
names the permission that it needs.

| Permission         | What the key can do                              |
| ------------------ | ------------------------------------------------ |
| `contacts:read`    | Read and export contacts.                        |
| `contacts:write`   | Create, update, assign and delete contacts.      |
| `attributes:read`  | Read the workspace attributes.                   |
| `attributes:write` | Create, update and archive workspace attributes. |
| `members:read`     | Read the teammate roster.                        |

A write permission includes its read permission. `contacts:write` therefore
also reads contacts, because every write answers with the record that it
wrote.

<Note>
  These permissions are not the roles that people hold in Kai. A key has no
  role and no seat. Give a key the smallest set of permissions that its job
  needs.
</Note>

## Revoke a key

In **Settings → API**, select **Revoke** beside the key. The next request with
that key returns 401. Kai keeps the name of the key in the list, so the audit
trail stays complete.

## Errors

Kai answers the same way for every authentication failure:

```json theme={null}
{ "error": { "type": "unauthorized", "message": "That API key is not valid." } }
```

The message is the same for a key that does not exist, a key that is revoked
and a key that expired. This is deliberate: a different message for each case
would let a caller learn which key ids exist.

If the key is valid but lacks the permission, the response is 403 and names
the permission:

```json theme={null}
{
  "error": {
    "type": "forbidden",
    "message": "This key does not have the \"contacts:write\" permission."
  }
}
```

## Transport

The API accepts HTTPS only. Do not put a key in a URL, in a query parameter or
in a log line. Kai never sends a key by email.
