Overview
JWT authentication is ideal for first-party web apps and server integrations that can safely store user credentials.POST /api/v1/auth/loginexchanges credentials for an access token.- HttpOnly cookies (
auth_token,refresh_token_id) are also set for browser clients. - Use
POST /api/v1/auth/refresh-sessionto rotate short-lived tokens.
Access tokens expire quickly (15 minutes). Always implement refresh logic.
Login Flow
- Collect email/password from the integration user.
- Send the payload to
/api/v1/auth/login. - Cache the returned JWT for Authorization headers.
- Store refresh identifiers securely.
The
accessToken should be used in the Authorization: Bearer <token> header for subsequent API requests. The refreshToken can be used to obtain a new access token when it expires. HttpOnly cookies are also set for browser-based clients.Using Tokens
Include the JWT in every request:Refresh Sessions
- Endpoint:
POST /api/v1/auth/refresh-session - Requires the
refresh_token_idcookie (for browser clients) or refresh token in the request body (for server-to-server). - Returns a brand new JWT access token and rotates refresh identifiers.
- Access tokens expire after 15 minutes (configurable via
JWT_EXPIRES_IN). - Refresh tokens expire after 7 days (configurable via
JWT_REFRESH_EXPIRES_IN).
Browser-based Refresh (Cookie-based)
For browser clients, the refresh endpoint automatically uses therefresh_token_id cookie:
auth_token- New JWT access tokenrefresh_token_id- New refresh token identifier
Server-to-Server Refresh
For server integrations, include the refresh token in the request:Error Codes
All errors follow the standard error response format:no_token– Missing Authorization headertoken_expired– Access token exceeded its TTLtoken_invalid– Token signature or claims invalidrate_limited_email/rate_limited_ip– Too many login attemptsaccount_not_fully_activated– User account is inactiveaccount_inactive_login_attempt– Login attempt on inactive account
400– Bad Request (validation errors, invalid token)401– Unauthorized (authentication failed)403– Forbidden (account inactive)