---
title: "Authenticate user"
method: POST
path: "/users/login"
tags: ["Users - Authentication"]
---

# Authenticate user

`POST /users/login`

Validates email/password credentials via bcrypt. Returns a JWT access token
in the response body and sets a refresh token in an HTTP-only cookie.
Rate-limited to 5 requests per minute per IP.

## Request body

- object
  - `email` string, email, required
  - `password` string, password, required

## Response `202`

Authentication successful

- object
  - `message` string
  - `data` object
    - `token` string — JWT access token
    - `isSuperAdmin` boolean — Only present when user is super-admin (role_id=5)
    - `onboarding_status` string — Organization onboarding status (not present for super-admin)
    - `is_org_creator` boolean — Whether user is the first admin of the org (not present for super-admin)

## Other responses

- `401` — Invalid email or password
- `429` — Too many login attempts
- `500` — Internal server error

## Changes

- **2026-04-21** `55cdc040840c` — 4 breaking, 6 info
  - added the new required request property `email`
  - added the new required request property `password`
  - request body became required
  - removed the success response with the status `201`
  - …6 more
- **2026-04-05** `c419b1e72a65` — 1 breaking, 2 warning, 6 info
  - removed the success response with the status `200`
  - removed the request property `email`
  - removed the request property `password`
  - api operation id `loginUser` was added
  - …5 more
- **2025-09-11** `cfa9ae933c17` — 5 warning, 11 info
  - removed the optional property `data/accessToken` from the response with the `200` status
  - removed the optional property `data/refreshToken` from the response with the `200` status
  - removed the optional property `data/user/last_login` from the response with the `200` status
  - removed the optional property `data/user/password_hash` from the response with the `200` status
  - …12 more
- **2025-08-31** `0d2ea2f98fd4` — 1 info
  - removed the non-success response with the status `429`
- **2025-08-29** `af64a3a9480e` — 5 breaking, 7 info
  - the request property `email` became required
  - the request property `password` became required
  - the `email` request property type/format changed from `string`/`` to `string`/`email`
  - the `password` request property type/format changed from `string`/`` to `string`/`password`
  - …8 more

[Full history](https://skmtc.dev/verifywise-ai/apis/verifywise-api/changes/users/login/post.md)

---

[API](https://skmtc.dev/verifywise-ai/apis/verifywise-api.md) · [All operations](https://skmtc.dev/verifywise-ai/apis/verifywise-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/verifywise-ai/verifywise-api/revisions/55cdc040840c/schema)
