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
/api/auth/signupCreate a new user account
Rate Limit: 10 requests per hour
Request Body:
| Field | Type | Required | Validation |
|---|---|---|---|
email | string | Yes | Valid email format, normalized |
password | string | Yes | Min 8 characters, must contain uppercase, lowercase, and number |
name | string | Yes | 1-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:
| Status | Error | Description |
|---|---|---|
| 400 | Validation errors | Missing or invalid fields |
| 400 | Email already registered | Email address is already in use |
| 429 | Too many signup attempts | Rate limit exceeded |
Email Verification
/api/auth/verify-emailVerify email address using token from email
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
token | string | Yes | Verification 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
/api/auth/resend-verificationResend 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
/api/auth/loginAuthenticate user and receive tokens
Rate Limit: 5 requests per 15 minutes
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
email | string | Yes | User's email address |
password | string | Yes | User'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:
| Status | Error | Description |
|---|---|---|
| 401 | Invalid credentials | Wrong email or password |
| 403 | Account suspended | Account has been suspended |
| 403 | Email not verified | Email verification required |
| 403 | Please use SSO to sign in | User must sign in via SSO provider |
| 429 | Too many login attempts | Rate limit exceeded |
Two-Factor Authentication
Verify 2FA Code (Login)
/api/auth/2fa/verifyComplete login with 2FA code
Rate Limit: 10 requests per 5 minutes
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
tempToken | string | Yes | Temporary token from login response |
token | string | Yes | 6-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
/api/auth/2fa/setupGenerate QR code and secret for 2FA setup
Headers:
| Header | Value |
|---|---|
| Authorization | Bearer {access_token} |
Success Response (200 OK):
{
"qrCode": "data:image/png;base64,iVBORw0KGgo...",
"secret": "JBSWY3DPEHPK3PXP",
"backupSecret": "JBSWY3DPEHPK3PXP"
}Verify 2FA Setup
/api/auth/2fa/verify-setupConfirm 2FA setup with verification code
Headers:
| Header | Value |
|---|---|
| Authorization | Bearer {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
/api/auth/2fa/disableDisable two-factor authentication
Headers:
| Header | Value |
|---|---|
| Authorization | Bearer {access_token} |
Request Body:
{
"token": "123456"
}Use Recovery Code
/api/auth/2fa/recoverLogin 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
/api/auth/refreshGet 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:
| Status | Error | Description |
|---|---|---|
| 400 | Refresh token required | Missing refresh token |
| 401 | Invalid refresh token | Token is invalid or malformed |
| 401 | Token has been revoked | Token version mismatch (user logged out) |
| 403 | Account suspended | User account is suspended |
Logout
/api/auth/logoutInvalidate all tokens for the current user
Headers:
| Header | Value |
|---|---|
| Authorization | Bearer {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
/api/auth/meGet the currently authenticated user's profile
Headers:
| Header | Value |
|---|---|
| Authorization | Bearer {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
/api/auth/forgot-passwordRequest 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
/api/auth/reset-passwordSet a new password using reset token
Request Body:
| Field | Type | Required | Validation |
|---|---|---|---|
token | string | Yes | Reset token from email |
password | string | Yes | Same 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:
| Status | Error | Description |
|---|---|---|
| 400 | Token and password are required | Missing required fields |
| 400 | Password must be at least 8 characters | Password too short |
| 400 | Password must contain an uppercase letter | Missing uppercase |
| 400 | Password must contain a lowercase letter | Missing lowercase |
| 400 | Password must contain a number | Missing digit |
| 400 | Invalid or expired reset link | Token invalid or expired |
Exchange Authorization Code
/api/auth/exchange-codeExchange 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 Type | Expiration |
|---|---|
| Access Token | 15 minutes |
| Refresh Token | 7 days |
| 2FA Temp Token | 5 minutes |
| Password Reset Token | 1 hour |
| Team Invite Token | 7 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"
}
]
}