# auth.md

Questo documento dice a un agente come autenticarsi su Sending, quali credenziali
esistono e che permessi portano. Il workspace non e' mai un parametro della
richiesta: viene sempre derivato dalla credenziale.

Ci sono due strade, e servono a due cose diverse.

## 1. API key · accesso a un workspace

Per uso server-to-server e per l'API REST v1. La key si crea dalla dashboard in
*Impostazioni › API Keys*, si vede in chiaro solo alla creazione e porta gli scope
scelti in quel momento.

```http
Authorization: Bearer sk_...
```

- Base URL: `https://sending.dev/api/v1`
- Descrizione macchina: [OpenAPI 3.1](https://sending.dev/api/v1/openapi.json)
- Documentazione: [Autenticazione](https://sending.dev/docs/authentication)

La stessa key vale anche sull'endpoint MCP, come alternativa a OAuth.

## 2. OAuth 2.1 · accesso per conto di un utente

E' la strada dei client MCP. Siamo insieme authorization server e resource server.

- Resource: `https://sending.dev/api/mcp`
- Protected Resource Metadata (RFC 9728): [`/.well-known/oauth-protected-resource`](https://sending.dev/.well-known/oauth-protected-resource)
- Authorization Server Metadata (RFC 8414): [`/.well-known/oauth-authorization-server`](https://sending.dev/.well-known/oauth-authorization-server)
- Issuer: `https://sending.dev`
- Registrazione dinamica del client (RFC 7591): `https://sending.dev/api/auth/mcp/register`
- Grant: `authorization_code` con PKCE `S256`, piu' `refresh_token`
- Il token va nell'header: `Authorization: Bearer <access_token>` (`bearer_methods_supported: ["header"]`)

```agent_auth
skill: mcp
register_uri: https://sending.dev/api/auth/mcp/register
authorization_uri: https://sending.dev/api/auth/mcp/authorize
token_uri: https://sending.dev/api/auth/mcp/token
methods:
  - type: dynamic_client_registration
    spec: RFC 7591
    uri: https://sending.dev/api/auth/mcp/register
  - type: authorization_code
    pkce: S256
    uri: https://sending.dev/api/auth/mcp/authorize
```

### I permessi non arrivano dalla richiesta di authorize

Vale la pena leggerlo prima di aprire una issue: i client MCP non conoscono il
nostro catalogo di scope e in `authorize` chiedono quasi sempre i soli scope OIDC
(`openid`, `profile`, `email`, `offline_access`), che infatti sono gli unici
elencati in `scopes_supported`.

I permessi effettivi li sceglie **l'utente** nella schermata di consenso, dove vede
il catalogo completo, e restano modificabili da *Connessioni MCP* senza dover
ricollegare il client. Quindi un token con i soli scope OIDC puo' avere pieno
accesso agli strumenti, e viceversa chiedere uno scope non lo garantisce.

Catalogo assegnabile: `automations`, `campaigns`, `commerce`, `contacts`,
`domains`, `email`, `events`, `inbox`, `integrations`, `messages`, `utm`,
`webhooks`, nelle forme `:read`, `:write` o `:send` secondo l'area, piu' `*`
per l'accesso completo.

### Registrazione autonoma dell'agente: non supportata

Per essere espliciti ed evitare attese inutili: **non** implementiamo il protocollo
di registrazione agenti di auth.md. Non esistono `identity_endpoint`,
`claim_endpoint` ne' `events_endpoint`, e la metadata OAuth non pubblica un blocco
`agent_auth`: un agente non puo' creare da solo un account Sending.

Serve sempre un umano che apra un workspace; da li' in poi l'agente e' autonomo,
con una API key o con OAuth. La registrazione dinamica su
`/api/auth/mcp/register` registra un **client OAuth** (RFC 7591), non un account.

## Cosa aspettarsi quando manca qualcosa

- Credenziale assente o non valida: `401`.
- Credenziale valida ma senza lo scope richiesto dal tool o dalla route: `403 forbidden`.
- Oltre la quota del piano: `402`, con l'indicazione del limite raggiunto.

Gli invii reali sono soggetti a guardrail server-side (dominio verificato,
suppression list, idempotenza obbligatoria, quota del piano) che valgono uguali
per API key e OAuth: nessuna delle due li aggira.

## Altre risorse di discovery

- Catalogo API: [`/.well-known/api-catalog`](https://sending.dev/.well-known/api-catalog)
- MCP Server Card: [`/.well-known/mcp/server-card.json`](https://sending.dev/.well-known/mcp/server-card.json)
- Prompt completo REST + MCP: [`/llms-full.txt`](https://sending.dev/llms-full.txt)
