# Authenticating to Lumbox (Agent Guide)

> How an AI agent obtains credentials and calls the Lumbox API or MCP server. Lumbox supports two mechanisms: a static API key (simplest) and OAuth 2.1 with PKCE (for delegated, scoped access). The machine-readable metadata is linked at the bottom.

## TL;DR

- REST API base: `https://api.lumbox.co/v1`
- Send `X-API-Key: <key>` on every request (or `Authorization: Bearer <key>`).
- Get a key at `https://app.lumbox.co/settings/api-keys` (free, no card).
- Hosted MCP server (OAuth): `https://mcp.lumbox.co/mcp`
- Protected-resource metadata: `https://lumbox.co/.well-known/oauth-protected-resource`
- Authorization-server metadata: `https://lumbox.co/.well-known/oauth-authorization-server`

## Option A — API key (recommended for most agents)

1. Sign up at `https://app.lumbox.co/signup` and verify your email.
2. Create an API key at `https://app.lumbox.co/settings/api-keys`.
3. Call the API:

```bash
curl https://api.lumbox.co/v1/inboxes \
  -H "X-API-Key: $LUMBOX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"github-bot"}'
```

The same key works for the stdio MCP server:

```bash
LUMBOX_API_KEY=<key> npx -y @lumbox/mcp-server
```

## Option B — OAuth 2.1 (delegated, scoped access)

Use this when an agent acts on behalf of a Lumbox user, or to connect the hosted MCP server.

- Authorization endpoint: `https://api.lumbox.co/oauth/authorize`
- Token endpoint: `https://api.lumbox.co/oauth/token`
- Dynamic client registration: `https://api.lumbox.co/oauth/register`
- Revocation: `https://api.lumbox.co/oauth/revoke`
- Grants: `authorization_code` (with PKCE `S256`) and `refresh_token`. Client-credentials is available for machine-to-machine agents.
- Scopes: `inbox:read`, `inbox:write`, `email:read`, `email:send`, `domain:manage`.

### Autonomous discovery flow

1. Call any protected API path without credentials. The server replies `401` with:
   `WWW-Authenticate: Bearer resource_metadata="https://lumbox.co/.well-known/oauth-protected-resource"`.
2. Fetch that protected-resource document to learn the `authorization_servers`.
3. Fetch `https://lumbox.co/.well-known/oauth-authorization-server` for the endpoints and `code_challenge_methods_supported`.
4. (Optional) Register a client at the `registration_endpoint`.
5. Run the authorization-code + PKCE flow, exchange the code at the token endpoint, and call the API with `Authorization: Bearer <access_token>`.

### Connecting the hosted MCP server

```bash
claude mcp add --transport http lumbox https://mcp.lumbox.co/mcp
```

The MCP server advertises its own protected-resource metadata at `https://mcp.lumbox.co/.well-known/oauth-protected-resource` and runs the same OAuth flow.

## Scopes reference

| Scope          | Grants                                          |
|----------------|-------------------------------------------------|
| `inbox:read`   | List and read inbox metadata                    |
| `inbox:write`  | Create, update, delete inboxes                  |
| `email:read`   | Read received email and parsed data, long-poll  |
| `email:send`   | Send, reply, forward, bulk-send                 |
| `domain:manage`| Add and verify custom domains                   |

## Errors and rate limits

- Errors return JSON `{ "error": "<message>" }` with the matching HTTP status.
- `401` means missing/invalid credentials (see the `WWW-Authenticate` header).
- Rate limit: 120 req/min. Responses carry `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`; over-limit returns `429 { "error": "...", "retry_after_seconds": N }`.

## Pick a method

| Method | Identity type | When to use | How |
|--------|---------------|-------------|-----|
| API key | `anonymous` (credential: `api_key`) | Most agents; fastest path | Create a key, send `X-API-Key: ak_...` on every request |
| OAuth 2.1 + PKCE | `identity_assertion` (credential: `oauth_access_token`) | Acting on behalf of a Lumbox user | Authorization-code + PKCE flow (Option B above) |
| Client credentials | `identity_assertion` | Machine-to-machine, no user | `POST /oauth/token` with `grant_type=client_credentials` |
| Dynamic registration | `anonymous` | Agent has no client yet | `POST /oauth/register` to mint a client, then run a flow above |

The advertised `agent_auth` endpoints (`register_uri`, `claim_uri`, `revocation_uri`) map to `https://api.lumbox.co/oauth/register`, `/oauth/token`, and `/oauth/revoke`.

### Concrete template — bootstrap a client (email-only agent, no prior credential)

```http
POST https://api.lumbox.co/oauth/register
Content-Type: application/json

{
  "client_name": "my-email-agent",
  "redirect_uris": ["https://example.com/callback"],
  "token_endpoint_auth_method": "none",
  "contacts": ["agent@example.com"]
}
```

The response returns a `client_id`. Then claim a token:

```http
POST https://api.lumbox.co/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials&client_id=<client_id>&scope=inbox:write email:read
```

Use the returned `access_token` as `Authorization: Bearer <token>`. The simplest path remains: sign up at https://app.lumbox.co/signup and create an `ak_...` key for `X-API-Key`.

## Machine-readable metadata

- OpenAPI: `https://lumbox.co/openapi.json`
- Authorization server: `https://lumbox.co/.well-known/oauth-authorization-server`
- Protected resource: `https://lumbox.co/.well-known/oauth-protected-resource`
- API catalog: `https://lumbox.co/.well-known/api-catalog`
- MCP server card: `https://lumbox.co/.well-known/mcp/server-card.json`
