One metered entry point for language models, embeddings, images, video, text to speech and speech to text. It is OpenAI-compatible under /v1/ai, so the OpenAI SDK, the AI SDK (@ai-sdk/openai) and most agents work by changing the base URL. Pick a Vibiz model by what it is for (vibiz/fast, vibiz/smart, vibiz/image…), or any lab's model by its own id (anthropic/claude-opus-5.5, moonshotai/kimi-k3.1-pro…). Either way exactly that model runs: Vibiz never swaps in another one.
import OpenAI from 'openai';
const openai = new OpenAI({ baseURL: process.env.VIBIZ_AI_BASE_URL, apiKey: process.env.VIBIZ_AI_API_KEY });
const stream = await openai.chat.completions.create({ model: 'vibiz/fast', messages, stream: true });Keys
- Account key (
vz_sk_…): agents and scripts. AddX-Vibiz-Project: prj_…to bill a project. - Project AI key (
vz_ai_…):vibiz add ai. The app's env getsVIBIZ_AI_BASE_URL,VIBIZ_AI_API_KEYand the aliasesOPENAI_BASE_URL,OPENAI_API_KEY, sonew OpenAI()works unchanged. - App key:
new OpenAI(vibiz.ai)with@vibiz/app.
Models and pricing
A Vibiz model is a stable name for what it is for. Each runs one lab model, named below and in every answer (served_model); we move a tier to a newer model as labs ship them, and the change shows here. If that model is down, the call fails (model_unavailable or provider_unavailable) rather than run a different model you didn't pay for.
| Vibiz model | Runs on | For | Price (USD) |
|---|---|---|---|
vibiz/fast (default chat) | GPT-6 Luna (OpenAI) | chat, tool calls, JSON | $0.10 / $0.50 per million tokens in / out |
vibiz/lite | DeepSeek V4.1 Flash (DeepSeek) | the cheapest chat, 1M token context | $0.14 / $0.42 |
vibiz/smart-mini | Claude Haiku 5.5 (Anthropic) | quick, strong writing and coding | $0.10 / $0.50 |
vibiz/balanced | Gemini 3.8 Flash (Google) | quality and price balanced, 1M token context | $0.825 / $4.125 |
vibiz/reasoning | GPT-6.1 Terra (OpenAI) | thinks before it answers: math, logic, planning | $1 / $5 |
vibiz/smart | Claude Sonnet 5.5 (Anthropic) | hard tasks: writing, coding, agents | $2 / $10 |
vibiz/pro | Claude Opus 5.5 (Anthropic) | the strongest chat tier, long agent runs | $4 / $20 |
vibiz/embed | text-embedding-3-small (OpenAI) | embeddings, 1536 dimensions | $0.02 per million tokens |
vibiz/embed-large | text-embedding-3-large (OpenAI) | embeddings, 3072 dimensions | $0.13 per million tokens |
vibiz/image | Nano Banana 2 (Google) | fast images, edits, consistent characters | about $0.067 per image |
vibiz/image-pro | Nano Banana 2.1 (Google) | Google's newest image model | about $0.034 per image |
vibiz/image-text | GPT-5.4 Image 2 (OpenAI) | long prompts, text rendered in the image | about $0.04 per image |
vibiz/video | LTX-2.5 Fast (Lightricks) | 6 s clips at 720p with sound (jobs only) | $0.54 per video |
vibiz/voice | Eleven v4 Turbo (ElevenLabs) | natural real-time voices | $0.04 per 1,000 characters |
vibiz/voice-pro | Eleven v4 (ElevenLabs) | the most expressive voices | $0.08 per 1,000 characters |
vibiz/voice-lite | Eleven Flash v2.5 (ElevenLabs) | the fastest voices, 32 languages | $0.04 per 1,000 characters |
vibiz/transcribe | Scribe v2 (ElevenLabs) | speech to text, 99 languages | $0.22 per hour of audio |
These are the labs' list prices. A call is billed at what it really cost plus the AI fee in the price book (markup_pct on each model in GET /v1/ai/models). Some chat models charge more once a call's input passes a long-context threshold (pricing.long_context): GPT-6 models past 272,000 input tokens, Claude Haiku 5.5 past 100,000. Every JSON response carries cost_micro_usd, the exact cost of that call, and served_model (speech: the X-Vibiz-Served-Model header).
All models
Beyond the Vibiz models, every language model from every major lab runs by its own id: OpenAI, Anthropic, Google, DeepSeek, xAI, Moonshot AI, Qwen, Mistral, Meta, MiniMax, Z.ai and more, over 400 in all, kept current as labs release them. Search them in the console (AI models), with GET /v1/ai/models?all=1&q=kimi, vibiz ai models kimi, or the vibiz_ai_models tool.
{ "model": "moonshotai/kimi-k3.1-pro", "messages": [{ "role": "user", "content": "Hi" }] }It runs exactly that model, at its list price plus the AI fee, and the answer names it. Usage groups a model behind a Vibiz model under that Vibiz model, and any other model under its own id. The media models above (google/gemini-nano-banana-2.1, elevenlabs/v4…) and older ones (black-forest-labs/flux-schnell, openai/whisper-1…) are called by id the same way. A model that isn't in the list can't be called (invalid_request, param: "model"), so a typo can't reach an expensive model.
Video takes 16:9 or 9:16 (1:1 comes back as 16:9).
Limits
| Daily spend ceiling | $5 per account per UTC day by default (AI and actions together; an owner raises it in Billing); each call is held at its worst case before it runs |
| Credits | each call's worst case must fit in the account's balance (plus $0.50); out of credits: 402 payment_required (Billing) |
| Project budget | PATCH /v1/projects/:id/ai { daily_budget_usd, end_user_daily_budget_usd } |
max_tokens | 1,024 when not given, at most 16,384 (per model) |
| Images | 4 per request, 256–2,048 px a side |
| Speech | 4,096 characters |
| Transcription | 25 MB upload |
| Embeddings | 2,048 inputs |
| Rate, account key | 120 requests and 400k tokens a minute, 20 in flight |
| Rate, project key | 60 requests and 200k tokens a minute (settable to 600 and 2M), 10 in flight (up to 50) |
| Media links | permanent with a project (Files); 24 hours without one |
Use it
curl https://app.vibiz.app/v1/ai/chat/completions \
-H "Authorization: Bearer $VIBIZ_API_KEY" -H 'content-type: application/json' \
-d '{"model":"vibiz/fast","messages":[{"role":"user","content":"Name a bakery in three words."}]}'vibiz ai "Name a bakery in three words."
vibiz image "a croissant on a marble table" -o hero.png
vibiz say "Welcome to Acme Bakery" -o welcome.mp3 --voice alloy
vibiz transcribe call.m4a --language enAgents use vibiz_ai_chat, vibiz_image_generate, vibiz_speech_create and vibiz_speech_transcribe; media comes back as links, never base64; with a project the link is permanent and the file is in the project's Files (vibiz_files). The same as actions: POST /v1/actions/ai.chat { "input": { "prompt": "…" } }.
| Route | Does |
|---|---|
POST /v1/ai/chat/completions | chat, streaming (SSE) or not; tools, JSON mode |
POST /v1/ai/embeddings | embeddings |
POST /v1/ai/images/generations | images: b64_json (default) or url |
POST /v1/ai/audio/speech | text to speech, streamed mp3 or pcm |
POST /v1/ai/audio/transcriptions | speech to text, multipart file |
POST /v1/ai/jobs, GET /v1/ai/jobs/:id | slow images and video: 202, then poll |
GET /v1/ai/models, GET /v1/ai/health | catalogue with prices; per capability ok/degraded/down |
Voices are alloy, ash, coral, echo, fable, nova, onyx, sage, shimmer. Pass your own user's id as user (or X-Vibiz-User) and spend breaks down per end user.
Generated media is kept in Files
Every image, video and audio you generate is saved in the project's Files, with the model, the prompt and the cost. Use the url in the response (it is permanent), or vibiz files latest / vibiz files search "<prompt words>" later.
Files are named by date and prompt (2026-10-28-cold-email-cover.png). A call with a development key (the development app key or AI key) saves to the development Files; every other project call saves to production. A call billed to the account with no project has no Files to go to: it is not saved and its links expire after 24 hours. Saving never fails the call: if it can't be saved, you get the 24-hour link and no file fields.
The answers keep their OpenAI shape and add:
| Call | Added |
|---|---|
POST /v1/ai/images/generations | file_id and file_url on each data[i]; with response_format: "url", url is the permanent link |
POST /v1/ai/jobs (image and video), once done | file_id and file_url on each output.data[i]; url is permanent and expires_at is null |
POST /v1/ai/audio/speech | headers X-Vibiz-File-Id and X-Vibiz-File-Url (the file appears once the audio has finished) |
actions image.generate, speech.create | url permanent, plus file_id and file_url |
Your own keys
Have Google Cloud credits, or a Google account you'd rather pay? Add your own Google key and Google's models run on your Google account: Google bills you, and the call costs 0 on Vibiz (each answer says "paid_by": "your_key", with would_cost_micro_usd: what it would have cost here). Models from other labs keep running on Vibiz, billed as usual: your key never moves a Vibiz model to a Gemini model.
Two kinds of Google credentials:
| Type | What it is | Serves |
|---|---|---|
"gemini_api_key" | a Gemini API key from Google AI Studio | Google's chat, image, video, speech and transcription models, and embeddings if you turn them on |
"vertex" | a Google Cloud service account key file, a project id and a region (default global): Vertex AI, which spends Google Cloud credits | Gemini 3.1 Flash Lite, 3.5 Flash Lite and 3.5 Flash chat, and transcription, today; the rest stays on Vibiz |
GEMINI_API_KEY=… vibiz ai keys set google # or type it at the hidden prompt
vibiz ai keys set google --vertex sa.json --region us-central1
vibiz ai keys # status, and which models run on your key
vibiz ai keys test google
vibiz ai keys remove googleOr in the console: API keys ▸ Your AI keys. With the API: PUT /v1/ai-keys/google { "type": "gemini_api_key", "api_key": "…" } (owner keys only). A key is checked with a free call to Google before it is saved, and refused with the reason if Google refuses it. It is stored encrypted and never shown again: only its last 4 characters, when it was last used and its last error. A project can have its own key (/v1/projects/:id/ai-keys/google), which replaces the account's for that project.
What to know:
- No silent fallback. A call your key can serve runs only on your key. If Google refuses it or is down, the call fails (
provider_failed,details.reason: "customer_key_rejected", orprovider_unavailable): it is never retried on Vibiz's account, so you are never billed by us by surprise. - What runs on your key: any
google/…model by its id (google/gemini-4-argon,google/gemini-3.8-flash-tts,google/gemini-omni-1.1-flash,google/gemini-embedding-2…), and the Vibiz models whose model is Google's:vibiz/balanced(Gemini 3.8 Flash),vibiz/image(Nano Banana 2) andvibiz/image-pro(Nano Banana 2.1). - Everything else runs on Vibiz, billed as usual: the key's status lists every Vibiz model with
paid_by: "your_key"or"vibiz". - Embeddings are off by default (
use_for): vectors from another model don't match the ones your index already holds, and nothing would error. Turn them on for a new index:PATCH /v1/ai-keys/google { "use_for": ["llm", "embeddings", …] }. - Speech on your Google key comes back as WAV (
audio/wav) when you ask formp3: we don't convert audio.pcmis the same 24 kHz 16-bit mono PCM as always. - Transcription on your Google key takes files up to 14 MB, and video takes
16:9or9:16. - A job made on your key fails if you remove the key before it runs; it never runs on ours.
What agents can and can't do
Agents may call every AI route and tool; each call is metered and held against the daily ceiling. Rotating the project's production AI key is an owner's (POST /v1/projects/:id/ai/keys/rotate), and so are setting and removing your own provider keys; agents can read their status (vibiz_ai_keys), never a secret.
Errors
OpenAI-shaped, so OpenAI SDKs read them: { "error": { "code", "message", "type", "param", "details"? } }.
| Code | Status | When | Next step |
|---|---|---|---|
invalid_request | 400 | bad input, unknown model, a cap exceeded; param names the field | fix the field |
content_filtered | 400 | a content filter refused the request | change the prompt |
context_length_exceeded | 400 | the input is longer than the model's window | shorten it |
payload_too_large | 413 | body or upload over its cap | send less |
unauthorized | 401 | missing, invalid or revoked key | check the key |
rate_limited | 429 | details.reason: daily_spend, project_budget, end_user_budget, requests_per_minute, tokens_per_minute, concurrency | wait (Retry-After), or raise the budget; daily_spend resets at midnight UTC |
provider_unavailable | 503 | every route failed; details.reason timeout, stall, circuit_open | retry later |
model_unavailable | 503 | no route can run that model right now; Vibiz never swaps in another | retry after details.retry_after_seconds, or pick another model |
not_configured | 503 | this model can't be served right now | use another Vibiz model |
Mid-stream, the error arrives as a final SSE event, data: {"error": {…}}, without [DONE].