---
title: "Authentication and scopes"
description: "Authenticate to the Lookio API with an API key or an OAuth token, and choose the scopes that decide what a credential may do."
canonical: "https://lookio.app/docs/api/authentication"
updated: "2026-11-03"
---

# Authentication and scopes

Send a credential in the `Authorization` header of every request.

```bash
curl https://api.lookio.app/v1/account \
  -H "Authorization: Bearer $LOOKIO_API_KEY"
```

A credential looks like `sk_live_<id>_<secret>_<checksum>`. Never put it in a URL or a query string, and never in front-end code: the API sends no CORS headers on `/v1`, so a browser cannot call it.

## Two kinds of credential

|                      | API key                                                                                                                                       | OAuth connection                                                                |
| -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- |
| **Created by**       | An admin, in **Developer tools**.                                                                                                             | A person, who approves it in the app. Used by the CLI login and by MCP clients. |
| **Belongs to**       | The workspace.                                                                                                                                | The person who approved it.                                                     |
| **Permissions**      | Its scopes, and optionally a list of assistants.                                                                                              | Its scopes, narrowed by the person's own Lookio permissions at every call.      |
| **Conversations**    | Keeps the conversations it starts, continued with `conversation_id`. Name your users with `end_user`, or send `store: false` to keep nothing. | Keeps the person's own chats, personal. Use `conversation_id`.                  |
| **Members and tags** | Never.                                                                                                                                        | Admins only, with the `admin` scope.                                            |
| **Lifetime**         | Until it expires or is revoked.                                                                                                               | Access token 30 days, renewed by a refresh token valid 90 days.                 |

Use an API key for a job or a backend. Use a connection for a person's CLI or AI client. See [API keys](/docs/platform/api-keys).

## Scopes

A scope is a permission on a credential. A request is refused with `insufficient_scope` when the credential lacks the scope the endpoint needs. Each endpoint page names its scope.

| Scope               | Lets the credential                                                                                                                                                                                                                                                           |
| ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `account:read`      | See your workspace, plan, and credit balance.                                                                                                                                                                                                                                 |
| `usage:read`        | See your credit usage over time, and the log of every answer: when, which assistant, through which channel, what it cost. Not what was asked.                                                                                                                                 |
| `resources:read`    | See your resources, their indexed content and their import status, including the pages of a site, and the log of every indexing with its errors.                                                                                                                              |
| `resources:write`   | Add resources (files, web pages, whole sites, text), edit them, re-index them and synchronise sites. Importing costs no credits.                                                                                                                                              |
| `resources:delete`  | Delete resources and everything indexed from them.                                                                                                                                                                                                                            |
| `assistants:read`   | See the assistants you have access to and their settings, and the conversations people had with them (widget visitors, the users of your product), with their thumbs.                                                                                                         |
| `assistants:write`  | Create and edit assistants, and choose the resources they answer from. Deleting an assistant is a separate permission.                                                                                                                                                        |
| `assistants:delete` | Delete assistants. Their resources are kept.                                                                                                                                                                                                                                  |
| `query`             | Ask questions and read answers with sources. Each answer returned by the model spends the selected mode's fixed price, even if no source is found. Assistants with no resources are refused before a model call, at no cost. Rename or delete conversations and rate answers. |
| `admin`             | Manage the Lookio permissions of the workspace's members and their access to assistants, and read the workspace's activity log (who changed what). Admins only.                                                                                                               |
| `webhooks:write`    | Create, edit and delete the webhooks that notify your systems when an import finishes or needs attention. Not available yet.                                                                                                                                                  |

`query` is the only scope that spends credits. Deleting is apart from adding: `resources:delete` and `assistants:delete` are separate scopes, so a key can create and edit without being able to remove anything. Widgets follow the assistant scopes: reading them needs `assistants:read`, creating and changing them `assistants:write`, deleting them `assistants:delete`.

Scopes can be granted before the feature they name exists. `webhooks:write` is such a scope: no endpoint honours it yet.

### What a credential can really do

`GET /v1/account` returns the credential's effective scopes. They are the scopes it was granted, narrowed by:

- for a personal connection, the ceiling an admin set for what members may hand to AI clients,
- the person's own Lookio permissions, call by call: a connection never gets a tool its owner would be refused,
- for an API key, the fact that `admin` is never available: a key does not manage people.

On a paid plan, a person also needs the `api` permission to use the REST API and the CLI, and the `mcp` permission to use an MCP client, or the call fails with `permission_denied`.

## OAuth

An MCP client or the CLI gets a token through OAuth 2.1. You do not need this to use an API key.

- **Authorization code with PKCE.** PKCE with `S256` is required. `plain` is refused.
- **Device code** (RFC 8628) for machines with no browser, with a 5 second polling interval and a 15 minute code.
- **Refresh tokens** to renew access tokens.
- **Client registration** by Client ID Metadata Document (an `https` client id) or by dynamic registration (RFC 7591). Every client is public: there is no client secret.

Discover the endpoints at `/.well-known/oauth-authorization-server` on the host you call. The same server answers on `api.lookio.app` and `mcp.lookio.app`.

| Endpoint             | Path              |
| -------------------- | ----------------- |
| Authorization        | `/authorize`      |
| Token                | `/oauth/token`    |
| Device authorization | `/oauth/device`   |
| Registration         | `/oauth/register` |
| Revocation           | `/oauth/revoke`   |

A token can be requested for one resource (RFC 8707): `https://api.lookio.app/v1`, `https://mcp.lookio.app/mcp` or `https://mcp.lookio.app/mcp/code`. A token issued for one of them is refused on the others. A token requested with no `resource` works everywhere.

See [Connect an AI client](/docs/mcp/connect) for the MCP flow.

## Failures

| Code                      | Meaning                                                                    |
| ------------------------- | -------------------------------------------------------------------------- |
| `authentication_required` | No `Authorization: Bearer` header.                                         |
| `invalid_api_key`         | The credential is malformed or unknown.                                    |
| `api_key_expired`         | The credential passed its expiry.                                          |
| `api_key_revoked`         | An admin revoked it, or the person behind a connection left the workspace. |
| `insufficient_scope`      | Valid credential, missing scope.                                           |
| `permission_denied`       | The person lacks a Lookio permission.                                      |

Repeated failed authentication from one address is rate limited. See [Rate limits](/docs/api/rate-limits).
