> ## Documentation Index
> Fetch the complete documentation index at: https://docs.emiti.fravelabs.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Autenticación

> API keys para tus integraciones, JWT para el panel.

El API acepta dos mecanismos de autenticación. Elegí el que corresponda al caso:

* **API keys (`Authorization: ApiKey`)** — para integraciones máquina-a-máquina: ERPs, POS, scripts, webhooks. Es el mecanismo que vas a usar en el 95 % de los casos.
* **JWT (`Authorization: Bearer <token>`)** — es el token que emite el panel de e-Miti cuando iniciás sesión. Sólo lo usa la aplicación web del panel para consumir el API en tu nombre. No lo generes vos: se emite y refresca automáticamente durante el uso del panel.

Ambos mecanismos van en el header estándar `Authorization`. Si el header falta o el scheme es desconocido, el API devuelve `401`.

## API keys

### Generar una key

1. Iniciá sesión en el panel ([emiti.fravelabs.com](https://emiti.fravelabs.com)).
2. Andá a **Configuración → API Keys**.
3. Hacé clic en **Crear API Key**, ponele un nombre descriptivo (`erp-staging`, `pos-tienda-1`, etc.).
4. **Copiá la clave que aparece en el modal**. Empieza con el prefijo `emiti_k_`.

<Warning>
  La clave se muestra **una sola vez**. Guardala en tu gestor de secretos (AWS Secrets Manager, HashiCorp Vault, etc.). Si la perdés tenés que generar otra — la BD guarda sólo un hash, no el valor original.
</Warning>

También podés crearla desde el API con un JWT de administrador de tu tenant:

```bash theme={null}
curl -X POST https://api.emiti.fravelabs.com/v1/admin/api-keys \
  -H "Authorization: Bearer <tu-jwt>" \
  -H "Content-Type: application/json" \
  -d '{"nombre": "erp-produccion"}'
```

Response (la key en claro sólo aparece acá):

```json theme={null}
{
  "id": "01HXY...",
  "nombre": "erp-produccion",
  "prefix": "emiti_k_aBcD123",
  "key_plain": "emiti_k_aBcD123EfGhIjKlMnOpQrStUv",
  "created_at": "2026-07-01T14:32:11-03:00"
}
```

### Usarla en un request

Mandá la clave en el header `Authorization` con scheme `ApiKey` (case-insensitive):

```bash theme={null}
curl https://api.emiti.fravelabs.com/v1/de/01HXY4Z8W2Q5C7T3F9M8N6K2VB \
  -H "Authorization: ApiKey emiti_k_aBcD123EfGhIjKlMnOpQrStUv"
```

El formato es `Authorization: ApiKey <clave>`. El scheme `ApiKey` (así, con mayúscula A y K) es el canónico, aunque el parsing es case-insensitive.

Si la clave es inválida o falta, recibís 401 con este shape:

```json theme={null}
{
  "error": {
    "codigo": "AUTH_APIKEY_INVALIDA",
    "mensaje": "API Key no reconocida o revocada.",
    "request_id": "01HXY4Z..."
  }
}
```

### Alcance

* Las API keys operan sobre **tu tenant únicamente**. Cualquier request a recursos de otro tenant devuelve 404 (no filtramos por 403 para no confirmar la existencia).
* Los endpoints administrativos (`/v1/admin/tenants/*`) **no** son accesibles con API key — requieren JWT con rol de superadmin.

### Rotación y expiración

* Podés setear `expires_at` al crear la clave para que caduque automáticamente. Después de esa fecha, todos los requests reciben 401.
* Para rotar sin downtime: creá la nueva key, actualizala en tu servicio, y **después** revocá la vieja.

### Revocar una key

Desde el panel: **Configuración → API Keys → Revocar**. Toma efecto inmediato — el próximo request con esa clave recibe 401.

Desde el API:

```bash theme={null}
curl -X DELETE https://api.emiti.fravelabs.com/v1/admin/api-keys/{id} \
  -H "Authorization: Bearer <tu-jwt>"
```

La revocación es un soft-delete: la key queda en BD para auditoría (podés ver `last_used_at` para saber hasta cuándo se usó), pero deja de autenticar requests.

## JWT (uso del panel)

Cuando iniciás sesión en el panel, e-Miti emite un JWT firmado por Cognito y lo usa para todos los requests que hace en tu nombre. No hace falta que lo manejes vos.

Si consumís el API desde tu propia integración, **usá una API key**. El flujo JWT no está pensado para uso programático directo: los tokens caducan en 1 hora y su renovación es responsabilidad del cliente Cognito.

## Shape del context inyectado

Cuando un request llega autenticado, el API sabe:

| Campo        | Origen | Descripción                                                                           |
| ------------ | ------ | ------------------------------------------------------------------------------------- |
| `tenant_id`  | ambos  | UUID interno de tu tenant. Multi-tenant: todas tus queries se filtran por este valor. |
| `tenant_ruc` | ambos  | RUC-DV (ej. `80012345-0`) — denormalizado para logs.                                  |
| `role`       | JWT    | `admin`, `user` o `superadmin`. Con API key, siempre es `user`.                       |
| `auth_via`   | ambos  | `jwt` o `api_key`. Los endpoints de admin exigen `jwt`.                               |

No necesitás manejar estos campos en tu integración — el API los usa internamente para autorización y auditoría.
