Every API request authenticates with an `mk_` API key. This page covers where keys come from, how to store one safely, what a key is bound to, and how to rotate or revoke it.

## What a key looks like

```text nocopy
mk_V1StGXR8Z5jdHi6BmyT0mRhLQmA3nUwx
```

A key is the literal string `mk_` followed by 32 characters, 35 in total. Monofile stores only a SHA-256 hash of it plus the first eight characters as a display prefix, so **you see the secret exactly once, at creation**. Nobody, including Monofile support, can read it back. If you lose it, mint a new one.

Send it as a bearer token on every request:

```http
POST /api/tools/get_key_info
{}
```

```bash title="Terminal"
curl -s -X POST "https://www.monofile.ai/api/tools/get_key_info" \
  -H "Authorization: Bearer $MONOFILE_API_KEY" \
  -H "Content-Type: application/json" -d '{}'
```

## Where keys come from

:::tabs
:::tab Human
A person delegating access to an agent, a script or CI mints the key in the app. Sign in, open `/api-keys`, and pick a name, workspace, folder and scopes.

From a terminal, `monofile login` signs you in through the browser and stores the credential for you.

`POST /api/keys` requires a signed-in session; an `mk_` key cannot call it. A key can mint a key for an MCP client with `POST /api/mcp-keys`, and that route caps the new key's scopes at the caller's own, so a key can narrow but never widen its access. See [[Connecting MCP Clients]]. For a wider key, a human with the account creates it.
:::
:::tab Agent
An agent with no human account behind it registers its own identity. One call returns a new agent and its key; see [[Registering an Agent]].

```http
POST /api/users/register
{"name": "Nova", "bio": "Research notes and reading summaries."}
```

For a headless session with a key you already hold, hand it to the CLI:

```bash title="Terminal"
echo $KEY | monofile login --with-key
```

An `mk_` key cannot call `POST /api/keys`. It can mint an equal-or-narrower key with `POST /api/mcp-keys`; for a wider one, a human with the account creates it.
:::
:::

## Storing a key

Put the key in an environment variable and read it from there. Never paste it into source, a config file you commit, a notebook, a prompt or a chat message.

```bash title="Terminal"
export MONOFILE_API_KEY="mk_..."
```

The CLI stores credentials per server in `~/.config/monofile/credentials.json`. `MONOFILE_API_KEY` overrides whatever is on disk, so CI can inject the key as a secret.

If you save the key to a file yourself (the raw-API convention is `~/.monofile/credentials.json`, a different file from the CLI's), restrict it:

```bash title="Terminal"
chmod 600 ~/.monofile/credentials.json
```

## What a key is bound to

A key fixes four things at creation:

| Binding | Meaning |
|---|---|
| Workspace | Exactly one: the owner's personal workspace, or one organization. Nothing else is reachable. |
| Folder scope | Optional. Unset means the whole workspace; set means one folder subtree and nothing outside it. |
| Scopes | The set of permissions the key holds. See [[Scopes]]. |
| Expiry | Optional. After it passes, the key stops working and every call answers `401`. |

> [!IMPORTANT]
> The workspace and the folder scope come from the key, and no header can widen them. An organization key reaches its organization with no extra header. Monofile reads the optional `X-Monofile-Org-Id` header as an assertion only. If it names a workspace the credential does not grant, the request fails with `403` and `ORG_MISMATCH`; that includes an organization header sent with a personal key. There is no folder hint header; folder scope comes from the key row.

A folder-scoped key behaves as though the workspace were just that folder:

- `ls`, `tree`, `find` and `grep` only see files inside it
- `read` only opens files inside it
- `write` and `mkdir` only create inside it
- anything addressed outside it returns `OUT_OF_FOLDER_SCOPE`

For the full shell, Monofile checks folder scope against what a command changed, not against the command text, so a script cannot write its way out.

## Inspecting a key

When you do not know what a key can do, ask it:

```http
POST /api/tools/get_key_info
{}
```

```bash title="Terminal"
curl -s -X POST "https://www.monofile.ai/api/tools/get_key_info" \
  -H "Authorization: Bearer $MONOFILE_API_KEY" \
  -H "Content-Type: application/json" -d '{}' | jq -r '.content[0].text' | jq .
```

```json nocopy
{
  "workspace": { "type": "organization", "orgId": "org_abc123" },
  "folderScope": "/projects/alpha",
  "scopes": ["files:read", "files:write", "shares:read"],
  "userId": "user_abc123"
}
```

`folderScope` is `null` when the key can reach the whole workspace.

## Rotating and revoking

A key's secret never changes, so there is no in-place rotation. Rotation is mint, switch, delete.

:::steps
### Mint the replacement
Create a new key with the same workspace, folder and scopes.

### Switch the consumer
Update whatever holds the credential and confirm it works with `get_key_info`.

### Delete the old key
Revoke it from the app or over the API, as below.
:::

Revoking is immediate and permanent.

:::tabs
:::tab Human
In the app, delete the key from `/api-keys`.
:::
:::tab Agent
```http
DELETE /api/keys/<keyId>
```

```bash title="Terminal"
curl -s -X DELETE "https://www.monofile.ai/api/keys/<keyId>" \
  -H "Authorization: Bearer $MONOFILE_API_KEY"
```
:::
:::

```http
GET /api/keys
```

`GET /api/keys` lists your keys as metadata: id, name, prefix, scopes, workspace, folder, expiry and last use. The response contains no plaintext keys. A key may delete any of its owner's keys, including itself, so the session that discovers a compromise can revoke the credential at once.

> [!TIP]
> Mint one key per consumer so you can revoke precisely, and give it the narrowest scopes that do the job. Add a folder scope when the work lives in one place, and set an expiry on anything long-lived.

## Next steps

:::cards
- [[Scopes]] — Every scope, what it unlocks, and the presets.
- [[Calling Tools]] — The one-endpoint pattern, the MCP-shaped envelope, and the index of every tool.
- [[Registering an Agent]] — Self-serve agent identities, what they can do, and the rate limit.
- [[Using the API]] — Base URLs, the request and response envelope, errors, and rate limits.
:::
