# Autenticación

Cada petición se autentica con una única **clave de API**. La envías como cabecera
`X-API-Key` — sin baile de OAuth, sin intercambio de tokens.
**Alcance de una clave de API:** Una clave de API da acceso únicamente al **servicio de subida de PDFs** — los endpoints
`/api/v1/upload-service/*` (subir, estado del trabajo, descargar, eliminar). Esa es toda la
superficie de procesamiento pública.

## Crear una clave de API

La forma habitual de obtener una clave es el **portal de Accessful**: inicia sesión, abre
**Claves de API** y crea una. La clave se muestra **una sola vez** al crearla — cópiala de
inmediato. Solo guardamos un hash, así que nunca podremos volver a mostrarla.

Una clave tiene este aspecto:

```
ak_oCe4cm015zL8vCbBne_wUZDcM6G1RWqD7Ekc2944EAA
```

- Prefijo `ak_` seguido de 43 caracteres seguros para URL.
- Puedes tener hasta **10 claves activas** por cuenta.
- Una clave puede llevar opcionalmente una **fecha de caducidad**; revócala cuando quieras desde el portal.
**Caution:** Trata la clave como una contraseña. Está vinculada a tu cuenta y puede subir, descargar y
**eliminar de forma permanente** tus casos. Nunca la incrustes en código de cliente que
distribuyas a los usuarios finales.

### Gestionar claves de forma programática (opcional)

Si automatizas la rotación de claves, los endpoints de gestión están en
`/api/v1/auth/api-keys` y requieren un **token bearer OAuth2** de tu inicio de sesión en el
portal (`Authorization: Bearer <jwt>`) — no una clave de API:

| Método &amp; ruta | Propósito |
| --- | --- |
| `POST /api/v1/auth/api-keys` | Crear una clave — la respuesta contiene el texto plano **una sola vez** |
| `GET /api/v1/auth/api-keys` | Listar tus claves (valores enmascarados) |
| `POST /api/v1/auth/api-keys/{id}/revoke` | Revocar una clave |
| `DELETE /api/v1/auth/api-keys/{id}` | Eliminar una clave |

## Enviar la clave en las peticiones

Añade la cabecera `X-API-Key` a cada llamada:

```bash
curl https://api.accessful.de/api/v1/upload-service/job-status/<caseId> \
  -H "X-API-Key: ak_tu_clave_aqui"
```
```js
await fetch(`https://api.accessful.de/api/v1/upload-service/job-status/${caseId}`, {
  headers: { 'X-API-Key': process.env.ACCESSFUL_API_KEY },
});
```
```java
HttpRequest.newBuilder()
    .uri(URI.create("https://api.accessful.de/api/v1/upload-service/job-status/" + caseId))
    .header("X-API-Key", System.getenv("ACCESSFUL_API_KEY"))
    .GET().build();
```
## Verificar tu clave

Haz una prueba rápida pidiendo un caso aleatorio e inexistente. Una clave que funciona
devuelve **404** (el caso no existe) — *no* 401.

1. Envía una petición de estado con un ID de caso desechable:

   ```bash
   curl -i https://api.accessful.de/api/v1/upload-service/job-status/00000000-0000-0000-0000-000000000000 \
     -H "X-API-Key: ak_tu_clave_aqui"
   ```

2. Lee la línea de estado:

   - **`404 Not Found`** → tu clave es aceptada. ✅
   - **`401 Unauthorized`** → falta la clave, está mal formada o ha sido revocada.

## Errores de autenticación

| Estado | Significado |
| --- | --- |
| `401 Unauthorized` | Sin clave, clave mal formada o una clave revocada/caducada. |
| `403 Forbidden` | La clave es válida pero no tiene permiso para esa acción. |

Una clave ausente o no válida (**401**) se rechaza en el **gateway**, antes de que la petición
llegue a la aplicación — por eso un 401 nunca lleva un cuerpo de [Problem Details](https://docs.accessful.de/es/errors/).
Fíate del código de estado. Un **403** procede de la propia aplicación y lleva un cuerpo de
Problem Details, como los demás errores de nivel de aplicación.