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

# Authentication and API keys

> Create, scope, store and revoke Darwin API keys: dk_live_ and dk_test_ prefixes, every scope and what it unlocks, and where a secret key must never go.

<div className="darwin-location"><strong>Find it in Darwin</strong> Profile menu → Workspace settings → API <a href="https://app.meetdarwin.ai/admin/settings/api">Open this screen ↗</a></div>

Darwin authenticates every API call with a secret key sent as a bearer token. A key belongs to one workspace, carries a fixed set of scopes, and works until you revoke it.

```http theme={null}
Authorization: Bearer dk_live_...
```

## Kinds of key

| Prefix | What it is | Where it comes from |
| - | - | - |
| `dk_live_` | A secret key for a real workspace | **Settings → API → Create key** |
| `dk_test_` | A secret key for Darwin's demonstration (sandbox) workspace, so a key pasted into the wrong place is obvious. **Settings → API** marks it **Test**. | **Settings → API → Create key** in that workspace |
| `dko_` | A one-hour access token Darwin gives an AI app you connected over [MCP](/api-reference/mcp) | The app's sign-in; you never handle it |

A workspace can have 25 active secret keys. Revoke keys you no longer use to make room.

## Create a key

Owners and admins create keys in **Settings → API → Create key**. Members can see the list but not change it.

1. Enter a **Name** that says where the key is used.
2. Choose **Access**: **Read only** grants every read scope, **Full access** grants every scope, **Choose** lets you tick scopes one by one.
3. Select **Create key** and copy the key from the dialog. Darwin shows it once and keeps only a fingerprint and its first characters.

The list then shows each key's name, its first characters (for example `dk_live_Ab3x…`), its access and when it was last used.

## Scopes

A key can do only what its scopes allow. A write scope includes its read: a key with `knowledge:write` can also read knowledge. Calling an endpoint without its scope returns `403` with the code [`insufficient_scope`](/api-reference/errors#insufficient_scope), and the error names the scope the call needs.

| Scope | Lets the key |
| - | - |
| `conversations:read` | Read conversations and transcripts. Names and emails on them need `contacts:read` too. |
| `contacts:read` | Read contacts, and names and emails on conversations and meetings |
| `contacts:write` | Create and update contacts |
| `meetings:read` | Read meetings booked from the chat |
| `analytics:read` | Read the funnel, pages, sources and conversation quality |
| `events:read` | Read the event log (`GET /events`). Without `contacts:read` too, each event shows only what happened and to which object; with it, the full payload, as webhooks carry. |
| `webhooks:write` | Create, change and delete webhook endpoints, read their delivery logs and redeliver events |
| `knowledge:read` | Read the pages and documents the agent answers from |
| `knowledge:write` | Add, refresh and remove knowledge pages and documents |
| `agent:read` | Read the agent's settings, appearance and chat buttons |
| `agent:write` | Change the agent's settings, appearance and chat buttons, and switch the chat on or off |
| `experiments:read` | Read opening tests, their variants and results |
| `experiments:write` | Pause, resume and promote tests, and propose variants |
| `privacy:write` | Erase or export everything held about one person |
| `chat:write` | Hold conversations with the agent through the [chat API](/api-reference/chat-api) |

`GET /me` and `GET /workspace` need no scope.

### Personal data stays behind contacts:read

A key for a dashboard can read conversations, meetings and numbers without seeing who anyone is. Without `contacts:read`:

* On conversations, `contact`, `lead.first_name`, `lead.last_name`, `lead.email` and `booking.booker_email` are `null`. `lead.captured_at` still tells you a lead was captured.
* On meetings, `contact` is `null` and `invitee.name` and `invitee.email` are `null`.

Transcripts (`expand[]=messages`) are what the visitor and the agent wrote. If a visitor typed personal details into a message, those words appear in the transcript.

## Check what a key can do

```bash theme={null}
curl https://api.meetdarwin.ai/v1/me -H "Authorization: Bearer $DARWIN_API_KEY"
```

The response lists the key's `scopes`, its `mode` (`live` or `test`) and the `workspace` id.

## Revoke a key

In **Settings → API**, select **Revoke** beside the key and confirm. Anything using it stops working at once, and this cannot be undone. Revoked keys stay in the list, marked **Revoked**, so you can see what was there.

To rotate a key without downtime, create the new key, deploy it, check **used** on the new key in the list, then revoke the old one.

A revoked, expired and mistyped key all return the same `401` [`invalid_api_key`](/api-reference/errors#invalid_api_key).

## Keep keys secret

A secret key reads personal data and can change your live chat. Treat it like a password.

<Warning>
  Never put a secret key in website code, a browser extension, a mobile app, a public repository, a URL or a support message. Anyone who can read the page can read the key.
</Warning>

* Keep keys in environment variables or a secrets manager, and call the API from your server.
* The chat on your website does not use a secret key. Its embed carries a **public site key**, which is safe in page source.
* To tell the chat who a signed-in visitor is, sign their email on your server with the **identity secret** and pass only the signature to the page. See [Identify signed-in visitors](/api-reference/browser-sdk#identify-signed-in-visitors).
* If a key leaks, revoke it in **Settings → API** first, then create a replacement.

## The workspace must be in good standing

If the workspace still has to finish adding a card, for example a paid plan was chosen at sign-up and checkout was never completed, every call returns `402` with the code [`payment_required`](/api-reference/errors#payment_required). The same screen that asks for the card in the Darwin admin clears it.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.