One OpenAI-compatible endpoint. Twelve free LLM providers. Multimodal Vision, Image Gen, and Audio Speech/STT. ~1B+ tokens per month.
Aggregate the free tiers from Google, Groq, Cerebras, SambaNova, NVIDIA, Mistral, OpenRouter, GitHub Models, Cohere, Cloudflare, Pollinations, Z.ai (Zhipu), and Experiential Labs behind a unified OpenAI-compatible endpoint (/v1/chat/completions, /v1/images/*, /v1/audio/*). Keys are stored encrypted. An intelligent router picks the best available model for each request, handles multimodal inputs, falls over to the next provider when one is rate-limited, and tracks per-key usage so you stay under every free-tier cap.
- Why this exists
- Supported providers
- Features
- Not yet supported
- Quick start
- Admin-only access & dashboard security
- Using the API
- Screenshots
- How it works
- Limitations
- Contributing
- Terms of Service review
- Disclaimer
Every serious AI lab now offers a free tier — a few million tokens a month, a few thousand requests a day. On its own each tier is a toy. Stacked together, they add up to roughly 1.3 billion tokens per month of working inference capacity, across dozens of models from small-and-fast to reasonably capable.
The problem is that stacking them by hand is painful: fourteen different SDKs, fourteen different rate limits, fourteen places a request can fail. FreeLLMAPI collapses that into one OpenAI-compatible endpoint. Point any OpenAI client library at your local server, and it routes transparently across whichever providers you've added keys for.
- OpenAI-compatible —
POST /v1/chat/completions,POST /v1/completions,POST /v1/embeddings,POST /v1/moderations,POST /v1/images/*,POST /v1/audio/*, andGET /v1/modelswork with the official OpenAI SDKs and any OpenAI-compatible client (LangChain, LlamaIndex, Continue, Hermes, etc.). Just changebase_url. - Vector Embeddings (
/v1/embeddings) — OpenAI-standard text embedding generation with multi-provider failover across Googletext-embedding-004, Mistralmistral-embed, Cohereembed-english-v3.0/embed-multilingual-v3.0, and Cloudflarebge-base/bge-large. - Legacy Text Completions (
/v1/completions) — Full support for legacy prompt completions with streaming SSE and non-streaming response generation. - Content Moderation (
/v1/moderations) — Standard OpenAI content safety checks (hate, sexual, violence, self-harm, harassment) with provider integration and fallback safety analysis. - Multiple Choices (
n > 1) — Request multiple completions per call (n: 2..5) with parallel execution and aggregated token usage tracking. - Multi-tenant Auth & Client Token Budgets — Issue isolated client API keys (
freellm-client-...) for downstream applications, agents, or teams with custom RPM rate limits and monthly token budgets. - Multimodal Vision — OpenAI-standard
image_urlformat supported in/v1/chat/completionswith universal image format transcoding (HEIC, HEIF, TIFF, BMP, WebP, AVIF, PNG, JPEG, SVG) and dynamic vision-model routing. - AI Image Generation & Edits (
/v1/images/*) —POST /v1/images/generations,/v1/images/edits, and/v1/images/variationswith Pollinations Flux, Cloudflare Flux/SDXL, Google Imagen 3, and automatic zero-auth failover. - Audio Transcription, Translation & Speech (
/v1/audio/*) — Speech-to-text (/v1/audio/transcriptions,/v1/audio/translations) via Groq Whisper Large v3 / Turbo, Cloudflare Whisper, and Gemini Audio. Neural text-to-speech synthesis (/v1/audio/speech) with voices (alloy,echo,fable,onyx,nova,shimmer). - Streaming and non-streaming — Server-Sent Events for
stream: true, JSON response otherwise. Every provider adapter implements both. - Tool calling — OpenAI-style
tools/tool_choicerequests are passed through, and assistanttool_calls+toolrole follow-up messages round-trip across providers. - Automatic fallover — If the chosen provider returns a 429, 5xx, or times out, the router skips it, puts the key on a short cooldown, and retries on the next model in your fallback chain (up to 20 attempts).
- Global Key Cooldowns — If an API key encounters an error or hits rate limits on any model, it goes on a global cooldown for 1 hour across all models using that key to avoid redundant fallback loops.
- Per-key rate tracking — RPM, RPD, TPM, and TPD counters per
(platform, model, key)so the router always picks a key that's under its caps. - Sticky sessions — Multi-turn conversations keep talking to the same model for 30 minutes to avoid the hallucination spike that comes from mid-conversation model switches.
- Admin-Only Dashboard Access & API Protection — Secure
AuthGaterequiring scrypt-hashed credentials to access the UI and/api/*management endpoints, with brute-force rate limiting. - Hardware Passkeys & WebAuthn Biometrics — 1-click biometric sign-in via Touch ID, Windows Hello, Face ID, or FIDO2 security keys (YubiKey).
- One-Time Remote Setup Code — Generates an ephemeral 6-character code in server console logs on first boot to prevent unauthorized setup on public/cloud deployments (Render, Railway, Docker).
- Console-Based Password Recovery — Ephemeral 6-character reset codes logged directly to server console output for zero-dependency admin password recovery without SMTP or email services.
- Auto-Locking & Session Isolation — Sessions use browser
sessionStorageand a one-click header lock button to ensure unattended devices are instantly protected. - Encrypted key storage — API keys are encrypted with AES-256-GCM before hitting SQLite; decryption happens in-memory just before a request.
- Unified API key & Multi-tenant Keys — Clients authenticate with the master key or dedicated client API keys with token limits.
- Health checks — Periodic probes mark keys as
healthy,rate_limited,invalid, orerrorso the router skips dead ones automatically. - Playground & Media Studio — React + Vite UI with dedicated tabs for 💬 Chat & Vision, 🎨 Image Studio, 🎙️ Audio Lab, 🔢 Embeddings Lab (with cosine similarity comparison), and 🛡️ Moderation Inspector.
- Dedicated Cooldowns Page — Real-time tracking of sleeping keys with countdown timers and exact trigger errors.
- Automatic Sibling Sync — CLI tool (
npm run sync-keys) to scan adjacent repositories recursively and update their unified API key in.envconfigurations automatically. - Analytics — Per-request logging with latency, token counts, success rate, and per-provider breakdowns.
- Deploys to a Raspberry Pi — Runs happily on a Pi 4 under PM2 behind nginx. ~40 MB RSS at idle.
The scope is deliberately focused. If a feature isn't on this list and isn't below, assume it isn't there yet:
- Fine-tuning (
/v1/fine_tuning/jobs) - OpenAI Assistants API / Threads (legacy thread storage)
- Realtime WebRTC Audio API (bi-directional low-latency audio stream)
PRs that add any of these are very welcome. See Contributing.
Prerequisites: Node.js 20+, npm.
git clone https://github.com/byteWizard-zero/my-freellmapi-proxy.git
cd freellmapi
npm install
# Generate an encryption key for at-rest key storage
cp .env.example .env
echo "ENCRYPTION_KEY=$(node -e "console.log(require('crypto').randomBytes(32).toString('hex'))")" >> .env
# Start server + dashboard together
npm run devOpen http://localhost:5173 (the Vite dev UI). On first visit, set up your admin account (see Admin-Only Access), add your provider keys on the Provider Keys page, reorder the Fallback Chain to taste, and grab your unified API key. That unified key (freellmapi-...) is what you point your OpenAI SDK at.
For a production build:
npm run build
node server/dist/index.js # server + dashboard both served on :3001- Automatic Local Persistence: On first run, a unified key is generated and saved into
.envasUNIFIED_API_KEY=freellmapi-.... It automatically persists across server restarts and cold starts. - Cloud & Container Hosting (Render, Railway, Docker, Fly.io): On stateless container platforms where
.envfiles are not committed to git, set the environment variable in your cloud platform dashboard:This ensures your proxy endpoint always uses the same key across container redeployments and cold starts.UNIFIED_API_KEY=freellmapi-your-fixed-secret-key
- Dashboard Display: The React UI automatically fetches and displays the active key from the server. You don't need to manually configure anything inside the React UI.
If you have sibling coding projects on your machine that consume this proxy, you can automatically write the active unified API key directly to their .env files:
- Ensure your sibling repositories have a
.envor.env.localcontaining one of the standard key variables (e.g.OPENAI_API_KEY,UNIFIED_API_KEY,PROXY_API_KEY). - Run the sync command:
This tool scans all adjacent workspace folders recursively (up to depth 4), updates matching placeholders with your active unified API key, and prints diagnostics.
npm run sync-keys
FreeLLMAPI includes a built-in security perimeter that protects your upstream provider API keys, model routing configuration, client tenant keys, and usage analytics behind an AuthGate.
All management API routes (/api/*) require an authenticated admin session token. Downstream LLM consumer traffic (/v1/*) continues to authenticate separately via your master Unified API Key (freellmapi-...) or Client Project Keys (freellm-client-...).
When you run FreeLLMAPI for the first time, no admin account exists yet. Opening the web interface displays the Create Admin Account screen.
For security, FreeLLMAPI strictly enforces an AND gate requiring three credentials together: Admin Email, Password, AND the 6-character Setup Code:
- Open your dashboard URL (
http://localhost:5173,http://localhost:3001, or your remote cloud URL). - Check your server console logs (terminal output, Docker container logs, or cloud platform logs). On startup, the server generates and displays an ephemeral 6-character code:
======================================== Dashboard setup code: 9A4F2E (Required for admin account setup) ======================================== - Enter your Email, a strong Password (minimum 8 characters), and this 6-character Setup Code into the registration form.
- Click Create Account.
- Once your account is created, the setup code is permanently purged from memory, claiming admin ownership.
Once initialized, all subsequent visits require administrative authentication:
- Navigate to the dashboard URL.
- Enter your registered admin Email and Password.
- Click Sign in.
- Per-Visit Session Isolation: Session tokens are stored in the browser's
sessionStorage. If you close the browser tab or open a new window, you will be prompted to log in again. This prevents unauthorized access on shared or unattended computers. - Server-Side Expiry: Active sessions are validated against SQLite session token hashes (SHA-256) and expire after 30 days.
- Brute-Force Rate Limiting: The server tracks failed login attempts per client IP. After 5 failed attempts, further login requests from that IP are blocked for 15 minutes (
HTTP 429 Too Many Requests).
FreeLLMAPI supports FIDO2 / WebAuthn passwordless authentication. You can sign in using Touch ID, Windows Hello, Face ID, or physical security keys (e.g. YubiKey) without retyping your password.
- Log in to the dashboard using your email and password.
- If no passkey has been added yet, an alert banner appears at the top:
🔑 You haven't set up a Passkey yet. Set one up to sign in with your fingerprint or device PIN next time! (You can also click the Fingerprint icon
👆in the top-right header at any time). - Click Set up Passkey.
- Confirm the prompt presented by your browser or operating system (e.g. tap fingerprint scanner, scan face, or touch YubiKey).
- You can register passkeys across multiple devices (e.g. desktop, laptop, and phone).
- On future visits to the login screen, a highlighted button appears: "👆 Sign in with Fingerprint / Passkey".
- Click the button and authenticate with your biometric sensor or device PIN for instant 1-click access.
When leaving your workstation:
- Click the Lock icon (
🔒) in the top-right navigation bar. - The browser immediately wipes the session token from
sessionStorageand triggers a logout event. - The UI immediately resets to the sign-in screen, blocking further access to all dashboard management views and
/api/*endpoints.
If you forget your admin password, FreeLLMAPI includes a secure, zero-dependency recovery mechanism that works without needing external SMTP or email services:
- On the login screen, click "Forgot password?" below the password field.
- Enter your registered admin Email and click Send Reset Code.
- Check your server console output (e.g. terminal logs, Docker logs, or Render Dashboard Logs). FreeLLMAPI prints a time-limited 6-character reset code:
======================================== Password reset code: E7B841 Account: admin@example.com (Valid for 15 minutes) ======================================== - Enter the Reset Code, your New Password (minimum 8 characters), and confirm the password.
- Click Reset & Log In.
- FreeLLMAPI updates your password using scrypt hashing, invalidates all prior active sessions across all devices, and logs you into the dashboard with a new session.
All administrative backend routes (/api/keys, /api/client-keys, /api/models, /api/fallback, /api/analytics, /api/health, /api/settings) enforce authentication via the requireAuth middleware.
To interact with these management routes programmatically (e.g. from CI/CD, scripts, or external tools):
-
Obtain a Session Token:
curl -X POST http://localhost:3001/api/auth/login \ -H "Content-Type: application/json" \ -d '{ "email": "admin@example.com", "password": "your-password" }'
Response:
{ "token": "7f8b9c0d1e2f...", "user": { "id": 1, "email": "admin@example.com" } } -
Call Protected Admin Routes: Send the session token in the
Authorizationheader as a Bearer token (or viax-dashboard-token):# List configured provider keys curl http://localhost:3001/api/keys \ -H "Authorization: Bearer 7f8b9c0d1e2f..." # Manage client tenant keys curl http://localhost:3001/api/client-keys \ -H "Authorization: Bearer 7f8b9c0d1e2f..."
Any OpenAI-compatible client works. Examples:
Python
from openai import OpenAI
client = OpenAI(
base_url="http://localhost:3001/v1",
api_key="freellmapi-your-unified-key",
)
resp = client.chat.completions.create(
model="auto", # let the router pick; or specify e.g. "gemini-2.5-flash"
messages=[{"role": "user", "content": "Summarise the fall of Rome in one sentence."}],
)
print(resp.choices[0].message.content)
print("Routed via:", resp.headers.get("x-routed-via"))curl
curl http://localhost:3001/v1/chat/completions \
-H "Authorization: Bearer freellmapi-your-unified-key" \
-H "Content-Type: application/json" \
-d '{
"model": "auto",
"messages": [{"role": "user", "content": "hi"}]
}'Streaming
stream = client.chat.completions.create(
model="auto",
messages=[{"role": "user", "content": "Stream me a haiku about SQLite."}],
stream=True,
)
for chunk in stream:
print(chunk.choices[0].delta.content or "", end="", flush=True)Tool calling
Pass OpenAI-style tools and tool_choice; the assistant response round-trips back through the proxy exactly like the OpenAI API. Multi-step flows (assistant tool_calls → tool role follow-up → final answer) work across every provider the router can reach.
tools = [{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get current weather for a city.",
"parameters": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"],
},
},
}]
# 1. Model asks for a tool call
first = client.chat.completions.create(
model="auto",
messages=[{"role": "user", "content": "What's the weather in Karachi?"}],
tools=tools,
tool_choice="required",
)
call = first.choices[0].message.tool_calls[0]
# 2. You execute the tool, feed the result back
final = client.chat.completions.create(
model="auto",
messages=[
{"role": "user", "content": "What's the weather in Karachi?"},
first.choices[0].message,
{"role": "tool", "tool_call_id": call.id, "content": '{"temp_c": 32, "cond": "sunny"}'},
],
tools=tools,
)
print(final.choices[0].message.content)Works with stream=True as well — you'll get delta.tool_calls chunks followed by a finish_reason: "tool_calls" close. Under the hood, OpenAI-compatible providers (Groq, Cerebras, SambaNova, Mistral, OpenRouter, GitHub Models, HuggingFace, Cloudflare, Cohere compat) get the request passed through; Gemini requests get translated into Google's functionDeclarations / functionResponse shape and the response is translated back.
Multimodal Vision
Pass image URLs or base64 data URLs in standard OpenAI content arrays. Requests with images are automatically routed to vision-capable models:
resp = client.chat.completions.create(
model="auto",
messages=[{
"role": "user",
"content": [
{"type": "text", "text": "Describe the contents of this image in detail."},
{"type": "image_url", "image_url": {"url": "data:image/jpeg;base64,..."}},
],
}],
)
print(resp.choices[0].message.content)Image Generation (/v1/images/generations)
Generate images with Pollinations Flux, Cloudflare Flux 1 Schnell / SDXL, and Google Imagen 3:
img_resp = client.images.generate(
prompt="A futuristic electric hypercar speeding across a neon highway at twilight",
model="flux",
size="1024x1024",
response_format="b64_json",
)
# Access generated base64 or URL
image_b64 = img_resp.data[0].b64_jsonAudio Transcription & Translation (/v1/audio/*)
Transcribe audio files or voice notes into text using Whisper Large v3 / Turbo:
with open("voice_memo.mp3", "rb") as audio_file:
transcript = client.audio.transcriptions.create(
model="whisper-large-v3",
file=audio_file,
)
print(transcript.text)Text-to-Speech (/v1/audio/speech)
Synthesize spoken audio from text with natural neural voices:
speech_response = client.audio.speech.create(
model="tts-1",
voice="nova",
input="Hello! FreeLLMAPI now streams high-quality neural speech.",
)
speech_response.stream_to_file("output.mp3")Vector Embeddings (/v1/embeddings)
Generate dense vector representations for semantic search and retrieval across Google, Mistral, Cohere, and Cloudflare:
embed_resp = client.embeddings.create(
model="text-embedding-004", # or "auto", "mistral-embed", "embed-english-v3.0"
input=["Artificial intelligence and neural networks", "Machine learning models"],
)
for item in embed_resp.data:
print(f"Embedding index {item.index}: {len(item.embedding)} dimensions")Legacy Completions (/v1/completions)
Interact with classic prompt-style completion models with full streaming support:
completion = client.completions.create(
model="auto",
prompt="Generate three creative company names for a quantum computing startup:\n1.",
max_tokens=60,
temperature=0.7,
)
print(completion.choices[0].text)Multiple Choices (n > 1)
Generate multiple independent completions in a single call:
multi_choice = client.chat.completions.create(
model="auto",
messages=[{"role": "user", "content": "Write a short catchy tagline for a coffee shop."}],
n=3,
)
for i, choice in enumerate(multi_choice.choices):
print(f"Choice {i + 1}: {choice.message.content}")Content Moderation (/v1/moderations)
Run content safety evaluations with category scores and flags:
mod_resp = client.moderations.create(
input="Check if this input text complies with content safety standards.",
)
print("Flagged:", mod_resp.results[0].flagged)
print("Category scores:", mod_resp.results[0].category_scores)Client API Keys & Token Budgets (/api/client-keys)
Create isolated API tokens with custom RPM rate limits and monthly token budgets for downstream apps:
# Create a tenant key with 60 RPM limit and 1,000,000 monthly token quota
curl http://localhost:3001/api/client-keys \
-H "Content-Type: application/json" \
-d '{
"name": "Discord Bot",
"rateLimitRpm": 60,
"monthlyTokenBudget": 1000000
}'Every response carries an X-Routed-Via: <platform>/<model> header so you can see which provider actually served each call. If a request fell over between providers, you'll also see X-Fallback-Attempts: N.
Manage provider credentials and grab the unified API key your apps connect with. Each key shows a status dot and when it was last health-checked.
Send a chat completion through the router and see which provider served it, with the model ID and latency printed right on the message.
Request volume, success rate, tokens in and out, average latency, and per-provider breakdowns over 24h / 7d / 30d windows.
┌──────────────────┐ Bearer freellmapi-… ┌─────────────────────────┐
│ OpenAI SDK / │ ──────────────────────▶ │ Express proxy (:3001) │
│ curl / any │ ◀────────────────────── │ /v1/chat/completions │
│ OpenAI client │ streamed tokens └────────────┬────────────┘
└──────────────────┘ │
▼
┌────────────────────────────────────────────────┐
│ Router │
│ 1. Pick highest-priority model that │
│ (a) has a healthy key and │
│ (b) is under all its rate limits. │
│ 2. Decrypt key, call provider SDK. │
│ 3. On 429/5xx → cooldown + retry next model. │
└────────────────────────────────────────────────┘
│
┌──────────────┬────────────┬──────────┴─────────┬─────────────┬──────────┐
▼ ▼ ▼ ▼ ▼ ▼
Google Groq Cerebras OpenRouter HF …10 more
- Router (
server/src/services/router.ts) — picks a model per request. - Rate-limit ledger (
server/src/services/ratelimit.ts) — in-memory RPM/RPD/TPM/TPD counters backed by SQLite, with cooldowns on 429s. - Provider adapters (
server/src/providers/*.ts) — one file per provider, implementing theProviderbase class:chatCompletion()andstreamChatCompletion(). - Health service (
server/src/services/health.ts) — periodic probe keeps key status fresh. - Dashboard (
client/) — React + Vite + shadcn/ui admin surface. - Storage — SQLite (
better-sqlite3) with AES-256-GCM envelope encryption for keys.
Stacking free tiers has real trade-offs. Be honest with yourself about them:
- No frontier models. The free-tier catalog tops out around Llama 3.3 70B, GLM-4.5, Qwen 3 Coder, and Gemini 2.5 Pro. You will not get GPT-5 or Claude Opus class reasoning through this. For hard problems, pay for a real API.
- Intelligence degrades as the day progresses. Your top-ranked models (usually Gemini 2.5 Pro, GPT-4o via GitHub Models) have the lowest daily caps. Once they hit their limits, the router falls down your priority chain to smaller/weaker models. Expect the effective intelligence of the endpoint to drop in the late hours of each day — then reset at UTC midnight.
- Latency is highly variable. Cerebras and Groq are extremely fast; others are not. You get whichever one is available.
- Free tiers can change without notice. Providers regularly tighten, loosen, or remove free tiers. When that happens you'll see 429s or auth errors until you update the catalog. Re-seed scripts live in
server/src/scripts/. - No SLA, by definition. If you need reliability, use a paid provider with a contract.
- Single-admin architecture. While FreeLLMAPI secures the dashboard with admin authentication and supports multi-tenant client API keys with token quotas for downstream applications, the management dashboard is designed for a single administrator.
Contributors very welcome! Good first PRs:
- Add a provider — copy
server/src/providers/openai-compat.tsas a template, wire it intoserver/src/providers/index.ts, seed its models inserver/src/db/index.ts, add a test inserver/src/__tests__/providers/. - Add an endpoint — embeddings, images, moderations. The provider base class can grow new methods; adapters declare which they support.
- Improve the router — cost-aware routing (cheapest-healthy-fastest tradeoffs), better latency-weighted priority, regional pinning.
- Dashboard polish — charts on the Analytics page, key rotation UX, batch import of keys from
.env. - Docs — more examples, client library snippets for Go/Rust/etc., a deployment recipe for Docker or Fly.
Development loop:
npm install
npm run dev # server on :3001, dashboard on :5173, both with HMR
npm test # vitest — 75 tests across providers, routes, router, ratelimitPRs should include a test, keep the existing test suite green, and match the .editorconfig / tsconfig defaults already in the repo. Issues and discussions are open.
Thanks to everyone who's helped improve FreeLLMAPI:
- @moaaz12-web — tool-calling support across providers (#3)
- @lukasulc — better-sqlite3 bump to fix npm install on Node 24+ (#12)
- @VinhPhamAI — root
.envPORT now propagates to server + Vite dev proxy + UI base URL (#27) - @deadc — preserve Gemini
thoughtSignatureso multi-turn function calling stops 400-ing (#32); router model-first key-exhaustion tests + per-modellimitshoist (#42) - @zhangyu1324 — requested Ollama Cloud integration, now V10 catalog (#14 / #41)
- @jtbrennan-git — security review (#35) and Phase 1 hardening: parameterized analytics queries, sort-preset whitelist, timing-safe API key compare, mid-stream error sanitization
- @praveenkumarpranjal — guard Gemini SSE
JSON.parseso a malformed frame no longer aborts the whole stream, plus first streaming tests for the Google provider (#47)
A self-hosted, single-user, personal-use setup was re-reviewed against each provider's ToS (May 2026). Summary:
| Provider | Verdict | Notes |
|---|---|---|
| Google Gemini | March 2026 ToS narrows scope to "professional or business purposes, not for consumer use" — a self-hosted developer proxy is still defensible, but the clause is new. | |
| Groq | ✅ Likely OK | GroqCloud Services Agreement permits Customer Application integration. |
| Cerebras | ✅ Likely OK | Permitted; explicitly forbids selling/transferring API keys. |
| Mistral | ✅ Likely OK | APIs allowed for personal/internal business use. |
| OpenRouter | ✅ Likely OK | April 2026 ToS sharpens the no-resale / no-competing-service clause; private single-user proxy still fine. |
| SambaNova | EULA §1.5(c) blocks resale and "service bureau" use; single-user with no third-party access is fine. | |
| Cloudflare Workers AI | No anti-proxy clause; covered by general Self-Serve Subscription Agreement. | |
| NVIDIA NIM | Trial ToS §1.2 / §1.4: "evaluation only, not production." Disabled in default catalog. | |
| GitHub Models | Free tier explicitly scoped to "experimentation" and "prototyping." | |
| Cohere | ❌ Avoid | Terms §14 still forbids "personal, family or household purposes." |
| Zhipu (open.bigmodel.cn) | ✅ Likely OK | Personal/non-commercial research carve-out still in the platform docs. |
| Z.ai (api.z.ai) | New row — Singapore entity (distinct from Zhipu CN). §III.3(l) anti-traffic-redirect clause could plausibly be read against a proxy; no explicit personal-use carve-out. | |
| Ollama Cloud | ✅ Likely OK | New row — Free plan permits cloud-model access (1 concurrent, 5-hour session caps). No anti-proxy / anti-resale clauses found. (Integration tracked in #14.) |
| Moonshot AI (Kimi) | ✅ Likely OK | Direct global API endpoint (api.moonshot.ai/v1) supported. |
Rules of thumb that keep most providers happy: one account per provider, no reselling, no sharing your endpoint with other humans, don't hammer a free tier as a paid production backend. This is informational, not legal advice — read each provider's ToS and make your own call.
Removed since the April 2026 review: Hugging Face and MiniMax direct integrations were dropped from the catalog (HF — tool-call format issues; MiniMax — superseded by the OpenRouter minimax/minimax-m2.5:free route).
This project is for personal experimentation and learning, not production. Free tiers exist so developers can prototype against them; they aren't a stable, supported inference substrate and shouldn't be treated as one. If you build something real on top of FreeLLMAPI, swap in a paid API before you ship. Your relationship with each upstream provider is governed by the terms you accepted when you created your account — those terms still apply when the traffic is proxied through this project, and you're responsible for complying with them.



