Chapter 2: Authentication
Overview
The Polysystems Backend API uses a dual-authentication system to provide both security and flexibility:
- JWT (JSON Web Tokens) - For account management and administrative operations
- Access Tokens (API Keys) - For API endpoint access in production applications
This chapter explains both authentication methods, when to use each, and best practices for securing your applications.
Authentication Architecture
┌─────────────────────────────────────────────────────────────┐
│ User Account │
│ (Email/Password Authentication) │
└──────────────────────┬──────────────────────────────────────┘
│
▼
┌────────────────┐
│ JWT Token │ ◄─── Account Management
│ (Short-lived) │ • Generate API Keys
└────────────────┘ • Manage Settings
│ • View Billing
│
▼
┌─────────────────────────┐
│ Access Tokens │ ◄─── API Endpoint Access
│ (Long-lived API Keys) │ • Hub API
│ │ • OMM API
└─────────────────────────┘ • Yggdrasil API
│ • Domain APIs
│
▼
┌────────────────┐
│ API Endpoints │
└────────────────┘JWT Authentication
What are JWT Tokens?
JWT (JSON Web Tokens) are short-lived tokens used for account-level operations. They contain encoded user information and expire after a set period (default: 24 hours).
When to Use JWT Tokens
Use JWT tokens for:
- User registration and login
- Generating and managing access tokens
- Updating account settings
- Managing payment methods
- Viewing transaction history
- Configuring webhooks
Obtaining a JWT Token
Registration
curl -X POST https://api.polysystems.ai/api/auth/register \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"password": "SecurePassword123!",
"username": "myusername"
}'Response:
{
"id": "user-550e8400-e29b-41d4-a716-446655440000",
"email": "user@example.com",
"username": "myusername",
"role": "user",
"is_email_verified": false,
"created_at": "2024-01-15T12:00:00Z"
}Login
curl -X POST https://api.polysystems.ai/api/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"password": "SecurePassword123!"
}'Response:
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user": {
"id": "user-550e8400-e29b-41d4-a716-446655440000",
"email": "user@example.com",
"username": "myusername",
"role": "user"
}
}Using JWT Tokens
Include the JWT token in the Authorization header with the Bearer scheme:
curl -X GET https://api.polysystems.ai/api/auth/me \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."JWT Token Lifecycle
Register/Login → Receive Token → Use Token (24h) → Token Expires → Login AgainJWT Protected Endpoints
The following endpoints require JWT authentication:
| Endpoint | Method | Description |
|---|---|---|
/api/auth/me | GET | Get current user info |
/api/auth/change-password | POST | Change password |
/api/keys | POST | Generate access token |
/api/keys | GET | List access tokens |
/api/keys/{id}/revoke | POST | Revoke access token |
/api/keys/{id} | DELETE | Delete access token |
/api/keys/{id}/limits | PUT | Set spending limits |
/api/payments/* | * | All payment endpoints |
/api/monitoring/* | * | All monitoring endpoints |
Access Token Authentication
What are Access Tokens?
Access tokens (also called API keys) are long-lived credentials designed for programmatic API access. They are scoped to your account and can be individually managed, revoked, and rate-limited.
When to Use Access Tokens
Use access tokens for:
- Production applications
- Server-to-server communication
- Long-running services
- Third-party integrations
- Mobile and desktop applications
- Any programmatic API access
Access Token Format
Access tokens follow this format:
ps_{environment}_{random_string}
Examples:
ps_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6
ps_test_x9y8z7w6v5u4t3s2r1q0p9o8n7m6l5k4Prefix Meanings:
ps_live_- Production environment tokenps_test_- Test/development environment token
Generating Access Tokens
Access tokens are generated using your JWT token:
curl -X POST https://api.polysystems.ai/api/keys \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Production API Key",
"expires_at": null
}'Response:
{
"id": "key-123e4567-e89b-12d3-a456-426614174000",
"name": "Production API Key",
"key_value": "ps_live_abcdef123456789",
"is_active": true,
"created_at": "2024-01-15T12:00:00Z",
"expires_at": null
}⚠️ Important: The key_value is only displayed once. Save it immediately!
Using Access Tokens
Access tokens can be provided in two ways:
Method 1: X-API-Key Header (Recommended)
curl -X POST https://api.polysystems.ai/api/hub/agents/chat \
-H "X-API-Key: ps_live_abcdef123456789" \
-H "Content-Type: application/json" \
-d '{
"messages": [{"role": "user", "content": "Hello!"}]
}'Method 2: Authorization Bearer Header
curl -X POST https://api.polysystems.ai/api/hub/agents/chat \
-H "Authorization: Bearer ps_live_abcdef123456789" \
-H "Content-Type: application/json" \
-d '{
"messages": [{"role": "user", "content": "Hello!"}]
}'Access Token Protected Endpoints
The following API groups require access token authentication:
| API Group | Base Path | Description |
|---|---|---|
| Polysystems Hub | /api/hub/* | Agent management, memory, tasks, RAG |
| OMM | /api/omm/* | Omni-modal AI processing |
| Yggdrasil | /api/yggdrasil/* | Advanced AI services |
| V1 Compatibility | /v1/* | OpenAI-compatible endpoints |
Access Token Expiration
Access tokens can be configured with optional expiration dates:
# Create token that expires in 30 days
curl -X POST https://api.polysystems.ai/api/keys \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Temporary API Key",
"expires_at": "2024-02-15T12:00:00Z"
}'Note: Tokens with expires_at: null never expire unless manually revoked.
Authentication Middleware Flow
Request Processing Pipeline
Incoming Request
│
▼
┌─────────────────┐
│ Rate Limiting │ ← Check request rate
└─────────────────┘
│
▼
┌─────────────────┐
│ Authentication │ ← Validate token/key
└─────────────────┘
│
▼
┌─────────────────┐
│ Pricing Check │ ← Calculate cost
└─────────────────┘
│
▼
┌─────────────────┐
│ Balance Check │ ← Verify sufficient credits
└─────────────────┘
│
▼
┌─────────────────┐
│ Spending Limits │ ← Check key limits
└─────────────────┘
│
▼
┌─────────────────┐
│ Deduct Credits │ ← Charge account
└─────────────────┘
│
▼
┌─────────────────┐
│ Process Request │ ← Execute API call
└─────────────────┘
│
▼
┌─────────────────┐
│ Log Usage │ ← Record transaction
└─────────────────┘
│
▼
Return ResponseSecurity Best Practices
1. Token Storage
❌ Don’t:
- Hardcode tokens in source code
- Commit tokens to version control
- Store tokens in client-side code (web browsers)
- Share tokens publicly or in screenshots
- Log tokens in application logs
✅ Do:
- Use environment variables
- Store in secure credential managers
- Use secrets management systems (AWS Secrets Manager, HashiCorp Vault)
- Rotate tokens regularly
- Use different tokens for different environments
2. Token Rotation
Regularly rotate your access tokens:
# 1. Generate new token
curl -X POST https://api.polysystems.ai/api/keys \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-d '{"name": "New Production Key"}'
# 2. Update your application with new token
# 3. Revoke old token
curl -X POST https://api.polysystems.ai/api/keys/{old_key_id}/revoke \
-H "Authorization: Bearer YOUR_JWT_TOKEN"3. Principle of Least Privilege
Create separate access tokens for different purposes:
# Development token with limits
curl -X POST https://api.polysystems.ai/api/keys \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-d '{
"name": "Development Token",
"expires_at": "2024-02-15T12:00:00Z"
}'
# Production token
curl -X POST https://api.polysystems.ai/api/keys \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-d '{
"name": "Production Token"
}'
# Set spending limits on development token
curl -X PUT https://api.polysystems.ai/api/keys/{dev_key_id}/limits \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-d '{
"daily_limit": 1.00,
"monthly_limit": 10.00
}'4. Monitor Token Usage
Regularly check which tokens are active and when they were last used:
curl -X GET https://api.polysystems.ai/api/keys \
-H "Authorization: Bearer YOUR_JWT_TOKEN"Response:
[
{
"id": "key-123",
"name": "Production API Key",
"key_value_preview": "ps_live_abcd...xyz9",
"is_active": true,
"last_used_at": "2024-01-15T12:45:00Z",
"created_at": "2024-01-01T10:00:00Z",
"expires_at": null
},
{
"id": "key-456",
"name": "Development Key",
"key_value_preview": "ps_live_wxyz...abc3",
"is_active": true,
"last_used_at": "2024-01-10T08:30:00Z",
"created_at": "2024-01-05T14:00:00Z",
"expires_at": "2024-02-15T12:00:00Z"
}
]5. Secure Password Practices
For JWT authentication (login):
- Use strong, unique passwords (minimum 12 characters)
- Enable two-factor authentication (if available)
- Don’t share account credentials
- Change passwords regularly
- Use a password manager
Environment-Specific Tokens
Development Environment
# .env.development
PS_API_URL=http://localhost:8080
PS_API_KEY=ps_test_dev_token_here
PS_JWT_TOKEN=dev_jwt_token_hereStaging Environment
# .env.staging
PS_API_URL=https://staging-api.polysystems.ai
PS_API_KEY=ps_live_staging_token_here
PS_JWT_TOKEN=staging_jwt_token_hereProduction Environment
# .env.production (use secrets manager instead)
PS_API_URL=https://api.polysystems.ai
PS_API_KEY=ps_live_production_token_hereAuthentication Error Responses
401 Unauthorized - Missing Token
{
"error": "Missing API key",
"message": "Expected 'X-API-Key' or 'Authorization: Bearer' header with access key"
}401 Unauthorized - Invalid Token
{
"error": "Invalid API key",
"message": "The provided access key is not valid"
}401 Unauthorized - Expired Token
{
"error": "API key expired",
"message": "This access key has expired"
}403 Forbidden - Insufficient Permissions
{
"error": "Access denied",
"message": "You do not have permission to access this resource"
}402 Payment Required - Insufficient Credits
{
"error": "Insufficient credits",
"message": "This request costs $0.0020 but your balance is insufficient. Please top up your account."
}402 Payment Required - Spending Limit Exceeded
{
"error": "Spending limit exceeded",
"message": "This access key has reached its spending limit. Please adjust limits or top up credits."
}Language-Specific Examples
Python
import os
import requests
# Store credentials in environment variables
API_KEY = os.getenv('PS_API_KEY')
BASE_URL = os.getenv('PS_API_URL', 'https://api.polysystems.ai')
# Using X-API-Key header
headers = {
'X-API-Key': API_KEY,
'Content-Type': 'application/json'
}
response = requests.post(
f'{BASE_URL}/api/hub/agents/chat',
headers=headers,
json={
'messages': [
{'role': 'user', 'content': 'Hello!'}
]
}
)
print(response.json())Node.js
const axios = require('axios');
const API_KEY = process.env.PS_API_KEY;
const BASE_URL = process.env.PS_API_URL || 'https://api.polysystems.ai';
async function callAPI() {
try {
const response = await axios.post(
`${BASE_URL}/api/hub/agents/chat`,
{
messages: [
{ role: 'user', content: 'Hello!' }
]
},
{
headers: {
'X-API-Key': API_KEY,
'Content-Type': 'application/json'
}
}
);
console.log(response.data);
} catch (error) {
console.error('Error:', error.response?.data || error.message);
}
}
callAPI();Go
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"os"
)
func main() {
apiKey := os.Getenv("PS_API_KEY")
baseURL := os.Getenv("PS_API_URL")
if baseURL == "" {
baseURL = "https://api.polysystems.ai"
}
payload := map[string]interface{}{
"messages": []map[string]string{
{"role": "user", "content": "Hello!"},
},
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", baseURL+"/api/hub/agents/chat", bytes.NewBuffer(jsonData))
req.Header.Set("X-API-Key", apiKey)
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
fmt.Println("Error:", err)
return
}
defer resp.Body.Close()
var result map[string]interface{}
json.NewDecoder(resp.Body).Decode(&result)
fmt.Println(result)
}cURL
#!/bin/bash
# Load from environment
API_KEY="${PS_API_KEY}"
BASE_URL="${PS_API_URL:-https://api.polysystems.ai}"
curl -X POST "${BASE_URL}/api/hub/agents/chat" \
-H "X-API-Key: ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"messages": [
{"role": "user", "content": "Hello!"}
]
}'Testing Authentication
Test JWT Authentication
# 1. Login
TOKEN=$(curl -X POST https://api.polysystems.ai/api/auth/login \
-H "Content-Type: application/json" \
-d '{"email": "user@example.com", "password": "password"}' \
| jq -r '.token')
# 2. Test JWT endpoint
curl -X GET https://api.polysystems.ai/api/auth/me \
-H "Authorization: Bearer $TOKEN"Test Access Token Authentication
# Test with access token
curl -X GET https://api.polysystems.ai/api/hub/health \
-H "X-API-Key: ps_live_your_token_here"Summary
In this chapter, you learned:
- ✅ The difference between JWT tokens and access tokens
- ✅ When to use each authentication method
- ✅ How to obtain and use JWT tokens
- ✅ How to generate and manage access tokens
- ✅ Security best practices for token management
- ✅ How to handle authentication errors
- ✅ Language-specific implementation examples
Next Steps
- Chapter 3: Access Tokens - Deep dive into access token management
- Chapter 4: API Routing - Explore available API endpoints
- Chapter 6: Spending Limits - Set up spending controls