# Scopes y empresas (/docs/autenticacion/scopes)

## La tabla de scopes [#la-tabla-de-scopes]

| Scope                              | Concede                                                                                            |
| ---------------------------------- | -------------------------------------------------------------------------------------------------- |
| `documents:read`                   | Leer documentos emitidos, PDF, XML y eventos                                                       |
| `documents:write`                  | Emitir documentos, reintentar, enviar por correo                                                   |
| `received:read`                    | Leer los DTE recibidos de proveedores                                                              |
| `received:write`                   | Aceptar / reclamar / acusar recibo                                                                 |
| `empresas:read`                    | Leer empresas, puesta en marcha, configuración, folios                                             |
| `empresas:write`                   | Crear empresas, cargar certificados, cambiar configuración                                         |
| `folios:write`                     | Solicitar CAF al SII, cargar CAF                                                                   |
| `tax:read`                         | RCV, propuestas y declaraciones de F29, sugerencias                                                |
| `tax:write`                        | Caracterizar, declarar F29, confirmar sugerencias, ingresar gastos                                 |
| `webhooks:read` / `webhooks:write` | Endpoints de webhook y replay de eventos                                                           |
| `usage:read`                       | Libro de consumo                                                                                   |
| `keys:write`                       | Mintear, rotar y revocar llaves de API. Solo llaves root; nunca combinado con los scopes de arriba |

Si falta un scope recibes `403 insufficient_scope`, con el scope requerido nombrado en
`error.message`. No tienes que adivinar cuál era.

### El set de arranque [#el-set-de-arranque]

La primera llave de una cuenta se mintea con estos seis, que son exactamente lo que recorre el
[quickstart](/docs/empezar/quickstart) de punta a punta:

```
documents:read, documents:write, empresas:read, empresas:write, webhooks:read, webhooks:write
```

Ni uno más. `keys:write` queda fuera porque es el poder de una llave root, y los cuatro scopes de la
puesta en marcha quedan fuera porque conceden actos con efecto legal.

### Los scopes de la puesta en marcha [#los-scopes-de-la-puesta-en-marcha]

Cuatro scopes estrechos gobiernan los actos que autorizan a Facturia ante el SII (disponibles desde
v1.1). **Ninguno entra en el set de arranque, ni por defecto ni por conveniencia**, y se piden uno
por uno:

| Scope               | Concede                                                                                                                                                                                                                                                                                       |
| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `mandato:write`     | Acuñar el enlace de firma del mandato y leerlo (`GET …/mandato`)                                                                                                                                                                                                                              |
| `mandato:attest`    | Postear una aceptación **con cuerpo** (el integrador recogió la firma en su propio flujo; queda registrado como `acceptance_method: api`) y **revocar** el mandato con `DELETE …/mandato` — la revocación es el acto de mayor efecto del contrato y desde v1.1 no la concede `empresas:write` |
| `onboarding:write`  | Acuñar enlaces de pasos humanos, pedir una re-lectura, acuñar el enlace de aprobación de `go_live`, cargar el certificado                                                                                                                                                                     |
| `onboarding:attest` | Postear la autorización de `go_live` **con cuerpo**                                                                                                                                                                                                                                           |

`empresas:write` implica los dos scopes `:write` (`mandato:write`, `onboarding:write`) — así una
llave que ya existe sigue pudiendo acuñar el enlace de firma y los enlaces de los pasos humanos. &#x2A;*No
implica ninguno de los dos `:attest`**: esos se piden explícitamente o no se conceden nunca (ADR-0012
§4). Una llave con solo `empresas:write` que intenta `POST …/mandato` con cuerpo recibe `403
insufficient_scope: mandato:attest`, exactamente como si no tuviera ningún scope de la puesta en
marcha. La diferencia entre `:write` y `:attest` es la diferencia entre **pedirle a una persona que
apruebe** y **afirmar que ya aprobó en otra parte**: lo segundo es una atestación, se registra
visiblemente como tal, y por eso vive detrás de su propio scope que nunca se concede por implicación
ni por defecto. El camino completo está en [De sandbox a producción](/docs/empezar/produccion).

> **Trampa — Una llave root no puede leer documentos**
>
> `keys:write` no se combina con ningún otro scope. Una llave root (`sk_live_root_…` /
> `sk_test_root_…`) **no puede emitir, no puede leer documentos y no puede tocar datos tributarios**:
> su único poder es mintear y revocar otras llaves.
>
> Es la confusión más común al empezar: minteas la llave root, la pruebas contra `/v1/documents` y
> recibes un `403`. No está rota — está haciendo exactamente lo que debe. Mintea con ella una llave
> ordinaria y usa esa.

## Lista blanca de empresas [#lista-blanca-de-empresas]

Además de los scopes, cada llave lleva una lista de empresas:

* `["*"]` — toda empresa de la cuenta, incluidas las que se creen después.
* Una lista explícita de RUT — `["77928532-4", "78281439-7"]`.

Una llave con exactamente un RUT es un [token de empresa](/docs/empezar/conceptos#token-de-empresa)
y el header `Facturia-Empresa` se vuelve opcional.

Los dos ejes se aplican juntos: una llave con `documents:write` sobre `["77928532-4"]` puede emitir
para esa empresa y para ninguna otra. Nombrar otra empresa devuelve `403 empresa_not_allowed` — no un
`404`, porque ya conoces su RUT y fingir que no existe no protege a nadie.

## Combinaciones que conviene tener en la cabeza [#combinaciones-que-conviene-tener-en-la-cabeza]

| Forma                                  | Scopes                                     | Empresas                  | Para qué                                                     |
| -------------------------------------- | ------------------------------------------ | ------------------------- | ------------------------------------------------------------ |
| Backend de un producto propio          | `documents:*`, `received:*`, `tax:*`       | `["*"]`                   | Una sola llave que opera todas las empresas de la cuenta     |
| Llave por cliente (ERP, SaaS vertical) | lo mínimo que ese cliente necesita         | un solo RUT               | El sistema del cliente no puede direccionar nada más         |
| Solo lectura para BI o conciliación    | `documents:read`, `tax:read`, `usage:read` | `["*"]`                   | Una llave que no puede emitir aunque se filtre               |
| Root                                   | `keys:write`                               | según lo que va a delegar | Mintear y revocar llaves. Nada más                           |
| Exploración y demos                    | cualquiera, pero `sk_test_`                | cualquiera                | Una llave de test es un límite de capacidad, no una política |

## Modo de sesión: `Facturia-Mode` [#modo-de-sesión-facturia-mode]

La superficie `/dashboard/*` se autentica con un JWT de cuenta en vez de una llave `sk_`, porque un
navegador nunca debe sostener una llave `sk_`. Una sesión no tiene prefijo que cargue su modo, así
que el modo viaja en un header:

```
Facturia-Mode: test
```

Por defecto es `live`. El backend lo aplica exactamente igual que aplicaría el modo de una llave: en
modo live una empresa de sandbox no existe, y viceversa. Un valor no reconocido es un `400`, nunca
una caída silenciosa a `live`.

Dos reglas aplican a una sesión que no aplican a una llave:

* **Una sesión puede mintear llaves Y leer datos.** Una llave root no puede lo segundo. La diferencia
  es intencional: una llave root es una credencial delegada, y una sesión es el dueño de la cuenta en
  persona.
* **Una sesión de cuenta es la única credencial que mintea una llave root:**
  `POST /dashboard/api_keys` con `{"root": true}` (sin `scopes` ni `empresas`) devuelve una
  `sk_live_root_…` / `sk_test_root_…` sin abrir ningún panel. Una llave —root u ordinaria— que pide
  `root: true` recibe `403 privilege_escalation`: la delegación llega hasta un nivel y una llave root
  no mintea otra llave root. Ver [Llaves root y rotación](/docs/autenticacion/llaves-root).
