Skip to content

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