# Authentication

_Last updated: July 7, 2026_

Waydock's MCP server authenticates with **per-user bearer API keys**, not OAuth. Each user issues and revokes their own keys, each key carries an explicit scope set, and every call is audited. New here? Start with the [Quickstart](/docs/quickstart).

> **For agents:** send `Authorization: Bearer wdmcp_...` on every request to `https://waydock.ai/api/mcp/stream`. Waydock does **not** run an OAuth authorization server for MCP, so there is no `/.well-known/oauth-authorization-server` and no dynamic client registration. The machine-readable version of this page is [/auth.md](/auth.md).

## The key

A Waydock MCP key looks like this:

```text
wdmcp_a1b2c3d4_9f8e7d6c5b4a39281706f5e4d3c2b1a0
```

The `wdmcp_` prefix, a short public segment, and a long random secret. The key is shown **once** at creation. Waydock stores only a SHA-256 hash of it, never the key itself, and verifies with a constant-time comparison.

## Issuing a key

1. Sign in and open **Settings → Account → MCP** ([/settings/account/mcp](/settings/account/mcp)).
2. Click **Create key** and choose a scope preset (**Read & email myself** or **Full access**) or a custom scope set. See [Scopes & presets](/docs/tools#the-scope-catalog).
3. Name the key after the agent that will use it (for example `claude-desktop`, `cursor`, `nightly-brief-bot`). The name appears in your audit log next to every call.
4. Copy the key. It is not shown again.

You can hold up to **3 live keys on Free** and **5 on Pro**. New keys are read-only by default.

## Sending the key

Pass the key as a bearer token on every MCP request:

```text
Authorization: Bearer wdmcp_xxxxxxxx
```

The `X-API-Key: wdmcp_xxxxxxxx` header is also accepted. Keys created before a past rename may start with the legacy `ddmcp_` prefix; those still authenticate.

## Optional restrictions per key

Each key can be locked down further, all enforced at authentication time:

- **Expiry.** Set an expiry date; the key stops authenticating the moment it passes.
- **IP allowlist.** Restrict a key to one or more CIDR ranges. A call from an address outside the list is rejected before any tool runs.
- **Tool denylist.** Block specific tools for a key regardless of its scopes. Useful to hand an agent broad read scopes but withhold, say, `waydock_send_email`.

## Lifecycle

- **Rotate.** Generate a fresh secret for an existing key without changing its id or scopes. The old secret stops working immediately, and the new one is shown once. Use this if a key may have leaked.
- **Revoke.** Delete a key instantly. Because the app UI and the MCP endpoint read the same key record, revoking stops both in the same moment.
- **History.** Every key keeps a change log (create, update, rotate, revoke, re-consent), and every call is written to the audit log with the agent name, tool, outcome, and latency.

## Re-consent when scopes are added

Each key is stamped with the scope **catalog version** it was created under. When Waydock adds new optional scopes to the catalog, an existing key does **not** silently gain them. The key is flagged as pending re-consent, and the owner explicitly acknowledges the new version to pick up any new scopes they want. Existing grants are never changed without the owner's action.

## Rate limits and idempotency

- **Daily call ceiling** follows the plan: **500 per day on Free, 100,000 on Pro**, plus a per-IP window. Call `waydock_quota` (no scope required) for your remaining budget.
- **Idempotency.** Send an `Idempotency-Key` header (or `X-Idempotency-Key`) on a write request and Waydock returns the cached response for a repeat of the same key, so a retried send does not fire twice.

## Discovery endpoints

| Endpoint | Auth | Purpose |
| --- | --- | --- |
| `GET /.well-known/mcp/server-card.json` | public | Server discovery card |
| `GET /api/mcp/manifest` | public | Full tool + scope catalog |
| `GET /auth.md` | public | This authentication guide, as Markdown |
| `GET /api/mcp/health` | key | Liveness |
| `GET /api/mcp/whoami` · `/key_info` · `/quota` | key | Identity, key details, budget |

## Security properties

- Keys are stored as a **SHA-256 hash**, never in plaintext, and compared in constant time.
- Outbound send is **wildcard-proof**: a key cannot send to third parties unless its scope list contains the literal `write:mail.send`. No preset or wildcard satisfies it.
- Every call is scope-checked and, for paid write scopes, entitlement-checked at call time.
- All access is logged to one audit trail shared by the app and the agent endpoint.

## See also

- [Quickstart](/docs/quickstart) for client configs
- [Tool reference](/docs/tools) for tools, scopes, and presets
- [Security](/security) for the outbound-safety contract
