Documentation

Session Auth API Reference

User registration, login, session management, password reset, OAuth, MFA, and email verification

Note on Authentication Methods

Session authentication is primarily used by the web dashboard. For API integrations, we recommend using API keys for better security and control.

Session Cookie Authentication

Most endpoints set or require an HttpOnly session cookie automatically. For API clients that cannot use cookies, you can pass the session token via the Authorization: Bearer <token> header instead.

Registration & Login

POST/api/v2/auth/session/register

Register a new user account. Creates user, tenant, and optionally a session for immediate login. Password must be 8-128 characters with at least one uppercase letter, one lowercase letter, and one digit.

Request

json
{
"email": "newuser@example.com",
"password": "SecurePassword123!",
"name": "John Doe",
"organization_name": "Acme Corporation",
"auto_login": false,
"access_code": null
}
// access_code: optional — required during early access period

Response

json
{
"user_id": "550e8400-e29b-41d4-a716-446655440000",
"email": "newuser@example.com",
"name": "John Doe",
"tenant_id": "660e8400-e29b-41d4-a716-446655440000",
"session_id": null,
"session_token": null,
"email_verification_required": true,
"email_sent": true,
"email_error": null,
"message": "Registration successful"
}
POST/api/v2/auth/session/login

Login with email and password. Creates a new session and sets an HttpOnly cookie with the session token.

Request

json
{
"email": "user@example.com",
"password": "SecurePassword123!",
"remember_me": false
}

Response

json
{
"user_id": "550e8400-e29b-41d4-a716-446655440000",
"email": "user@example.com",
"name": "John Doe",
"email_verified": true,
"is_active": true,
"session_id": "770e8400-e29b-41d4-a716-446655440000",
"session_token": null,
"mfa_required": false,
"mfa_token": null,
"auth_provider": "local",
"has_password": true,
"message": "Login successful"
}
POST/api/v2/auth/session/logout

Logout and invalidate the current session. Revokes the session in the database and clears the cookie. Pass logout_all=true as a query parameter to revoke all sessions for the user.

Request

json
// Query parameter (optional):
// ?logout_all=true
// No request body required.
// Session cookie or Authorization header is used.

Response

json
{
"message": "Logout successful"
}
GET/api/v2/auth/session/me

Get current authenticated user information. Validates the session and returns user details.

Response

json
{
"user_id": "550e8400-e29b-41d4-a716-446655440000",
"email": "user@example.com",
"name": "John Doe",
"email_verified": true,
"is_active": true,
"created_at": "2025-01-15T10:30:00Z",
"last_login_at": "2025-06-01T14:22:00Z",
"auth_provider": "local",
"has_password": true
}

Session Management

POST/api/v2/auth/session/refresh

Refresh the current session by extending its expiry. Returns the updated expiry time and whether the session was extended.

Response

json
{
"expires_at": "2025-06-08T14:22:00Z",
"session_extended": true
}
GET/api/v2/auth/session/sessions

List all active sessions for the current user. Each session includes device information and whether it is the current session.

Response

json
[
{
"session_id": "770e8400-e29b-41d4-a716-446655440000",
"device_name": "Web Browser (Mozilla/5.0...)",
"ip_address": "192.168.1.100",
"last_accessed_at": "2025-06-01T14:22:00Z",
"created_at": "2025-05-28T09:00:00Z",
"expires_at": "2025-06-08T09:00:00Z",
"is_current": true
},
{
"session_id": "880e8400-e29b-41d4-a716-446655440000",
"device_name": "Web Browser (Chrome/125.0...)",
"ip_address": "10.0.0.50",
"last_accessed_at": "2025-05-30T11:15:00Z",
"created_at": "2025-05-25T08:00:00Z",
"expires_at": "2025-06-04T08:00:00Z",
"is_current": false
}
]
DELETE/api/v2/auth/session/sessions/{session_id}

Revoke a specific session by its ID. Use this to remotely log out another device.

Response

json
{
"message": "Session revoked successfully"
}
POST/api/v2/auth/session/rotate-session

Rotate the current session token. Creates a new session with a new token and revokes the old one. Used after security-sensitive operations like password changes to prevent session fixation. The new session token is set in the HttpOnly cookie.

Response

json
{
"session_id": "990e8400-e29b-41d4-a716-446655440000",
"message": "Session rotated successfully"
}

Password Reset

POST/api/v2/auth/session/password-reset/request

Request a password reset email. Always returns a success message to prevent email enumeration.

Request

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

Response

json
{
"message": "If the email exists, a reset link has been sent"
}
GET/api/v2/auth/session/password-reset/validate

Validate a password reset token before showing the reset form. Pass the token as a query parameter.

Request

json
// Query parameter:
// ?token=reset_token_from_email

Response

json
{
"valid": true,
"expires_in_minutes": 45
}
POST/api/v2/auth/session/password-reset/complete

Complete password reset with a new password. Automatically logs in the user after successful reset by setting a session cookie.

Request

json
{
"token": "reset_token_from_email",
"new_password": "NewSecurePassword123!"
}

Response

json
{
"success": true,
"message": "Password reset successful",
"user_id": "550e8400-e29b-41d4-a716-446655440000"
}

OAuth Authentication

POST/api/v2/auth/session/google

Login or register with a Google OAuth ID token (client-side flow). Validates the Google ID token and creates a session. Supports optional password for smart account linking with existing local accounts.

Request

json
{
"id_token": "google_oauth_id_token",
"remember_me": false,
"password": null,
"access_code": null
}
// password: optional — for smart account linking with existing local accounts
// access_code: optional — required during early access period for new registrations

Response

json
{
"user_id": "550e8400-e29b-41d4-a716-446655440000",
"email": "user@gmail.com",
"name": "John Doe",
"email_verified": true,
"is_active": true,
"session_id": "770e8400-e29b-41d4-a716-446655440000",
"session_token": null,
"message": "Google login successful"
}
POST/api/v2/auth/session/google/initiate

Initiate the server-side Google OAuth flow with CSRF protection. Returns an authorization URL to redirect the user to Google. Pass the action as a query parameter: 'login', 'register', or 'link'.

Request

json
// Query parameter (optional):
// ?action=login

Response

json
{
"authorization_url": "https://accounts.google.com/o/oauth2/v2/auth?client_id=...&state=...",
"state": "csrf_state_token"
}
GET/api/v2/auth/session/google/callback

Google OAuth callback handler for the server-side authorization code flow. Called by Google after user authorizes the application. Validates the state parameter for CSRF protection, exchanges the authorization code for tokens, and creates a session.

Request

json
// Query parameters (set by Google redirect):
// ?code=authorization_code&state=csrf_state_token
// or on error:
// ?error=access_denied

Response

json
{
"message": "OAuth login successful",
"redirect_url": "https://app.example.com/auth/oauth-success",
"user": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "user@gmail.com",
"name": "John Doe",
"email_verified": true
}
}
POST/api/v2/auth/session/link-provider

Link an OAuth provider to an existing authenticated account. Requires a valid session. Can optionally require password verification for extra security.

Request

json
{
"provider": "google",
"id_token": "google_oauth_id_token",
"authorization_code": null,
"redirect_uri": null,
"require_password_verification": false,
"password": null
}

Response

json
{
"success": true,
"message": "Google account linked successfully",
"provider": "google",
"provider_email": "user@gmail.com"
}
POST/api/v2/auth/session/unlink-provider

Unlink an OAuth provider from the authenticated account. Requires a valid session and password verification. The account must have both a password and an OAuth provider linked (auth_provider='both').

Request

json
{
"password": "CurrentPassword123!"
}
// password: required — account password for identity verification before unlinking

Response

json
{
"success": true,
"message": "Provider unlinked successfully"
}

Email Verification

POST/api/v2/auth/session/verify-email

Verify user email with the verification token received via email.

Request

json
{
"token": "email_verification_token"
}

Response

json
{
"success": true,
"message": "Email verified successfully",
"email_verified": true
}
POST/api/v2/auth/session/resend-verification

Resend verification email to the current authenticated user. Requires a valid session but allows unverified users. No request body needed.

Response

json
{
"message": "Verification email sent"
}
POST/api/v2/auth/session/resend-verification-by-email

Resend verification email by email address without requiring authentication. Returns success regardless of whether the email exists to prevent enumeration.

Request

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

Response

json
{
"message": "If the email exists and is unverified, a verification email has been sent"
}
GET/api/v2/auth/session/email-verification-status

Check the current user's email verification status. Requires a valid session.

Response

json
{
"email_verified": true,
"email": "user@example.com"
}

Multi-Factor Authentication (MFA)

TOTP-Based MFA

MFA uses time-based one-time passwords (TOTP) compatible with authenticator apps like Google Authenticator or Authy. Setup is a two-step process: generate a secret, then confirm with a valid code. Backup codes are provided for account recovery.

POST/api/v2/auth/session/mfa/setup

Step 1: Generate TOTP secret and backup codes. Returns a provisioning URI for QR code display in authenticator apps. Requires active session.

Response

json
{
"provisioning_uri": "otpauth://totp/Scopix:user@example.com?secret=BASE32SECRET&issuer=Scopix",
"backup_codes": ["ABCD-1234", "EFGH-5678", "IJKL-9012", "MNOP-3456"],
"secret": "BASE32SECRETKEY"
}
// provisioning_uri: scan as QR code in authenticator app
// backup_codes: one-time use recovery codes — store securely
// secret: for manual entry into authenticator app
POST/api/v2/auth/session/mfa/setup/confirm

Step 2: Confirm MFA setup by providing the first valid TOTP code from the authenticator app. This activates MFA on the account. Requires active session.

Request

json
{
"totp_code": "123456"
}
// totp_code: required, exactly 6 digits from authenticator app

Response

json
{
"message": "MFA enabled successfully"
}
POST/api/v2/auth/session/mfa/verify

Complete login by verifying a TOTP code after password authentication returned mfa_required=true. No session required — authenticates via the temporary mfa_token from the login response.

Request

json
{
"mfa_token": "temporary_mfa_challenge_token",
"code": "123456",
"remember_me": false
}
// mfa_token: required — from login response when mfa_required is true
// code: required, 6-digit TOTP code or backup code (format: XXXX-XXXX)
// remember_me: optional, default false — extend session duration

Response

json
{
"user_id": "550e8400-e29b-41d4-a716-446655440000",
"email": "user@example.com",
"name": "John Doe",
"email_verified": true,
"is_active": true,
"session_id": "770e8400-e29b-41d4-a716-446655440000",
"session_token": null,
"mfa_required": false,
"mfa_token": null,
"auth_provider": "local",
"has_password": true,
"message": "MFA verification successful"
}
// Sets HttpOnly session cookie on success
GET/api/v2/auth/session/mfa/status

Get current MFA status and remaining backup codes. Requires active session.

Response

json
{
"mfa_enabled": true,
"backup_codes_remaining": 4
}
POST/api/v2/auth/session/mfa/disable

Disable MFA on the account. Requires password confirmation. Requires active session.

Request

json
{
"password": "CurrentPassword123!"
}
// password: required — account password for verification

Response

json
{
"message": "MFA disabled successfully"
}
POST/api/v2/auth/session/mfa/backup-codes/regenerate

Generate new backup codes, invalidating all previous codes. Requires password confirmation. Requires active session.

Request

json
{
"password": "CurrentPassword123!"
}
// password: required — account password for verification

Response

json
{
"backup_codes": ["WXYZ-1234", "ABCD-5678", "EFGH-9012", "IJKL-3456"]
}
// Previous backup codes are immediately invalidated
// Store new codes securely