AuthenticationAuthentication

Chapter 2: Authentication

Overview

The Polysystems Backend API uses a dual-authentication system to provide both security and flexibility:

  1. JWT (JSON Web Tokens) - For account management and administrative operations
  2. 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 Again

JWT Protected Endpoints

The following endpoints require JWT authentication:

EndpointMethodDescription
/api/auth/meGETGet current user info
/api/auth/change-passwordPOSTChange password
/api/keysPOSTGenerate access token
/api/keysGETList access tokens
/api/keys/{id}/revokePOSTRevoke access token
/api/keys/{id}DELETEDelete access token
/api/keys/{id}/limitsPUTSet 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_x9y8z7w6v5u4t3s2r1q0p9o8n7m6l5k4

Prefix Meanings:

  • ps_live_ - Production environment token
  • ps_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:

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 GroupBase PathDescription
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 Response

Security 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_here

Staging 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_here

Production Environment

# .env.production (use secrets manager instead)
PS_API_URL=https://api.polysystems.ai
PS_API_KEY=ps_live_production_token_here

Authentication 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