
# Descargar una exportación de datos de usuarios

`GET /v1/jobs/user-exports/{job_id}/download` · permiso `users:export`

Genera un enlace de un solo uso para el paquete de una [exportación de datos de usuario](/docs/api/management/users/export) completada. Cada llamada escribe un registro `user_export.downloaded` en el registro de auditoría de gestión antes de emitir el enlace.

## Solicitud

| Parámetro | En | Obligatorio | Descripción |
|---|---|---|---|
| `job_id` | path | sí | ID del trabajo, con el prefijo `job_`. |

Un trabajo creado con `include_ip: true` también requiere `audit-events:read_ip` en la credencial que descarga.

## Respuesta

`302 Found` con un cuerpo vacío. `Location` es un enlace relativo en el mismo host, `/downloads/user-exports/{environment_id}/{job_id}/{token}`. La respuesta incluye `Cache-Control: no-store` y `Referrer-Policy: no-referrer`.

- El enlace es válido durante 15 minutos y funciona una sola vez: el token se consume en la primera solicitud, aunque la transferencia se interrumpa. Vuelva a llamar a esta operación para obtener un enlace nuevo.
- El enlace no requiere credenciales; el token es la única credencial. Mantenga `Location` en secreto y no lo registre en logs.
- El archivo está cifrado en reposo con la clave del entorno, por lo que no se usa una URL prefirmada de almacenamiento; KeenAuth lo descifra y lo transmite.

Seguir el enlace con `GET` devuelve `200 OK` con `Content-Type: application/zip`, `Content-Length` y `Content-Disposition: attachment; filename="user-export-job_….zip"`. `HEAD` se rechaza con `405` para que las vistas previas de enlaces no consuman el token. Compare el SHA-256 del archivo con `file.sha256` del trabajo. Si la conexión termina antes de recibir los bytes de `Content-Length`, el paquete está incompleto; descártelo y solicite un enlace nuevo. Un enlace no válido, usado o vencido devuelve `404 not_found`.

## Errores

Cada error es un cuerpo `application/problem+json` con un `code` estable.

| HTTP | `code` | Cuándo |
|---|---|---|
| 401 | `unauthenticated` | La clave de API falta, no es válida o fue revocada. |
| 403 | `insufficient_permissions` | La clave no tiene `users:export`, o el trabajo se creó con `include_ip` y la clave no tiene `audit-events:read_ip` (`required_permissions` enumera ambos). |
| 404 | `not_found` | El trabajo no existe, pertenece a otro entorno o el ID está mal formado. En el enlace: el token no es válido, ya se usó o venció. |
| 409 | `conflict` | El trabajo aún no está completado, o su archivo venció. |
| 429 | `rate_limited` | Se superó el límite de tasa; respete `Retry-After`. El propio enlace permite 10 solicitudes por minuto por dirección IP. |
| 503 | `service_unavailable` | Una dependencia no está disponible temporalmente; reintente más tarde. |

## Ejemplo

```bash
curl -L -o user-export.zip \
  https://api.eu.keenauth.com/v1/jobs/user-exports/job_01j9xk3m7q8r2s4t6v8w0y2z4e/download \
  -H "Authorization: Bearer $KEENAUTH_SECRET_KEY"
```

El CLI sigue el enlace por sí mismo, escribe el paquete en un archivo (nunca en la salida estándar), se niega a sobrescribir un archivo existente e imprime el tamaño y el SHA-256 de lo que escribió:

```bash
keenauth jobs user-exports download job_01j9xk3m7q8r2s4t6v8w0y2z4e --file user-export.zip
```

## Datos personales

Este endpoint contiene datos personales: perfil del usuario final. [Datos personales en las API de KeenAuth](/docs/policies/personal-data) describe qué se almacena, durante cuánto tiempo se conserva y cómo se elimina. No envíe categorías especiales de datos personales (salud, datos biométricos, religión, opiniones políticas, orientación sexual) en ningún campo.
