
# Listar usuarios

`GET /v1/users` · permiso `users:read`

Lista los usuarios del entorno con paginación por cursor, del más reciente al más antiguo de forma predeterminada. Aquí solo se aceptan filtros que no contienen datos personales. Para buscar usuarios por dirección de correo electrónico, número de teléfono o nombre de usuario, use [Buscar usuarios](/docs/api/management/users/search).

## Solicitud

| Parámetro | En | Obligatorio | Descripción |
|---|---|---|---|
| `limit` | query | no | Tamaño de página, de 1 a 100. Predeterminado 20. |
| `after` | query | no | Cursor opaco de `list_metadata.after`. Es excluyente con `before`. |
| `before` | query | no | Cursor opaco de `list_metadata.before`. Es excluyente con `after`. |
| `order` | query | no | `asc` o `desc` según la fecha de creación. Predeterminado `desc`. |
| `status` | query | no | `active`, `blocked` o `pending_deletion`. |
| `external_id` | query | no | Coincidencia exacta con su propio identificador. |
| `created_after` | query | no | Hora RFC 3339; usuarios creados después de ella. |
| `created_before` | query | no | Hora RFC 3339; usuarios creados antes de ella. |

Un cursor solo es válido con los mismos filtros y el mismo orden para los que se emitió; de lo contrario, la solicitud falla con `invalid_cursor`.

## Respuesta

`200 OK`. `data` contiene los usuarios de la página; `list_metadata.before` y `list_metadata.after` son cursores para la página anterior y la siguiente (`null` cuando no existe). No se devuelve el recuento total.

Los datos personales se enmascaran cuando la clave no tiene el permiso `users:read_pii`: `email` pasa a ser `a***@e***.com`, `phone_number` conserva solo sus últimos 2 dígitos (`+**********67`), `name`, `given_name`, `family_name`, `middle_name` y `nickname` pasan a ser iniciales (`A. L.`), `username` conserva solo su primer carácter (`a***`), `birthdate` pasa a ser `****-**-**` y `address` pasa a ser `{"redacted": true}`. `user_metadata` y `app_metadata` no se enmascaran.

```json
{
  "data": [ {
    "id": "usr_0a1b2c3d4e5f6g7h8j9k0m1n2p",
    "kind": "regular",
    "status": "active",
    "external_id": null,
    "username": null,
    "name": "Ada Lovelace",
    "email": "ada@example.com",
    "email_verified": true,
    "phone_number": null,
    "phone_verified": false,
    "user_metadata": {},
    "app_metadata": {},
    "created_via": "admin_api",
    "created_at": "2026-01-15T09:30:00Z",
    "updated_at": "2026-01-15T09:30:00Z",
    "last_sign_in_at": null,
    "deletion_requested_at": null,
    "deletion_due_at": null
  } ],
  "list_metadata": { "before": null, "after": "<opaque cursor>" }
}
```

## Errores

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

| HTTP | `code` | Cuándo |
|---|---|---|
| 400 | `invalid_cursor` | El cursor está mal formado, se ha manipulado o se emitió para otros filtros. |
| 422 | `validation_failed` | Un parámetro de consulta no es válido (`limit` fuera de rango, marca de tiempo incorrecta, parámetro repetido). |
| 401 | `unauthenticated` | La clave de API falta, no es válida o ha sido revocada. |
| 403 | `insufficient_permissions` | La clave no tiene el permiso `users:read`. |
| 429 | `rate_limited` | Se superó el límite de frecuencia; respete `Retry-After`. |
| 503 | `service_unavailable` | Una dependencia no está disponible temporalmente; reintente más tarde. |

## Ejemplo

```bash
curl "https://api.eu.keenauth.com/v1/users?limit=20&status=active" \
  -H "Authorization: Bearer $KEENAUTH_SECRET_KEY"
```

## 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.
