Skip to main content
Authenticates an existing user with their email and password. On success, returns an access token in the response body and sets a refreshToken httpOnly cookie. If a refreshToken cookie from a previous session is present, it is automatically revoked before issuing a new one.

Endpoint

POST /api/auth/login
Authentication: None required
This endpoint is rate-limited to 5 attempts per 15 minutes per email address. Exceeding the limit returns 429 Too Many Requests.

Request body

email
string
required
The user’s registered email address. The rate limiter uses this value as the identifier.
password
string
required
The user’s password.

Response

success
boolean
required
true on a successful login.
message
string
required
Human-readable result message. Value: "Login successful".
data
object
A refreshToken cookie is also set on the response (httpOnly, secure, sameSite: none, scoped to /api/auth).

Error cases

StatusMessageCause
400Validation error messageMissing or invalid request body fields
401"User not found"No account exists for the given email
401"Invalid password"Password does not match the stored hash
429"Too many requests."Rate limit of 5 attempts per 15 minutes exceeded
500"Login failed"Unexpected server error

Example

curl -X POST http://localhost:5000/api/auth/login \
  -H "Content-Type: application/json" \
  -c cookies.txt \
  -d '{
    "email": "[email protected]",
    "password": "SecurePass123!"
  }'
The -c cookies.txt flag saves the refreshToken cookie to a file so it can be reused in subsequent requests. In browser-based clients, this is handled automatically.
Success response (200):
{
  "success": true,
  "message": "Login successful",
  "data": {
    "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "user": {
      "id": "64f1a2b3c4d5e6f7a8b9c0d1",
      "email": "[email protected]",
      "name": "Alice Smith",
      "avatar": "https://example.com/avatar.png",
      "role": "user",
      "subscription": {
        "plan": "pro",
        "status": "active"
      }
    }
  }
}
Error response (401 — invalid credentials):
{
  "success": false,
  "message": "Invalid password",
  "statusCode": 401
}
Error response (429 — rate limit exceeded):
{
  "success": false,
  "message": "Too many requests.",
  "statusCode": 429
}

Build docs developers (and LLMs) love