# Autenticación

> Clave pública con orígenes permitidos para el navegador, clave secreta para tu servidor.

Cada pedido lleva la clave en la cabecera `Authorization`. Nunca la pongas en la URL: quedaría en historiales y registros.

```http
GET /api/v1/catalogo HTTP/1.1
Host: turnovapp.com
Authorization: Bearer tnv_pk_TU_CLAVE_PUBLICA
```

## Clave pública (navegador)

- Va a la vista de cualquiera en el JavaScript de tu sitio: por eso solo da acceso a lo que tu página de reservas ya muestra, y a crear reservas.
- Funciona solo desde los **orígenes permitidos** de la clave. El servidor compara la cabecera `Origin` antes de ejecutar nada: un pedido desde otro origen, o sin `Origin`, responde `403 ORIGEN_NO_PERMITIDO`.
- Los orígenes se cargan como `https://dominio` (sin camino). Se acepta `http://` solo para `localhost` y `127.0.0.1`.
- No puede leer reservas ya hechas: eso trae datos de la clienta.

### CORS

El navegador manda primero un preflight `OPTIONS` sin la clave. Turnova responde `204` con `Access-Control-Allow-Origin` igual a tu origen exacto (nunca `*`) si ese origen está cargado en alguna clave pública activa, y `403` sin cabeceras CORS si no. Las cabeceras permitidas son `Authorization`, `Content-Type` e `Idempotency-Key`; se expone `Retry-After`. No se usan cookies.

## Clave secreta (servidor)

- Guardala en una variable de entorno de tu servidor y no la mandes nunca al navegador.
- Si un pedido con clave secreta trae cabecera `Origin` (es decir, sale de un navegador), responde `403 CLAVE_SECRETA_EN_NAVEGADOR`.
- Es la única que puede tener el permiso `reservas:leer`.

```js
// Node 18+ (Next.js route handler, Express, etc.)
const res = await fetch("https://turnovapp.com/api/v1/reservas/" + compraId, {
  headers: { Authorization: `Bearer ${process.env.TURNOVA_CLAVE_SECRETA}` },
});
```

## Plan del negocio

La API funciona mientras el negocio tenga el plan Enterprise. Si cambia a otro plan, las claves no se borran, pero todo pedido responde `403 PLAN_SIN_API` con `upgrade_url` hasta que vuelva a Enterprise.

## Errores de acceso

| HTTP | Código | Qué pasó |
| --- | --- | --- |
| 401 | `CREDENCIAL_FALTANTE` | Mandá la clave en Authorization: Bearer <clave>. |
| 401 | `CREDENCIAL_INVALIDA` | La clave no es válida. |
| 401 | `CREDENCIAL_REVOCADA` | La clave fue revocada por el negocio. |
| 403 | `CLAVE_SECRETA_EN_NAVEGADOR` | La clave secreta es solo para servidores: desde el navegador usá la clave pública. |
| 403 | `ORIGEN_NO_PERMITIDO` | Este sitio no está autorizado para usar la clave. |
| 403 | `SCOPE_FALTANTE` | La clave no tiene permiso para esta operación. |
| 403 | `PLAN_SIN_API` | La API está incluida en el plan Enterprise. El negocio puede cambiar de plan desde su panel. |
