Authentication API

PixoMonitor uses JWT (JSON Web Tokens) for authentication. Access tokens expire after 15 minutes, and refresh tokens expire after 7 days.

Authentication Overview

All authenticated endpoints require a valid JWT token in the Authorization header:

Authorization: Bearer <access_token>

When an access token expires, use the refresh token to obtain a new access token. This allows for secure, seamless authentication without requiring users to log in again.

Session Metadata and Refresh Credentials

Requests that issue, rotate, or revoke a login session require a stable installation identifier:

HeaderRequiredDescription
X-PixoMonitor-Installation-IDYesUUID identifying this app installation or browser profile
X-PixoMonitor-PlatformNoClient platform such as web or ios; browser requests are treated as web
X-PixoMonitor-Device-NameNoDevice label, up to 255 characters
X-PixoMonitor-App-VersionNoClient version, up to 50 characters

The installation header is required by email verification, login session issuance, 2FA login verification/recovery, token refresh, logout, and browser authorization-code exchange. Reuse the same UUID for the lifetime of the installation.

Web clients must send requests with credentials enabled. PixoMonitor stores the rotating refresh credential in a Secure, HttpOnly, SameSite=Strict cookie and omits refreshToken from JSON responses. Non-web clients receive refreshToken in the response body and submit it in the refresh/logout request body.


Sign Up

POST/api/auth/signup

Create a new user account

Rate Limit: 10 requests per hour

Request Body:

FieldTypeRequiredValidation
emailstringYesValid email format, normalized
passwordstringYesMinimum 8 characters
namestringYes1-100 characters

Password Requirement: Minimum 8 characters.

Request Example:

{
  "email": "user@example.com",
  "password": "SecurePass123",
  "name": "John Doe"
}

Success Response (201 Created):

{
  "message": "Registration successful. Please check your email to verify your account.",
  "user": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "email": "user@example.com",
    "name": "John Doe",
    "role": "USER",
    "email_verified": false
  }
}

Error Responses:

StatusErrorDescription
400Validation errorsMissing or invalid fields
400Email already registeredEmail address is already in use
429Too many signup attemptsRate limit exceeded

Email Verification

GET/api/auth/verify-email

Verify email address using token from email

Query Parameters:

ParameterTypeRequiredDescription
tokenstringYesVerification token from email

Required Header: X-PixoMonitor-Installation-ID: {installation_uuid}

Success Response (200 OK):

{
  "message": "Email verified successfully",
  "user": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "email": "user@example.com",
    "name": "John Doe",
    "email_verified": true
  },
  "accessToken": "eyJhbGciOiJIUzI1NiIs...",
  "refreshToken": "native-clients-only"
}

Resend Verification Email

POST/api/auth/resend-verification

Resend email verification link

Request Body:

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

Success Response (200 OK):

{
  "message": "If this email is registered, a verification link has been sent."
}

The response is intentionally generic to prevent email enumeration attacks.


Login

POST/api/auth/login

Authenticate user and receive tokens

Rate Limit: 5 requests per 15 minutes

Required Header: X-PixoMonitor-Installation-ID: {installation_uuid}

Request Body:

FieldTypeRequiredDescription
emailstringYesUser's email address
passwordstringYesUser's password

Request Example:

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

Success Response (200 OK):

{
  "user": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "email": "user@example.com",
    "name": "John Doe",
    "role": "USER",
    "status": "ACTIVE",
    "twoFactorEnabled": false,
    "email_verified": true
  },
  "accessToken": "eyJhbGciOiJIUzI1NiIs...",
  "refreshToken": "native-clients-only"
}

2FA Required Response (200 OK):

If the user has two-factor authentication enabled:

{
  "requires2FA": true,
  "tempToken": "eyJhbGciOiJIUzI1NiIs..."
}

Error Responses:

StatusErrorDescription
401Invalid credentialsWrong email or password
403Account suspendedAccount has been suspended
403Email not verifiedEmail verification required
403Please use SSO to sign inUser must sign in via SSO provider
429Too many login attemptsRate limit exceeded

Two-Factor Authentication

Verify 2FA Code (Login)

POST/api/auth/2fa/verify

Complete login with 2FA code

Rate Limit: 10 requests per 5 minutes

Required Header: X-PixoMonitor-Installation-ID: {installation_uuid}

Request Body:

FieldTypeRequiredDescription
tempTokenstringYesTemporary token from login response
tokenstringYes6-digit TOTP code from authenticator app

Request Example:

{
  "tempToken": "eyJhbGciOiJIUzI1NiIs...",
  "token": "123456"
}

Success Response (200 OK):

{
  "user": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "email": "user@example.com",
    "name": "John Doe",
    "role": "USER",
    "status": "ACTIVE",
    "twoFactorEnabled": true,
    "email_verified": true
  },
  "accessToken": "eyJhbGciOiJIUzI1NiIs...",
  "refreshToken": "native-clients-only"
}

Setup 2FA

POST/api/auth/2fa/setup

Generate QR code and secret for 2FA setup

Headers:

HeaderValue
AuthorizationBearer {access_token}

Success Response (200 OK):

{
  "qrCode": "data:image/png;base64,iVBORw0KGgo...",
  "secret": "JBSWY3DPEHPK3PXP",
  "backupSecret": "JBSWY3DPEHPK3PXP"
}

Verify 2FA Setup

POST/api/auth/2fa/verify-setup

Confirm 2FA setup with verification code

Headers:

HeaderValue
AuthorizationBearer {access_token}

Request Body:

{
  "token": "123456"
}

Success Response (200 OK):

{
  "enabled": true,
  "recoveryCodes": [
    "A1B2C3D4",
    "E5F6G7H8",
    "I9J0K1L2",
    "M3N4O5P6",
    "Q7R8S9T0",
    "U1V2W3X4",
    "Y5Z6A7B8",
    "C9D0E1F2",
    "G3H4I5J6",
    "K7L8M9N0"
  ]
}

Store recovery codes securely! They can be used to access your account if you lose access to your authenticator app.

Disable 2FA

POST/api/auth/2fa/disable

Disable two-factor authentication

Headers:

HeaderValue
AuthorizationBearer {access_token}

Request Body:

{
  "token": "123456"
}

Use Recovery Code

POST/api/auth/2fa/recover

Login using a recovery code instead of TOTP

Request Body:

{
  "tempToken": "eyJhbGciOiJIUzI1NiIs...",
  "recoveryCode": "A1B2C3D4"
}

Success Response (200 OK):

{
  "user": { ... },
  "accessToken": "eyJhbGciOiJIUzI1NiIs...",
  "refreshToken": "eyJhbGciOiJIUzI1NiIs...",
  "remainingCodes": 9
}

Refresh Session

POST/api/auth/refresh

Rotate the current refresh session and obtain a new access token

Required Header: X-PixoMonitor-Installation-ID: {installation_uuid}

Web clients send an empty body with credentials enabled; the refresh credential comes from the Secure HttpOnly cookie. Non-web clients send:

{
  "refreshToken": "session-id.secret"
}

The response contains a new accessToken. Non-web responses also contain the rotated refreshToken; web responses rotate the cookie instead.

Invalid, expired, revoked, reused, or installation-mismatched refresh credentials return 401 Invalid refresh token. Suspended accounts return 403 Account suspended.


Logout Current Session

POST/api/auth/logout

Revoke the refresh session for this installation

Required Header: X-PixoMonitor-Installation-ID: {installation_uuid}

Web clients send an empty body with credentials enabled. Non-web clients send the current refreshToken in the request body. Success returns 204 No Content.

Logout All Sessions

POST/api/auth/logout-all

Revoke every active refresh session for the authenticated user

Include Authorization: Bearer {access_token}. Success returns 204 No Content.


Get Current User

GET/api/auth/me

Get the currently authenticated user's profile

Headers:

HeaderValue
AuthorizationBearer {access_token}

Success Response (200 OK):

{
  "user": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "email": "user@example.com",
    "name": "John Doe",
    "role": "USER",
    "status": "ACTIVE",
    "twoFactorEnabled": false,
    "email_verified": true
  }
}

POST/api/auth/exchange-code

Complete the internal browser OAuth or SSO callback flow

After a successful Google OAuth or SSO callback, PixoMonitor sets a short-lived Secure HttpOnly __Host-pixomonitor_oauth_code cookie and redirects the browser to /oauth/callback. The browser then sends a credentialed POST with an empty body.

Required Header: X-PixoMonitor-Installation-ID: {installation_uuid}

The endpoint reads only the HttpOnly cookie; request-body or query-string authorization codes are not accepted. On success, it clears the one-time cookie, sets the web refresh cookie, and returns an accessToken.

This is an internal browser handoff, not a general-purpose OAuth token-exchange API. The authorization cookie is single-use and expires after 2 minutes.


Token Expiration Summary

Token TypeExpiration
Access Token15 minutes
Refresh Session7 days
2FA Login Challenge5 minutes
Browser Authorization Cookie2 minutes
Team Invite Token7 days

Error Response Format

All error responses follow this format:

{
  "error": "Error message here"
}

For validation errors:

{
  "errors": [
    {
      "type": "field",
      "value": "invalid-email",
      "msg": "Invalid value",
      "path": "email",
      "location": "body"
    }
  ]
}