OpenAI-compatible endpoints. Drop-in replacement for most AI tools.
https://lumirouter.com/v1
Preferred: Create an account (accepts
Terms + Privacy) and save the lr_… key shown once.
API clients use Authorization: Bearer YOUR_API_KEY. The site/dashboard also uses an HTTP-only lr_session cookie.
Authorization: Bearer YOUR_API_KEY
Legacy: POST /v1/keys still issues a one-shot email key without a password account (see below).
Full account API under /v1/auth/*. Technical reference: repo docs/api.md.
Requires accepted_terms: true. Password min 8 characters. Returns api_key once and sets session cookie.
curl -X POST https://lumirouter.com/v1/auth/register \
-H "Content-Type: application/json" \
-d '{"email":"you@example.com","password":"at-least-8","accepted_terms":true}'
curl -X POST https://lumirouter.com/v1/auth/login \
-H "Content-Type: application/json" \
-c cookies.txt -d '{"email":"you@example.com","password":"…"}'
Forgot password → email link → reset-password.html?token=…. Valid emails get a generic 200 (anti-enumeration). Token is single-use, ~1 hour.
curl -X POST https://lumirouter.com/v1/auth/forgot-password \
-H "Content-Type: application/json" \
-d '{"email":"you@example.com"}'
Session or Bearer required. Old key stops working immediately; BYOK stays with the new key. Dashboard: API Key → Rotate key. Limit: 5 / hour.
curl -X POST https://lumirouter.com/v1/auth/rotate-key \ -H "Authorization: Bearer YOUR_LUMIROUTE_KEY"
Already have a key from POST /v1/keys?
Claim your account with email + key + password.
Same lr_… key is kept. Requires accepted_terms: true.
curl -X POST https://lumirouter.com/v1/auth/claim-account \
-H "Content-Type: application/json" \
-d '{"email":"you@example.com","api_key":"lr_…","password":"at-least-8","accepted_terms":true}'
No auth. One key per email (shown once). IP limit: 5 / hour. Prefer register for new users. To rotate an account key, use rotate-key.
curl -X POST https://lumirouter.com/v1/keys \
-H "Content-Type: application/json" \
-d '{"email":"you@example.com"}'
Recommended. Register your Groq/DeepSeek/Gemini/OpenAI keys once, then use only the LumiRoute API key in Cursor/Cline. You keep provider billing and ToS; we add routing + an OpenAI-compatible gateway.
curl -X POST https://lumirouter.com/v1/byok/keys \
-H "Authorization: Bearer YOUR_LUMIROUTE_KEY" \
-H "Content-Type: application/json" \
-d '{"groq":"gsk_...","deepseek":"sk_...","gemini":"AIza...","openai":"sk-..."}'
Check status (secrets never returned):
curl https://lumirouter.com/v1/byok/keys \ -H "Authorization: Bearer YOUR_LUMIROUTE_KEY"
{ "configured": { "groq": true, "deepseek": false, "gemini": true, "openai": true } }
Omit a field to leave it unchanged; send "" to delete that provider key.
https://lumirouter.com/v1auto, lr-gemini-2.5-flash, or byok/openai/gpt-6.1-solbyok/openai/gpt-image-2) in Cursor chat — use Images insteadhttps://lumirouter.com/v1auto, lr-gemini-2.5-flash, or byok/openai/gpt-6.1-solX-LumiRoute-*-Key headers if you prefer not to use KVAuthorization: Bearer YOUR_LUMIROUTE_KEY X-LumiRoute-Groq-Key: gsk_... X-LumiRoute-DeepSeek-Key: sk_... X-LumiRoute-Gemini-Key: AIza... X-LumiRoute-OpenAI-Key: sk-...
Headers override KV for that request.
On upstream 401 / 402 / 403 / 429 / 503, we try the next BYOK provider, then Cloudflare Workers AI:
Groq → Gemini → DeepSeek → OpenAI → CF.
Check lumiroute.route_reason in the JSON response.
LumiRoute Images API (JSON). Use POST /v1/images
(alias: /v1/images/generations).
Image models are not valid on /v1/chat/completions.
Requires OpenAI BYOK.
Text → image (no references):
curl https://lumirouter.com/v1/images \
-H "Authorization: Bearer YOUR_LUMIROUTE_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "byok/openai/gpt-image-2",
"prompt": "A product photo of a ceramic mug on a white table",
"size": "1024x1024"
}'
Image input → edit — same endpoint with
input_references. We forward to OpenAI
/v1/images/edits. Each ref is a data URL or https URL:
curl https://lumirouter.com/v1/images \
-H "Authorization: Bearer YOUR_LUMIROUTE_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "byok/openai/gpt-image-2",
"prompt": "Keep the product; replace the background with a warm sunset",
"input_references": [
{
"type": "image_url",
"image_url": { "url": "data:image/png;base64,...." }
}
]
}'
Optional fields: n, quality, size,
response_format, background, output_format,
mask (data/https URL for edits).
Up to 16 reference images (GPT Image models).
Image model ids:
byok/openai/gpt-image-2 — current flagship (gen + edit)byok/openai/gpt-image-1.5 / gpt-image-1 / gpt-image-1-minibyok/openai/dall-e-3 — generate only (edits not supported upstream)byok/openai/dall-e-2
In your app:
POST https://lumirouter.com/v1/images with model + prompt;
add input_references when you have a source image.
No auth. Returns Cloudflare availability, BYOK hint, and whether operator secrets exist (not used publicly).
curl https://lumirouter.com/health
Legacy email key issue (see above). Prefer register + rotate-key for accounts.
Rotate gateway key (see Accounts).
Send a chat completion request. Fully OpenAI-compatible. stream: true pipes live SSE from upstream (Groq/Gemini/DeepSeek/OpenAI/CF). Image models are rejected here — use Images.
OpenAI Images BYOK (generate + edit via input_references). Alias: /v1/images/generations. See Image generation.
List all available models including auto-routing options and image models.
Store or update your provider keys (see BYOK above).
Show which providers are configured (boolean only).
| Model | Behavior |
|---|---|
auto | Smart routing based on request content |
auto-cheap | Always cheapest sufficient model |
auto-code | Code-focused model (DeepSeek Coder) |
auto-quality | Highest quality model available |
| Model | Provider |
|---|---|
deepseek-chat | DeepSeek |
deepseek-coder | DeepSeek |
deepseek-reasoner | DeepSeek |
openai/gpt-oss-20b | Groq |
openai/gpt-oss-120b | Groq |
lr-gemini-2.5-flash | Gemini (use this in Cursor, not built-in Gemini) |
lr-gemini-3.6-flash | Gemini |
byok/openai/gpt-6-luna | OpenAI chat (BYOK) |
byok/openai/gpt-6.1-sol | OpenAI chat (BYOK) |
byok/openai/gpt-6-astra | OpenAI chat (BYOK) |
byok/openai/o4-mini | OpenAI reasoning (BYOK) |
byok/openai/o3 | OpenAI reasoning (BYOK) |
byok/openai/gpt-4.1 / gpt-4.1-mini | OpenAI chat (BYOK) |
byok/openai/gpt-4o / gpt-4o-mini | OpenAI chat (BYOK) |
byok/openai/gpt-image-2 | OpenAI Images — use /v1/images/generations |
byok/openai/gpt-image-1.5 / gpt-image-1 / gpt-image-1-mini | OpenAI Images |
byok/openai/dall-e-3 / dall-e-2 | OpenAI Images |
cf-granite-micro | Cloudflare |
cf-llama-3.2-1b | Cloudflare |
cf-llama-3.2-3b | Cloudflare |
cf-gpt-oss-20b | Cloudflare |
cf-gpt-oss-120b | Cloudflare |
cf-mistral-small-24b | Cloudflare |
cf-qwen3-30b | Cloudflare |
cf-qwen2.5-coder-32b | Cloudflare |
cf-qwq-32b | Cloudflare |
cf-deepseek-r1-32b | Cloudflare |
cf-llama-4-scout | Cloudflare |
cf-llama-3.3-70b | Cloudflare |
curl https://lumirouter.com/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "auto",
"messages": [
{"role": "user", "content": "Write a Python function to reverse a string"}
]
}'
When using auto models, the response includes a lumiroute field:
{
"model": "deepseek-coder",
"choices": [...],
"lumiroute": {
"requested_model": "auto",
"routed_model": "deepseek-coder",
"provider": "deepseek",
"route_reason": "code keywords detected"
}
}
Works with any tool that supports custom OpenAI-compatible endpoints:
Set base URL to https://lumirouter.com/v1 and use your LumiRoute API key.