# Authentication

> Create an API key in Settings → API, choose its permissions, and keep it backend-only.

Product: Clad API
Source: https://docs.useclad.ai/api/authentication

---

The API authenticates with **API keys** you create in **Settings → API**. A key
is scoped to one workspace and carries a fixed set of permissions. Keys look
like `clad_mk_...` and are passed as a Bearer token:

```http
POST /graphql HTTP/1.1
Host: clad-server-production.up.railway.app
Authorization: Bearer clad_mk_xxxxxxxxxxxxxxxxxx_...
Content-Type: application/json
```

### Creating a key

In Clad, go to **Settings → API** (org admins only), then:

1. Enter a **key name** — a label so you can recognize it later (e.g.
   `Production backend`).
2. Pick its **permissions**:
   - **Full access** — read and write everything this workspace exposes over the
     API, including admin-only settings.
   - **Read-only** — fetch issues, contacts, accounts, articles, and more, but
     make no changes.
   - **Custom** — grant exactly the scopes you need (see
     [Scopes & permissions](#scopes--permissions)).
3. Click **Create key** and copy the `clad_mk_...` secret immediately — it is
   shown **exactly once**. Store it in your backend secret manager.

Use the key from server-side code only. Never expose it in a browser, mobile
app, or public repo. Revoke a key anytime from the same page; integrations using
it stop working immediately.

> You don't create a "user" for the key — Clad manages the underlying API
> principal for you. You just name the key and choose its permissions.

### Creating keys programmatically

Org admins can also mint keys with the `createApiKey` mutation using an
admin-scoped key. `machineUserId` is the API principal a key is attached to; call
`machineUsers` to list existing ones or `createMachineUser` to make a new one for
grouping keys by system.

```graphql
mutation CreateKey($input: CreateApiKeyInput!) {
  createApiKey(input: $input) {
    apiKey { id keyPrefix scopes }
    secret   # returned once — store it now
    error { code message }
  }
}
```

```json
{
  "input": {
    "machineUserId": "<machine-user-id>",
    "name": "Production backend",
    "scopes": ["issues:read", "issues:write", "thread:reply"]
  }
}
```

Revoke a compromised key immediately with `revokeApiKey(id)`.

### Legacy keys

Existing REST `/v1` keys (`clad_live_...`) also authenticate against GraphQL,
but they are bridged to a single `issues:create` scope — they can call
`createIssue` and nothing else. To do more, mint a `clad_mk_...` key with
explicit scopes.
