Skip to main content

Auth API

All auth endpoints are under /api/v1/auth. Rate limit: 20 requests/minute.

Endpoints

MethodPathAuthDescription
POST/auth/registerPublicRegister a new user
POST/auth/loginPublicLogin and get tokens
POST/auth/logoutRequiredRevoke refresh token
POST/auth/verify-emailPublicVerify email address
POST/auth/password-reset/requestPublicRequest password reset email
POST/auth/password-reset/confirmPublicSet new password
POST/auth/refreshPublicRotate access token
GET/auth/googlePublicInitiate Google OAuth
GET/auth/google/callbackPublicGoogle OAuth callback

Register

Create a new user account. Sends a verification email.
POST /auth/register

Request Body

{
  "email": "user@example.com",
  "password": "Secure@123",
  "first_name": "John",
  "last_name": "Doe"
}

Response 201 Created

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "email": "user@example.com",
  "first_name": "John",
  "last_name": "Doe",
  "email_verified": false,
  "created_at": "2024-01-15T10:30:00Z"
}

Errors

StatusDetail
409Email already registered
422Validation error (invalid email, weak password)

Login

Authenticate and receive JWT access + refresh tokens.
POST /auth/login

Request Body

{
  "email": "user@example.com",
  "password": "Secure@123"
}

Response 200 OK

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "bearer",
  "user": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "email": "user@example.com",
    "first_name": "John"
  }
}

Token Expiry

TokenLifetime
Access token60 minutes
Refresh token7 days

Errors

StatusDetail
401Invalid email or password
403Email not verified

Logout

Revoke the current refresh token (invalidates the session).
POST /auth/logout
Authorization: Bearer <access_token>

Response 200 OK

{ "message": "Logged out successfully" }

Verify Email

Confirm an email address using the token from the verification email.
POST /auth/verify-email

Request Body

{
  "token": "abc123verificationtoken"
}

Response 200 OK

{ "message": "Email verified successfully" }

Errors

StatusDetail
400Invalid or expired verification token

Request Password Reset

Send a password reset email.
POST /auth/password-reset/request

Request Body

{
  "email": "user@example.com"
}

Response 200 OK

{ "message": "Password reset email sent" }
Always returns 200 even if the email is not registered (prevents user enumeration).

Confirm Password Reset

Set a new password using the token from the reset email.
POST /auth/password-reset/confirm

Request Body

{
  "token": "abc123resettoken",
  "new_password": "NewSecure@456"
}

Response 200 OK

{ "message": "Password reset successfully" }

Errors

StatusDetail
400Invalid or expired reset token

Refresh Token

Exchange a refresh token for a new access token. The refresh token is rotated on each use.
POST /auth/refresh

Request Body

{
  "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}

Response 200 OK

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "bearer"
}
Token rotation is enabled — each refresh invalidates the old refresh token and issues a new one.

Errors

StatusDetail
401Invalid or expired refresh token

Google OAuth

Single sign-on via Google. Redirects through Google’s consent screen and returns tokens on success.

Step 1 — Initiate

Redirect the user’s browser to:
GET /api/v1/auth/google
This redirects to Google’s OAuth consent screen.

Step 2 — Callback

After the user approves, Google redirects back to:
GET /api/v1/auth/google/callback?code=...
On success, the server redirects to the frontend with the access token:
/auth/callback?access_token=eyJhbGc...
The frontend (AuthCallback page) reads the token from the URL, fetches the user profile, and stores auth state.

New vs Returning Users

  • New user — account is auto-created with auth_provider = "google", no password set
  • Returning user — existing account is found by email and tokens are issued

Using Tokens

Include the access token in the Authorization header for all protected endpoints:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
When the access token expires (60 min), call POST /auth/refresh to get a new one. The frontend Axios interceptor handles this automatically.