Skip to main content

Login

Authenticate a user with email and password credentials.
curl -X POST https://api.example.com/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{
    "email": "[email protected]",
    "password": "securePassword123"
  }'

Endpoint

POST /api/v1/auth/login
endpoint
Authenticate user and receive JWT tokens

Request Body

email
string
required
User’s email address (must be valid email format)
password
string
required
User’s password (ASCII characters only)

Response

On success, returns status 200 OK with JWT tokens set as HTTP-only cookies:
jwt-access - Access token cookie (expires per JWT_ACCESS_EXP_MIN)
jwt-refresh - Refresh token cookie (expires per JWT_REFRESH_EXP_MIN)

Error Responses

400 Bad Request
Invalid email format or missing required fields
401 Unauthorized
Incorrect email or password

User Signup

Create a new user account with email and password.
curl -X POST https://api.example.com/api/v1/auth/users \
  -H "Content-Type: application/json" \
  -d '{
    "first_name": "John",
    "last_name": "Doe",
    "email": "[email protected]",
    "phone_number": "+14155552671",
    "password": "securePassword123"
  }'

Endpoint

POST /api/v1/auth/users
endpoint
Register a new user account

Request Body

first_name
string
required
User’s first name
last_name
string
required
User’s last name
email
string
required
User’s email address (must be unique and valid email format)
phone_number
string
required
User’s phone number (must be in E.164 format, e.g., +14155552671)
password
string
required
User’s password (ASCII characters only, will be hashed with bcrypt)

Response

On success, returns status 201 Created with JWT tokens set as HTTP-only cookies:
jwt-access - Access token cookie
jwt-refresh - Refresh token cookie

Error Responses

400 Bad Request
Validation errors (invalid email, phone number format, email/phone already exists, or password too long)

Get Current User

Retrieve information about the currently authenticated user.
curl -X GET https://api.example.com/api/v1/auth/me \
  -H "Cookie: jwt-access=<access_token>"

Endpoint

GET /api/v1/auth/me
endpoint
Get current authenticated user details

Authentication Required

This endpoint requires a valid access token in the jwt-access cookie.

Response

Returns status 200 OK if authenticated.

Logout

Log out the current user by clearing their JWT tokens.
curl -X POST https://api.example.com/api/v1/auth/logout \
  -H "Cookie: jwt-access=<access_token>"

Endpoint

POST /api/v1/auth/logout
endpoint
Logout from current device

Authentication Required

This endpoint requires a valid access token in the jwt-access cookie.

Response

Clears both jwt-access and jwt-refresh cookies by setting them to expired.

Logout All Devices

Invalidate all refresh tokens across all devices by incrementing the user’s JWT refresh version.
curl -X POST https://api.example.com/api/v1/auth/logout/all \
  -H "Cookie: jwt-access=<access_token>"

Endpoint

POST /api/v1/auth/logout/all
endpoint
Logout from all devices and invalidate all refresh tokens

Authentication Required

This endpoint requires a valid access token in the jwt-access cookie.

Response

Increments the user’s jwt_refresh_version in the database, invalidating all existing refresh tokens. Clears both jwt-access and jwt-refresh cookies for the current session.

Error Responses

400 Bad Request
Error incrementing refresh version

JWT Token Structure

Access and refresh tokens are signed using HS256 algorithm and contain the following claims:

Common Claims (Both Tokens)

sub
uuid
Subject - User ID (UUID v7 format)
exp
integer
Expiration time (Unix timestamp)

Optional Employee Claims

If the user is associated with a merchant as an employee:
merchant_id
uuid
Merchant ID the employee belongs to
employee_id
integer
Employee ID
location_id
integer
Location ID where the employee works
employee_role
string
Employee role (e.g., “owner”, “manager”, “staff”)

Refresh Token Only

refresh_version
integer
Current refresh token version (incremented on logout all devices)

Token Configuration

Token expiration times are configured via environment variables:
  • JWT_ACCESS_EXP_MIN - Access token expiration in minutes
  • JWT_REFRESH_EXP_MIN - Refresh token expiration in minutes
  • JWT_ACCESS_SECRET - Secret key for signing access tokens
  • JWT_REFRESH_SECRET - Secret key for signing refresh tokens

Implementation Notes

Password Security

  • Passwords are hashed using bcrypt with cost factor 14
  • Original passwords are never stored
  • Password comparison is constant-time to prevent timing attacks

Token Storage

Tokens are stored in HTTP-only cookies with the following properties:
  • HttpOnly: Prevents JavaScript access (XSS protection)
  • SameSite: Lax mode (CSRF protection)
  • Domain: .reservations.local (subdomain support)
  • Secure: false in development, true in production (HTTPS only)
  • Path: / (available site-wide)
  • Access token: jwt-access
  • Refresh token: jwt-refresh

Build docs developers (and LLMs) love