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

# Login

> Authenticate a Frost Auth console operator and receive a session cookie.

# Login

```http theme={null}
POST /api/v1/auth/login
Content-Type: application/json
```

Authenticates a console operator and sets the `session_token` httpOnly cookie used by all dashboard routes.

## Request

```json theme={null}
{
  "login": "alex.dev",
  "password": "••••••••",
  "twofa": "000000", // optional
  "hcaptchaToken": "P1_eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
```

## Parameters

| Field | Required | Description |
| - | - | - |
| `login` | Yes | Username or email address. Matched case-insensitively against both. |
| `password` | Yes | Account password. Verified with argon2id. |
| `twofa` | Conditional | Six-digit TOTP code or twelve-character recovery code. Required when the account has two-factor enabled. |
| `hcaptchaToken` | Conditional | hCaptcha response token from the sign-in widget. Only present when `NEXT_PUBLIC_HCAPTCHA_SITE_KEY` is configured. |

## Responses

```text 200 Success theme={null}
{
  "success": true,
  "response": {
    "data": {
      "user": {
        "id": "cmskeyhvo0001...",
        "name": "alex.dev",
        "email": "alex@example.com",
        "role": "Owner",
        "status": "Active",
        "createdAt": "2026-01-15T08:22:09.118Z",
        "totpEnabled": true
      }
    }
  }
}
```

```text 400 Bad Request theme={null}
{
  "error": true,
  "response": {
    "code": 400,
    "message": "All fields are required"
  }
}
```

```text 401 Unauthorized theme={null}
{
  "error": true,
  "response": {
    "code": 401,
    "message": "Invalid credentials"
  }
}
```

```text 403 Forbidden theme={null}
{
  "error": true,
  "response": {
    "code": 403,
    "message": "Account is inactive or suspended"
  }
}
```

```text 429 Rate Limited theme={null}
{
  "error": true,
  "response": {
    "code": 429,
    "message": "Too many auth attempts, try again later"
  }
}
```

```text 500 Server Error theme={null}
{
  "error": true,
  "response": {
    "code": 500,
    "message": "Server error"
  }
}
```

## Behavior

* Sets the `session_token` httpOnly cookie (`SameSite=Strict`, not readable from JavaScript).
* Browser clients must send `credentials: "include"` on subsequent requests.
* Wrong passwords are indistinguishable from unknown users — both answer `401 Invalid credentials`.
* A recovery code spent during login returns `recoveryCodesLeft` in the success response.
* When 2FA is enabled and no `twofa` was sent, the response carries `twoFactorRequired: true` alongside the 401.

## Rate Limits & Lockout

| Layer | Limit | Keyed by |
| - | - | - |
| Route limiter | 20 per 15 min | IP |
| Per-identity backoff | 5 free attempts, then doubling from 2s to 15 min | Account + IP separately |

> The per-identity lockout counts failed sign-ins against both the account identifier and the source address independently. One host spraying many accounts and many hosts hitting one account are both caught.

## Errors

| HTTP | Message | Cause |
| - | - | - |
| `400` | `All fields are required` | `login` or `password` missing/empty. |
| `401` | `Invalid credentials` | Wrong password or unknown user — indistinguishable. |
| `401` | `A two-factor code is required` | Account has 2FA but no `twofa` was sent. Carries `twoFactorRequired: true`. |
| `401` | `Invalid two-factor code` | Code doesn't match. Carries `twoFactorRequired: true`. |
| `401` | `That code has already been used — wait for the next one` | TOTP replay detected. |
| `403` | `Account is inactive or suspended` | Account status is not Active. |
| `429` | `Too many failed sign-in attempts — try again in Xs` | Per-identity lockout active. |
| `429` | `Too many auth attempts, try again later` | Route-level rate limit exceeded. |
| `500` | `Server error` | Unhandled exception in the login controller. |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.