Skip to content

Quick Start

Doc Version: 1.2.2 Last Updated: 2026-09-18 Applicable Version: v3.1.1+ Author: Lincoln

This guide will help you make your first API call to JAiRouter and understand the basic concepts.

Learning Objectives

After completing this guide, you will be able to: - Start JAiRouter service - Configure your first AI model service - Send API requests and receive responses - Experience load balancing and rate limiting

Prerequisites

  • JAiRouter is installed and running (see Installation Guide)
  • At least one AI model service is configured and accessible

The production profile (prod) deliberately ships no default JWT key, so you need to generate one with at least 32 characters.

💡 Tip: You can use the built-in key generator in the image:

docker run --rm sodlinken/jairouter:latest --generate-key
Alternatively, use the command-line methods below:

Linux / macOS / Git Bash

# Generate a Base64-encoded JWT key (32 bytes → 44 characters)
openssl rand -base64 32

Windows PowerShell

# Generate a Base64-encoded JWT key
[Convert]::ToBase64String((1..32 | ForEach-Object {Get-Random -Maximum 256}))

Set Environment Variables

# Set the JWT key (replace with the value generated above)
export JWT_SECRET="your-base64-encoded-secret"

# Optional: override the admin password (production only)
export INITIAL_ADMIN_PASSWORD="your-own-strong-password"

💡 Tip: For quick local testing (dev profile), no key configuration is required — a built-in development key is included. The JWT_SECRET is only needed for production. 🔐 Default console login: admin / ChangeMeOnFirstStartup123456 (created automatically only when the account table is empty). In production, override it with INITIAL_ADMIN_PASSWORD as shown above; otherwise change it after the first login.

Login Page

Management Console

Your First API Call

1. Chat Completion

Make a chat completion request using the OpenAI-compatible API:

curl -X POST http://localhost:8080/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "X-API-Key: <API key created in the console>" \
  -d '{
    "model": "qwen2.5:7b",
    "messages": [
      {
        "role": "user",
        "content": "Hello, how are you?"
      }
    ],
    "max_tokens": 100
  }'

2. Text Embeddings

Generate text embeddings:

curl -X POST http://localhost:8080/v1/embeddings \
  -H "Content-Type: application/json" \
  -d '{
    "model": "text-embedding-ada-002",
    "input": "Hello world"
  }'

Prerequisites: a management token

The commands in this section call the management API, which is authenticated — without a token they return 401 {"error":{"code":"AUTH_MISSING"}}. Get a JWT once per shell and reuse it (the dev default account is admin / ChangeMeOnFirstStartup123456; change it in production):

TOKEN=$(curl -s -X POST -H "Content-Type: application/json" \
  -d '{"username":"admin","password":"ChangeMeOnFirstStartup123456"}' \
  http://localhost:8080/api/auth/jwt/login | jq -r .data.token)

Every command below then sends it as -H "Jairouter_Token: $TOKEN". Note the header name: the JWT header is Jairouter_Token (configurable via jairouter.security.jwt.jwt-header), not Authorization: Bearer.

Common Configuration Examples

Online API Services

OpenAI GPT

curl -X POST "http://localhost:8080/api/config/instance/chat" \
  -H "Jairouter_Token: $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "gpt-4o",
    "baseUrl": "https://api.openai.com",
    "path": "/v1/chat/completions",
    "adapter": "normal",
    "headers": {
      "Authorization": "Bearer sk-proj-xxxxx"
    }
  }'

DeepSeek

curl -X POST "http://localhost:8080/api/config/instance/chat" \
  -H "Jairouter_Token: $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "deepseek-chat",
    "baseUrl": "https://api.deepseek.com",
    "path": "/v1/chat/completions",
    "adapter": "normal",
    "headers": {
      "Authorization": "Bearer sk-xxxxxxxx"
    }
  }'

Anthropic Claude

curl -X POST "http://localhost:8080/api/config/instance/chat" \
  -H "Jairouter_Token: $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "claude-sonnet",
    "baseUrl": "https://api.anthropic.com",
    "path": "/v1/messages",
    "adapter": "claude",
    "headers": {
      "x-api-key": "sk-ant-api03-xxxxx"
    }
  }'

Note: The Claude adapter automatically injects the anthropic-version header.

Google Gemini

curl -X POST "http://localhost:8080/api/config/instance/chat" \
  -H "Jairouter_Token: $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "gemini-pro",
    "baseUrl": "https://generativelanguage.googleapis.com/v1beta/openai",
    "path": "/chat/completions",
    "adapter": "normal",
    "headers": {
      "Authorization": "Bearer AIzaSyxxxxx"
    }
  }'

Local Inference Engines

Ollama

curl -X POST "http://localhost:8080/api/config/instance/chat" \
  -H "Jairouter_Token: $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "llama3.2:3b",
    "baseUrl": "http://localhost:11434",
    "path": "/api/chat",
    "adapter": "ollama"
  }'

vLLM

curl -X POST "http://localhost:8080/api/config/instance/chat" \
  -H "Jairouter_Token: $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "vllm-qwen",
    "baseUrl": "http://localhost:8000",
    "path": "/v1/chat/completions",
    "adapter": "vllm"
  }'

Tip: For more configuration examples, see Instance Configuration Examples.

View Service Status

Check Instance List

# Get all chat service instances
curl -H "Jairouter_Token: $TOKEN" "http://localhost:8080/api/config/instance/chat"

View Monitoring Metrics

🔑 Admin credentials are required**: the /actuator/** calls below go through the normal authentication chain — only

/actuator/health (including the liveness / readiness sub-paths), /actuator/info and /actuator/prometheus are anonymous (for k8s probes and Prometheus scraping); everything else needs the ADMIN role. Without credentials you get 401 AUTH_MISSING. (Before the fix even a valid ADMIN JWT got 401: the auth chain was excluded while hasRole("ADMIN") was still required, so the two cancelled out — see issue #340.)

Fetch a JWT and call the endpoint (verified locally):

TOKEN=$(curl -s -X POST http://localhost:8080/api/auth/jwt/login \
  -H 'Content-Type: application/json' \
  -d '{"username":"admin","password":"<your admin password>"}' | jq -r .data.token)
curl -s -H "Jairouter_Token: $TOKEN" http://localhost:8080/actuator/metrics | jq
# View application metrics
curl "http://localhost:8080/actuator/metrics"

# View specific metrics (e.g., request count)
curl "http://localhost:8080/actuator/metrics/http.server.requests"

Experience Load Balancing

Add a second service instance to experience load balancing:

# Add another instance
curl -X POST "http://localhost:8080/api/config/instance/chat" \
  -H "Jairouter_Token: $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "llama3.2:1b",
    "baseUrl": "http://localhost:11434",
    "path": "/v1/chat/completions",
    "adapter": "ollama",
    "weight": 2
  }'

Now send multiple requests, and JAiRouter will distribute them based on the configured load balancing strategy (default: round-robin).

Next Steps

Next StepContentSuitable For
First Steps GuideIn-depth configuration and production preparationReady to use in projects
Configuration GuideDetailed configuration parametersNeed specific configuration
API ReferenceComplete API documentationDevelopment integration
Deployment GuideProduction environment deploymentGoing live

Troubleshooting

Q: Service fails to start?

A: Check the following: 1. Port 8080 is not occupied 2. Java version is 17+ 3. Check logs for detailed error information

Q: Cannot connect to backend AI service?

A: Confirm: 1. Backend service is running normally 2. Network connection is normal 3. Configured URL and port are correct

Q: API call returns error?

A: Check: 1. Request format is correct 2. Model name matches 3. Check JAiRouter logs for detailed information