Authentication
Authenticate users and manage JWT tokens for API access.
POST /api/v1/auth/login
Authenticates a user with email and password, returning a JWT token for subsequent API requests.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
email |
string | Yes | User's email address |
password |
string | Yes | User's password (min 6 characters) |
Example Request
POST /api/v1/auth/login
Content-Type: application/json
{
"email": "[email protected]",
"password": "your-password"
}
Response (200 - Success)
{
"success": true,
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user": {
"id": "abc123",
"email": "[email protected]",
"displayName": "John Doe",
"tenantId": "tenant-uuid"
},
"expiresAt": "2024-12-25T12:30:00Z",
"timestamp": "2024-12-25T12:00:00Z"
}
Error Responses
| Status | Code | Description |
|---|---|---|
| 400 | VALIDATION_ERROR |
Missing or invalid email/password format |
| 401 | INVALID_CREDENTIALS |
Email or password is incorrect |
| 401 | ACCOUNT_LOCKED |
Account locked after too many failed attempts |
| 400 | INVALID_TENANT |
User is not assigned to any organization |
GET /api/v1/auth/profile
Returns the authenticated user's profile information including organization details.
Headers
Authorization: Bearer YOUR_JWT_TOKEN
Response (200 - Success)
{
"success": true,
"user": {
"id": "abc123",
"email": "[email protected]",
"displayName": "John Doe",
"tenantId": "tenant-uuid",
"tenantName": "Acme AV Solutions"
},
"timestamp": "2024-12-25T12:00:00Z"
}
Error Responses
| Status | Code | Description |
|---|---|---|
| 401 | INVALID_TOKEN |
Token is missing, malformed, or expired |
POST /api/v1/auth/refresh
Exchanges a valid refresh token for new access and refresh tokens. Uses token rotation for security - each refresh invalidates the previous refresh token. No Authorization header required.
Request Body
{
"refreshToken": "YOUR_REFRESH_TOKEN"
}
Response (200 - Success)
{
"success": true,
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "NEW_REFRESH_TOKEN",
"accessTokenExpiresAt": "2024-12-25T12:45:00Z",
"refreshTokenExpiresAt": "2025-01-01T12:30:00Z",
"user": {
"id": "user-guid",
"email": "[email protected]",
"displayName": "User Name",
"tenantId": "tenant-guid"
},
"timestamp": "2024-12-25T12:30:00Z"
}
Error Responses
| Status | Code | Description |
|---|---|---|
| 401 | INVALID_REFRESH_TOKEN |
Refresh token is invalid, expired, or revoked |
| 401 | TOKEN_REUSE_DETECTED |
Security alert: token was already used. All sessions terminated. |
| 409 | CONCURRENT_REFRESH |
Token was already refreshed by a concurrent request |
Each refresh returns a NEW refresh token. Store it securely and use it for the next refresh. Access tokens expire in 15 minutes; refresh tokens expire in 7 days.
API Keys
For external integrations like MCP clients (Claude Desktop, Cursor) and automated scripts, use API keys instead of JWT tokens. API keys don't expire and work anywhere a JWT Bearer token is accepted.
Creating an API Key
- Go to Settings → API Keys
- Click Create API Key and enter a name (e.g., "Claude Desktop")
- Copy the key immediately — it starts with
avs_and won't be shown again
Using an API Key
Use the API key as a Bearer token in the Authorization header, the same way you'd use a JWT token:
Authorization: Bearer avs_YOUR_API_KEY
API keys work with all REST API endpoints and the MCP Server.
Managing Keys
- You can have up to 5 active keys at a time
- Revoke a key from Settings if it's compromised — revocation is immediate
- All API keys are revoked automatically when you change your password
