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

# Authentication

> How the `Authorization: Bearer` header authenticates Slideless API requests

<Note>
  If you're not building against the raw HTTP API directly, use the [CLI](/cli/overview) instead — it handles authentication for you via `slideless login`.
</Note>

## The header

Every Slideless API endpoint (except the public token-based [`getSharedPresentation`](/api-reference/get-shared-presentation)) authenticates via the standard bearer token header:

```
Authorization: Bearer cko_your_key_here
```

## Key prefixes

| Prefix | Type             | Use case                                         |
| ------ | ---------------- | ------------------------------------------------ |
| `cko_` | Organization key | What every external integration uses             |
| `cka_` | Admin key        | Internal platform automation; not user-creatable |

The middleware inspects the prefix and routes to the right validator:

* `cka_` → validated against the `admin_api_keys` collection
* `cko_` → validated against the `organization_api_keys` collection (also resolves the org context)

Anything else returns `401`.

## Getting a key

Two paths:

* **Terminal / OTP** (recommended for CI and agents) — `POST /cliRequestSignupOtp` then `POST /cliCompleteSignup` (or the login variants). No browser round-trip. See [CLI auth endpoints](/api-reference/cli-auth) or the CLI wrapper at [`cli/auth`](/cli/auth).
* **Dashboard** — create a key at **Organization → API Keys** in [app.slideless.ai](https://app.slideless.ai). Same [API keys concept](/concepts/api-keys) either way; the OTP flow just automates the creation.

Pick scopes when creating:

| Scope                 | Granted to                                                     |
| --------------------- | -------------------------------------------------------------- |
| `presentations:write` | Endpoints that create or modify presentations (upload, update) |
| `presentations:read`  | Endpoints that read presentations (list, get)                  |

Keys minted through the OTP flow are granted both scopes by default.

## Verifying a key

The CLI way:

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
slideless verify
```

The raw HTTP way:

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl -X POST \
  -H "Authorization: Bearer cko_..." \
  https://europe-west1-slideless-ai.cloudfunctions.net/verifyApiKey
```

`200` → key is valid (response includes name, scopes, organization, last-used time).
`401` → key is missing, malformed, or revoked.

## Errors

| Status | Code                | What it means                            | Fix                                                     |
| ------ | ------------------- | ---------------------------------------- | ------------------------------------------------------- |
| `401`  | `unauthenticated`   | Header missing or key not recognized     | Send `Authorization: Bearer <cko_…>` with a valid value |
| `403`  | `permission-denied` | Key valid but you don't own the resource | The key's user must match the presentation's `ownerId`  |
| `403`  | `revoked`           | Key was revoked                          | Create a new key                                        |

## What's stored server-side

Slideless stores a SHA-256 hash of every API key, not the raw value. The dashboard shows the raw key **once** at creation. If you lose it, create a new one.

## Operational guidance

* **Treat keys as secrets** — don't commit, paste, or log them.
* **One key per integration** — easier to rotate, easier to attribute usage.
* **Set `lastUsedAt` reminders** — long-unused keys are good revocation candidates.
* **Use `slideless verify`** at the start of any long-running script so you fail fast on auth issues.
