de Publieke Partner — AI Proxy Router Documentation
A Cloudflare Worker-based AI prompt router with multi-provider support, priority-based fallback, and usage analytics.
Features
- Multi-Provider Support — Route prompts to 1min.ai, Straico, OpenAI, and more
- Priority-Based Fallback — Automatic failover when providers are unavailable
- Credit-Based Routing — Select models based on available credits
- Usage Analytics — Track calls, tokens, latency, and errors
- Admin UI — Visual configuration interface
- Google OAuth — Secure admin access restricted to @depubliekepartner.nl
Architecture
┌─────────────┐ ┌──────────────────┐ ┌─────────────┐
│ Client │────▶│ Worker (Hono) │────▶│ AI Provider│
└─────────────┘ └────────┬─────────┘ └─────────────┘
│
┌────────▼─────────┐
│ D1 (SQLite) │
│ - providers │
│ - models │
│ - api_keys │
│ - routes │
│ - usage_logs │
└──────────────────┘
Quick Start
Get started with the AI Router API in minutes.
Base URL
https://ai-router.dpp-ai.workers.dev
Basic Request
curl -X POST https://ai-router.dpp-ai.workers.dev/v1/prompt \
-H "Authorization: Bearer $PROXY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "Explain quantum computing in simple terms"
}'
Response
{
"response": "Quantum computing uses quantum mechanics...",
"provider": "openai",
"model": "gpt-4o",
"usage": {
"prompt_tokens": 8,
"completion_tokens": 150
}
}
Authentication
The prompt API requires an API key. Admin endpoints require Google OAuth authentication.
Prompt API Key
Include an API key on every /v1/prompt request.
Authorization: Bearer <key>
x-api-key: <key>
Admin access is restricted to @depubliekepartner.nl Google accounts only.
Admin Authentication Flow
- Navigate to
/auth/login - Sign in with your @depubliekepartner.nl Google account
- You'll be redirected back with a session cookie
- All
/admin/*endpoints will now work
Logout
GET /auth/logout
Prompt API
The main endpoint for sending prompts to AI providers. Include Authorization: Bearer <key> or x-api-key on every request.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
prompt | string | Yes | The prompt text to send |
credits | number | No | Available credits (filters routes by min_credits) |
provider | string | No | Force specific provider (e.g., "openai") |
model | string | No | Force specific model (e.g., "gpt-4o") |
Response
| Field | Type | Description |
|---|---|---|
response | string | The AI-generated response |
provider | string | Provider that handled the request |
model | string | Model that generated the response |
usage | object | Token usage statistics |
Example with Options
curl -X POST https://ai-router.dpp-ai.workers.dev/v1/prompt \
-H "Authorization: Bearer $PROXY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "Write a haiku about coding",
"credits": 100,
"provider": "openai"
}'
Providers
Manage AI provider configurations.
Provider Object
| Field | Type | Description |
|---|---|---|
id | string | Unique identifier |
name | string | Display name |
base_url | string | API endpoint URL |
auth_type | string | Authentication type (default: "api_key") |
priority | number | Lower = higher priority |
active | number | 1 = enabled, 0 = disabled |
Pre-configured Providers
| ID | Name | Base URL |
|---|---|---|
1min | 1min.ai | https://api.1min.ai/api/features |
straico | Straico | https://api.straico.com/v0/prompt/completion |
openai | OpenAI | https://api.openai.com/v1/chat/completions |
Models
Manage AI model configurations per provider.
Model Object
| Field | Type | Description |
|---|---|---|
id | string | Unique identifier |
provider_id | string | Reference to provider |
model_id | string | Provider's model identifier |
name | string | Display name |
cost_per_1k | number | Cost per 1000 tokens |
active | number | 1 = enabled, 0 = disabled |
Routes
Configure routing rules for prompt distribution.
Route Object
| Field | Type | Description |
|---|---|---|
id | string | Unique identifier |
name | string | Display name |
provider_id | string | Target provider |
model_id | string | Target model |
priority | number | Lower = tried first |
min_credits | number | Minimum credits required |
active | number | 1 = enabled, 0 = disabled |
Routes are sorted by priority (ascending). The router tries each route in order until one succeeds. If a provider fails, it automatically falls back to the next route.
API Keys
Manage API keys for providers. Keys are stored encrypted and never exposed in responses.
Creating an API Key
curl -X POST https://ai-router.dpp-ai.workers.dev/admin/keys \
-H "Content-Type: application/json" \
-H "Cookie: ai_router_session=..." \
-d '{
"provider_id": "openai",
"key_value": "sk-...",
"label": "Production Key"
}'
Statistics
View usage analytics and performance metrics.
Query Parameters
| Parameter | Default | Description |
|---|---|---|
range | 7d | Time range (e.g., "7d", "30d") |
Response
[
{
"provider_id": "openai",
"total_calls": 1500,
"success_count": 1480,
"error_count": 20,
"avg_latency": 245.5,
"total_tokens": 150000
}
]
Adding Custom Providers
Extend the router with additional AI providers.
1. Add Provider Handler
Edit src/providers.ts:
export async function callCustomProvider(o: CallOpts): Promise<AIResp> {
const res = await fetch(o.baseUrl, {
method: 'POST',
headers: {
'Authorization': \`Bearer \${o.apiKey}\`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: o.model,
prompt: o.prompt,
}),
});
const data = await res.json();
return {
response: data.text,
provider: 'custom',
model: o.model,
usage: data.usage,
};
}
// Register in getProviderFn
export function getProviderFn(id: string) {
const map = {
'1min': call1min,
'straico': callStraico,
'openai': callOpenAI,
'custom': callCustomProvider, // Add here
};
return map[id] || null;
}
2. Add Provider via Admin
curl -X POST https://ai-router.dpp-ai.workers.dev/admin/providers \
-H "Content-Type: application/json" \
-d '{
"id": "custom",
"name": "Custom Provider",
"base_url": "https://api.custom.ai/v1/complete",
"priority": 4
}'
Fallback Routing
Configure automatic failover between providers.
Strategy
- Routes sorted by
priority(ascending) - First matching route is attempted
- On failure, next route is tried
- All failures logged to
usage_logs
Example Configuration
// Primary: OpenAI GPT-4
{ "name": "Primary", "provider_id": "openai", "model_id": "gpt-4o", "priority": 1 }
// Fallback 1: Straico Claude
{ "name": "Fallback 1", "provider_id": "straico", "model_id": "claude-3-5-sonnet", "priority": 2 }
// Fallback 2: 1min.ai
{ "name": "Fallback 2", "provider_id": "1min", "model_id": "gpt-4o", "priority": 3 }
Error Handling
Understanding API error responses.
HTTP Status Codes
| Code | Meaning |
|---|---|
200 | Success |
400 | Bad request (missing prompt, no eligible routes) |
401 | Unauthorized (admin routes without auth) |
403 | Forbidden (wrong domain) |
500 | Server error (no routes configured) |
502 | All providers failed |
Error Response Format
{
"error": "Error message describing what went wrong"
}