
# List account lockouts

`GET /v1/attack-protection/lockouts` · permission `attack-protection:read`

Lists the environment's open account lockouts, oldest first. Brute force protection locks one sign-in path of a user (for example `password` or `totp`) after too many failures; the user's other paths stay open. A lockout that has expired is not listed, because it no longer blocks the path. The list pages forward only and returns no total count. The response holds no IP address and no failure counter key.

## Request

| Parameter | In | Required | Description |
|---|---|---|---|
| `limit` | query | no | Items per page, 1-100 (default 20). |
| `after` | query | no | Cursor from `list_metadata.after` of the previous page. |

`before` and `order=desc` are not supported and return `422`.

## Response

`200 OK`.

```json
{
  "data": [
    {
      "id": "lck_01jaz8m5c3f6t9w2y4b7d0g3k6",
      "user_id": "usr_0a1b2c3d4e5f6g7h8j9k0m1n2p",
      "path": "password",
      "locked_at": "2026-10-20T09:00:00Z",
      "expires_at": "2026-10-20T09:15:00Z",
      "failure_count": 20
    }
  ],
  "list_metadata": {"before": null, "after": null}
}
```

| Field | Description |
|---|---|
| `id` | Lockout id, prefixed `lck_`. The `user.unlocked` event carries the same id. |
| `user_id` | The locked user. |
| `path` | The locked sign-in path: `password`, `totp`, `sms_2fa`, `email_2fa`, `otp` or `recovery_code`. |
| `locked_at`, `expires_at` | When the lockout started and when it lifts by itself. |
| `failure_count` | Failed attempts in the window that caused the lockout. |

## Errors

Every error is an `application/problem+json` body with a stable `code`.

| HTTP | `code` | When |
|---|---|---|
| 400 | `invalid_cursor` | The cursor is malformed or belongs to another list. |
| 422 | `validation_failed` | `limit` is out of range, or `before` or a descending `order` was sent. |
| 401 | `unauthenticated` | The API key is missing, invalid or revoked. |
| 403 | `insufficient_permissions` | The key lacks the `attack-protection:read` permission. |
| 429 | `rate_limited` | The rate limit was exceeded; honor `Retry-After`. |
| 503 | `service_unavailable` | A dependency is temporarily unavailable; retry later. |

## Example

```bash
curl https://api.eu.keenauth.com/v1/attack-protection/lockouts?limit=50 \
  -H "Authorization: Bearer $KEENAUTH_SECRET_KEY"
```

CLI: `keenauth attack-protection lockouts list --limit 50`
