Multi-User API Guide | InvokeAI Documentation
Multi-User API Guide
Overview
This guide explains how to interact with InvokeAI’s API in both single-user and multi-user modes. The API behavior depends on the multiuser configuration setting.
Single-User vs Multi-User Mode
Single-User Mode (multiuser: false or option absent):
- No authentication required
- All API endpoints accessible without tokens
- Direct API access like previous InvokeAI versions
- All content visible in unified view
Multi-User Mode (multiuser: true):
- JWT token authentication required
- User-scoped access to resources
- Role-based authorization (admin vs regular user)
- Data isolation between users
Authentication (Multi-User Mode Only)
Authentication Flow
When multi-user mode is enabled, most API endpoints require authentication using JWT bearer tokens. The unauthenticated authentication endpoints are GET /api/v1/auth/status, POST /api/v1/auth/setup, and POST /api/v1/auth/login.
Authentication Process:
- Obtain Token: POST credentials to
/api/v1/auth/login - Store Token: Save the JWT token securely
- Use Token: Include token in
Authorizationheader for all requests - Refresh: Re-authenticate when token expires
Login Endpoint
Endpoint:POST /api/v1/auth/login
Request:
{
"email": "user@example.com",
"password": "SecurePassword123",
"remember_me": false
}
Response (Success):
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user": {
"user_id": "abc123",
"email": "user@example.com",
"display_name": "John Doe",
"is_admin": false,
"is_active": true,
"created_at": "2024-01-15T10:00:00Z",
"updated_at": "2024-01-15T10:00:00Z",
"last_login_at": "2024-01-15T15:30:00Z"
},
"expires_in": 86400
}
Response (Error):
{
"detail": "Incorrect email or password"
}
Status Codes:
200 OK— Authentication successful401 Unauthorized— Invalid credentials403 Forbidden— Account disabled422 Unprocessable Entity— Invalid request format
Using the Token
Include the JWT token in the Authorization header with the Bearer scheme:
HTTP Header:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Example HTTP Request:
GET /api/v1/boards HTTP/1.1
Host: localhost:9090
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/json
Token Expiration
Tokens have a limited lifetime:
- Default: 24 hours (86400 seconds)
- Remember Me: 7 days (604800 seconds)
Handling Expiration:
import requests
import time
def api_request(url, token, max_retries=1):
headers = {"Authorization": f"Bearer {token}"}
response = requests.get(url, headers=headers)
if response.status_code == 401: # Token expired
# Re-authenticate and retry
new_token = login()
headers = {"Authorization": f"Bearer {new_token}"}
response = requests.get(url, headers=headers)
return response
Logout Endpoint
Endpoint:POST /api/v1/auth/logout
Request:
POST /api/v1/auth/logout HTTP/1.1
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Response:
{
"success": true
}
Code Examples
Python
Using requests library:
import requests
import json
class InvokeAIClient:
def __init__(self, base_url="http://localhost:9090"):
self.base_url = base_url
self.token = None
def login(self, email, password, remember_me=False):
"""Authenticate and store token."""
url = f"{self.base_url}/api/v1/auth/login"
payload = {"email": email, "password": password, "remember_me": remember_me}
response = requests.post(url, json=payload)
response.raise_for_status()
data = response.json()
self.token = data["token"]
return data["user"]
def _get_headers(self):
"""Get headers with authentication token."""
if not self.token:
raise Exception("Not authenticated. Call login() first.")
return {"Authorization": f"Bearer {self.token}", "Content-Type": "application/json"}
def get_boards(self):
"""Get user's boards."""
url = f"{self.base_url}/api/v1/boards/"
response = requests.get(url, headers=self._get_headers())
response.raise_for_status()
return response.json()
def create_board(self, board_name):
"""Create a new board."""
url = f"{self.base_url}/api/v1/boards/"
response = requests.post(
url,
params={"board_name": board_name},
headers=self._get_headers()
)
response.raise_for_status()
return response.json()
def logout(self):
"""Logout and clear token."""
url = f"{self.base_url}/api/v1/auth/logout"
response = requests.post(url, headers=self._get_headers())
self.token = None
return response.json()
# Usage
client = InvokeAIClient()
user = client.login("user@example.com", "SecurePassword123")
print(f"Logged in as: {user['display_name']}")
boards = client.get_boards()
print(f"User has {len(boards['items'])} boards")
new_board = client.create_board("My New Board")
print(f"Created board: {new_board['board_name']}")
client.logout()
JavaScript/TypeScript
Using fetch API:
class InvokeAIClient {
constructor(baseUrl = 'http://localhost:9090') {
this.baseUrl = baseUrl;
this.token = null;
}
async login(email, password, rememberMe = false) {
const response = await fetch(`${this.baseUrl}/api/v1/auth/login`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
email,
password,
remember_me: rememberMe,
}),
});
if (!response.ok) {
throw new Error(`Login failed: ${response.statusText}`);
}
const data = await response.json();
this.token = data.token;
localStorage.setItem('invokeai_token', data.token);
return data.user;
}
getHeaders() {
if (!this.token) {
throw new Error('Not authenticated. Call login() first.');
}
return {'Authorization': `Bearer ${this.token}`, 'Content-Type': 'application/json'};
}
async getBoards() {
const response = await fetch(`${this.baseUrl}/api/v1/boards/`, {
headers: this.getHeaders(),
});
if (!response.ok) {
throw new Error(`Failed to get boards: ${response.statusText}`);
}
return response.json();
}
async createBoard(boardName) {
const url = new URL(`${this.baseUrl}/api/v1/boards/`);
url.searchParams.set('board_name', boardName);
const response = await fetch(url, {
method: 'POST',
headers: this.getHeaders(),
});
if (!response.ok) {
throw new Error(`Failed to create board: ${response.statusText}`);
}
return response.json();
}
async logout() {
const response = await fetch(`${this.baseUrl}/api/v1/auth/logout`, {
method: 'POST',
headers: this.getHeaders(),
});
this.token = null;
localStorage.removeItem('invokeai_token');
return response.json();
}
}
// Usage
(async () => {
const client = new InvokeAIClient();
try {
const user = await client.login('user@example.com', 'SecurePassword123');
console.log(`Logged in as: ${user.display_name}`);
const boards = await client.getBoards();
console.log(`User has ${boards.items.length} boards`);
const newBoard = await client.createBoard('My New Board');
console.log(`Created board: ${newBoard.board_name}`);
await client.logout();
} catch (error) {
console.error('Error:', error.message);
}
})();
cURL
Login:
# Login and extract token
TOKEN=$(curl -X POST http://localhost:9090/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"password": "SecurePassword123",
"remember_me": false
}' | jq -r '.token')
echo "Token: $TOKEN"
Get Boards:
curl -X GET http://localhost:9090/api/v1/boards/ \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json"
Create Board:
curl -X POST "http://localhost:9090/api/v1/boards/?board_name=My%20API%20Board" \
-H "Authorization: Bearer $TOKEN"
Best Practices
Token Storage
Do:
- Store tokens securely (keychain, secure storage)
- Use HTTPS to transmit tokens
- Clear tokens on logout
- Handle token expiration gracefully
Don’t:
- Store tokens in URL parameters
- Log tokens in plain text
- Share tokens between users
- Store tokens in version control
Error Handling
Always handle authentication errors:
def make_request(client, func, *args, **kwargs):
max_retries = 3
retry_count = 0
while retry_count < max_retries:
try:
return func(*args, **kwargs)
except AuthenticationError:
if retry_count >= max_retries - 1:
raise
# Re-authenticate
client.login(email, password)
retry_count += 1
except Exception as e:
logger.error(f"Request failed: {e}")
raise
Rate Limiting
Be mindful of API rate limits:
- Implement exponential backoff for retries
- Cache frequently accessed data
- Batch requests when possible
- Don’t hammer the login endpoint
Troubleshooting
Common Issues
Issue: “Invalid authentication credentials”
- Token expired — re-authenticate
- Token malformed — check token string
- Token signature invalid — check secret key hasn’t changed
Issue: Token not being sent
- Check
Authorizationheader is present - Verify
Bearerprefix is included - Check token isn’t truncated
Additional Resources
- User Guide — For end users
- Administrator Guide — For administrators
- GitHub Repository — Source code
Questions?
Visit the InvokeAI Discord or check the FAQ.