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:
| Header | Required | Description |
|---|---|---|
X-PixoMonitor-Installation-ID | Yes | UUID identifying this app installation or browser profile |
X-PixoMonitor-Platform | No | Client platform such as web or ios; browser requests are treated as web |
X-PixoMonitor-Device-Name | No | Device label, up to 255 characters |
X-PixoMonitor-App-Version | No | Client 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
/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 | Minimum 8 characters |
name | string | Yes | 1-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:
| 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 |
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
/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
Required Header: X-PixoMonitor-Installation-ID: {installation_uuid}
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": "native-clients-only"
}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
Required Header: X-PixoMonitor-Installation-ID: {installation_uuid}
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": "native-clients-only"
}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 Session
/api/auth/refreshRotate 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
/api/auth/logoutRevoke 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
/api/auth/logout-allRevoke every active refresh session for the authenticated user
Include Authorization: Bearer {access_token}. Success returns 204 No Content.
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
}
}Exchange Browser Authorization Cookie
/api/auth/exchange-codeComplete 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 Type | Expiration |
|---|---|
| Access Token | 15 minutes |
| Refresh Session | 7 days |
| 2FA Login Challenge | 5 minutes |
| Browser Authorization Cookie | 2 minutes |
| 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"
}
]
}