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.


Sign Up

POST/api/auth/signup

Create a new user account

Rate Limit: 10 requests per hour

Request Body:

FieldTypeRequiredValidation
emailstringYesValid email format, normalized
passwordstringYesMin 8 characters, must contain uppercase, lowercase, and number
namestringYes1-100 characters

Password Requirements:

  • Minimum 8 characters
  • At least one uppercase letter (A-Z)
  • At least one lowercase letter (a-z)
  • At least one number (0-9)

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

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": "eyJhbGciOiJIUzI1NiIs..."
}

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

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": "eyJhbGciOiJIUzI1NiIs..."
}

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

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": "eyJhbGciOiJIUzI1NiIs..."
}

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 Token

POST/api/auth/refresh

Get a new access token using refresh token

Rate Limit: 30 requests per 15 minutes

Request Body:

{
  "refreshToken": "eyJhbGciOiJIUzI1NiIs..."
}

Success Response (200 OK):

{
  "accessToken": "eyJhbGciOiJIUzI1NiIs...",
  "refreshToken": "eyJhbGciOiJIUzI1NiIs..."
}

Error Responses:

StatusErrorDescription
400Refresh token requiredMissing refresh token
401Invalid refresh tokenToken is invalid or malformed
401Token has been revokedToken version mismatch (user logged out)
403Account suspendedUser account is suspended

Logout

POST/api/auth/logout

Invalidate all tokens for the current user

Headers:

HeaderValue
AuthorizationBearer {access_token}

Success Response (200 OK):

{
  "message": "Logged out successfully"
}

Logging out increments the user's token version, which invalidates all existing refresh tokens.


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
  }
}

Forgot Password

POST/api/auth/forgot-password

Request a password reset link

Rate Limit: 3 requests per 15 minutes

Request Body:

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

Success Response (200 OK):

{
  "message": "If an account exists with that email, a password reset link has been sent."
}

The response is intentionally generic to prevent email enumeration. The reset link expires after 1 hour.


Reset Password

POST/api/auth/reset-password

Set a new password using reset token

Request Body:

FieldTypeRequiredValidation
tokenstringYesReset token from email
passwordstringYesSame requirements as signup

Request Example:

{
  "token": "a1b2c3d4e5f6...",
  "password": "NewSecurePass456"
}

Success Response (200 OK):

{
  "message": "Password reset successful. You can now log in with your new password."
}

Error Responses:

StatusErrorDescription
400Token and password are requiredMissing required fields
400Password must be at least 8 charactersPassword too short
400Password must contain an uppercase letterMissing uppercase
400Password must contain a lowercase letterMissing lowercase
400Password must contain a numberMissing digit
400Invalid or expired reset linkToken invalid or expired

Exchange Authorization Code

POST/api/auth/exchange-code

Exchange OAuth/SSO authorization code for tokens

Rate Limit: 10 requests per 5 minutes

Request Body:

{
  "code": "one-time-auth-code"
}

Success Response (200 OK):

{
  "accessToken": "eyJhbGciOiJIUzI1NiIs...",
  "refreshToken": "eyJhbGciOiJIUzI1NiIs..."
}

Authorization codes are single-use and expire quickly. This endpoint is used internally for OAuth/SSO callback flows.


Token Expiration Summary

Token TypeExpiration
Access Token15 minutes
Refresh Token7 days
2FA Temp Token5 minutes
Password Reset Token1 hour
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"
    }
  ]
}