# Keys, scopes and tenants

> Who can do what - API keys with scopes, keys limited to some namespaces, caps and rates, tenants, and the keys MCP connections get.

Every request acts for one **tenant** (an account: it owns namespaces, keys, usage and a bill)
with one **key**. A key has a scope, may be limited to some namespaces, and may carry its own
rate and caps. Give every app and agent its own narrow key; keep the full-access one to
yourself.

## Sending a key

Send the key as `Authorization: Bearer tb_...` (or `X-API-Key: tb_...`). The clients read
`SKIMMERDB_KEY` from the environment.

```sh title="curl"
curl -s https://api.skimmerdb.com/v1/me -H "Authorization: Bearer $KEY"
```

```python title="Python"
from skimmerdb import SkimmerDB
db = SkimmerDB("tb_...")        # or SkimmerDB() with SKIMMERDB_KEY set
print(db.me())
```

```ts title="TypeScript"
import { SkimmerDB } from "skimmerdb";
const db = new SkimmerDB("tb_...");   // or new SkimmerDB() with SKIMMERDB_KEY set
console.log(await db.me());
```

`GET /v1/me` says who you are, the tenant you act for, its plan, your scope and (for a limited
key) its namespaces.

## Your first key

Signing up (`POST /v1/signup`, or [the sign-up page](https://skimmerdb.com/signup)) makes you,
your first tenant and its first key: scope `admin`, full access, shown only once. Use it to make
narrower keys, not inside apps or agents.

## Scopes

| Scope | May |
|---|---|
| `read` | List namespaces, search, count, get documents, warm, SQL, usage |
| `write` | Also create and delete namespaces; write, update, delete and import documents |
| `admin` | Also make, list, change and revoke keys, and billing |

A request the key's scope doesn't allow is a `403 forbidden`.

## Making keys

`POST /v1/keys` with `{"name", "scope", "namespaces", "rate_per_s", "cap_queries", "cap_writes"}`.
The answer has the key; it's shown only here.

```sh title="curl"
curl -s https://api.skimmerdb.com/v1/keys -H "Authorization: Bearer $ADMIN_KEY" \
  -d '{"name": "support bot", "scope": "read", "namespaces": ["help-center"]}'
# {"id": 7, "name": "support bot", "key": "tb_...", "prefix": "tb_Ab3dE", "scope": "read", "namespaces": ["help-center"]}
```

```python title="Python"
key = db.create_key("support bot", scope="read", namespaces=["help-center"])
```

```ts title="TypeScript"
const key = await db.createKey("support bot", { scope: "read", namespaces: ["help-center"] });
```

| Field | Meaning |
|---|---|
| `name` | A label. |
| `scope` | `read`, `write` (the default) or `admin`. |
| `namespaces` | The namespaces the key may use: names, or `prefix*` (`"agent-7-*"`). Default: all. |
| `rate_per_s` | Requests a second for this key (0: none of its own; the tenant's plan still applies). |
| `cap_queries` | Queries a billing period (0: none). Past it: `429`. |
| `cap_writes` | Documents written or deleted a billing period (0: none). Past it: `429`. |

- `GET /v1/keys` lists the tenant's live keys (`connected_app` marks one made by an MCP/OAuth
  approval).
- `PUT /v1/keys/{id}/limits` changes `namespaces`, `rate_per_s`, `cap_queries` and `cap_writes`,
  at once.
- `DELETE /v1/keys/{id}` revokes it at once (and disconnects an MCP connection that uses it).

### Who can manage keys

Only an `admin` key **without** namespace limits or caps (signup's key is one), or the owner's
login, can make, list, change or revoke keys. So a `read` or `write` key handed to an app or an
agent can't make more keys, and an admin key limited to some namespaces can't make an unlimited
one.

## Keys limited to namespaces

A key limited to `["help-center"]` or `["mem-u-17", "agent-7-*"]` sees only those. Every other
namespace answers exactly like a name nobody has: `404`, and left out of `GET /v1/namespaces`.
The same holds over MCP. This is how you give each user's agent its own memory and nothing
else; see [Agent memory](/guides/agent-memory#scope-each-agent-to-its-own-memory).

> **Tip** Name namespaces with a prefix per owner or purpose (`agent-7-...`, `mem-...`, `kb-...`)
> so one `prefix*` covers every namespace an agent creates for itself.

## Tenants

A tenant owns namespaces (stored under its own prefix in object storage), keys, usage and a
bill. One tenant never sees another's namespaces: a name another tenant has answers exactly
like a name nobody has.

- A person can own or belong to several tenants. `GET /v1/tenants` lists yours (with your
  role); `POST /v1/tenants` `{"name"}` makes one you own. Both need a login.
- `POST /v1/login` `{"email", "password"}` answers a token valid for a day, for managing the
  account. It acts for your default tenant, or the one named by `X-Tenant: <id>`.
- `DELETE /v1/tenants/{id}` deletes a tenant, its namespaces, keys and usage for good (its
  owner only; not your account's own).

API keys belong to exactly one tenant, so a key never needs `X-Tenant`.

## MCP connections

An agent that connects to `https://api.skimmerdb.com/mcp` with OAuth sends you to a consent page
where you sign in and pick the tenant, read-only or read-and-write, and optionally the
namespaces it may use. The connection gets a key of its own, limited that way; it appears in
`GET /v1/keys` with `connected_app`, and revoking it disconnects the agent. An agent can also
connect with a key you made. See [Connect an agent](/mcp).

## Limits

Each tenant's plan sets requests a second and requests in flight (per server); a key's own
`rate_per_s` can only be tighter. Answers that count against a rate carry `RateLimit-Limit`,
`RateLimit-Remaining`, `RateLimit-Reset` and `RateLimit-Policy`, and every `429` has
`Retry-After`. See [Limits and plans](/reference/limits).
