Adding a New Service¶
Adding a new upstream API service to KeyPool is config-only. No code changes required.
Step 1: Insert Service Config¶
Via admin API:
curl -X POST https://keypool.yourdomain.com/admin/services \
-H "Authorization: Bearer YOUR_ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "openai",
"display_name": "OpenAI",
"base_url": "https://api.openai.com",
"auth_scheme": "bearer",
"rate_limit_rpm": 60
}'
Or directly in D1:
INSERT INTO services (name, display_name, base_url, auth_scheme, rate_limit_rpm)
VALUES ('openai', 'OpenAI', 'https://api.openai.com', 'bearer', 60);
Step 2: Add API Keys¶
curl -X POST https://keypool.yourdomain.com/admin/keys \
-H "Authorization: Bearer YOUR_ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"service": "openai",
"key_value": "sk-abc123...",
"balance_total": 5.00,
"balance_unit": "usd",
"account_email": "user1@example.com"
}'
Step 3: Configure SDK¶
Point your SDK to the KeyPool proxy:
import OpenAI from 'openai';
const client = new OpenAI({
apiKey: 'your-team-token', // KeyPool team token, NOT a real OpenAI key
baseURL: 'https://keypool.yourdomain.com/v1/openai',
});
Auth Schemes¶
| Value | Upstream Header | Services |
|---|---|---|
bearer |
Authorization: Bearer {key} |
Firecrawl, Groq, Tavily, OpenAI |
x-api-key |
x-api-key: {key} |
Exa, Serper, Cartesia |
xi-api-key |
xi-api-key: {key} |
ElevenLabs |
authorization-raw |
Authorization: {key} |
AssemblyAI |
authorization-token |
Authorization: Token {key} |
Deepgram |
query-param |
?api_key={key} appended to URL |
Legacy APIs (upstream auth only; not a client→KeyPool auth method) |
Path Rewriting¶
The proxy strips the KeyPool prefix and forwards the rest to the upstream:
Client request: POST /v1/exa/search
Upstream request: POST https://api.exa.ai/search
Client request: POST /v1/groq/openai/v1/chat/completions
Upstream request: POST https://api.groq.com/openai/v1/chat/completions
SDK Compatibility¶
| Service | Custom URL Support | Notes |
|---|---|---|
| Exa | ✅ baseURL option |
Works out of the box |
| Firecrawl | ✅ apiUrl option |
Works out of the box |
| AssemblyAI | ✅ baseUrl in config |
Works out of the box |
| Groq | ✅ baseURL (OpenAI-compat) |
Works out of the box |
| Tavily | ✅ api_key + base_url |
Pass api_key as team token, override base_url |
| Serper | ✅ raw HTTP | Use x-api-key auth with /search and /images endpoints |
| ElevenLabs | ✅ baseUrl option (@elevenlabs/elevenlabs-js) / base_url (elevenlabs Python) |
Pass KeyPool team token as SDK apiKey; KeyPool accepts xi-api-key inbound and injects upstream xi-api-key |
| Cartesia | ✅ baseURL option (@cartesia/cartesia-js) / base_url (cartesia Python) |
Pass KeyPool team token as SDK apiKey; Cartesia-Version header injected automatically via proxy_headers |
| Deepgram | ✅ JS: createClient(apiKey, { global.fetch.options.url }); Python: DeepgramClient(api_key, httpx_client=httpx.Client(base_url=...)) |
Uses Authorization: Token {key} upstream; keypool route is /v1/deepgram |