OpenAI-compatible API

API Documentation

Get started in 5 minutes. One URL change — your existing OpenAI code works unchanged.

1

Quickstart

Install the OpenAI SDK, swap the base_url, and you're routing through Viapi. Your API key is issued by your firm admin in the dashboard.

Install

bash
pip install openai

Python

python
from openai import OpenAI

client = OpenAI(
    api_key="vi_live_your_key_here",
    base_url="https://api.viapi.ai/v1/proxy"
)

response = client.chat.completions.create(
    model="default",  # Routes to your configured provider
    messages=[{"role": "user", "content": "Hello!"}]
)
print(response.choices[0].message.content)
2

Authentication

Viapi accepts your API key in two ways. Keys are prefixed vi_live_ and are scoped to your client account.

HeaderRecommended
http
X-Viapi-Key: vi_live_your_key_here
Bearer tokenOpenAI SDK compatible
http
Authorization: Bearer vi_live_your_key_here
How to get your key

Your firm admin creates and issues API keys from the Viapi dashboard. Keys can be scoped with budget limits and rate caps per client.

3

Endpoints

Base URL: https://api.viapi.ai

MethodPathDescription
POST
/v1/proxy/chat/completionsChat completions — supports batch and streaming (SSE)
GET
/v1/proxy/modelsList available models for your account
GET
/v1/dashboard/client/me/usageYour usage statistics and token counts
GET
/v1/export/usageExport usage as CSV for billing reconciliation
POST
/v1/proxy/images/generationsImage generation — DALL-E and other image models
POST
/v1/video/jobsSubmit async video generation job, returns viapi_job_id
GET
/v1/video/jobs/{id}Poll video job status and get result URL on completion
POST
/v1/estimateEstimate cost in cents before generating — informational only

Full interactive reference: Swagger UI ↗

4

Streaming

Pass stream=Trueto receive server-sent events (SSE). The response format matches OpenAI's streaming protocol exactly.

python
stream = client.chat.completions.create(
    model="default",
    messages=[{"role": "user", "content": "Hello!"}],
    stream=True
)
for chunk in stream:
    print(chunk.choices[0].delta.content, end="")

Response Format

Responses are OpenAI-compatible with an additional viapi extension block containing billing metadata — cost, markup, and provider routing information.

json
{
  "id": "chatcmpl-abc123",
  "object": "chat.completion",
  "created": 1714000000,
  "model": "gpt-4o",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "Hello! How can I help you today?"
      },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 12,
    "completion_tokens": 18,
    "total_tokens": 30
  },
  "viapi": {
    "request_id": "req_01jwxyz",
    "client_id": "cli_abc",
    "provider": "openai",
    "model_used": "gpt-4o",
    "cost_usd": 0.000042,
    "markup_usd": 0.000013,
    "billed_usd": 0.000055
  }
}
viapi.request_id

Unique request identifier for support

viapi.provider

Which upstream provider handled the request

viapi.cost_usd

Raw provider cost before markup

viapi.billed_usd

Amount billed to this client

Rate Limits

Rate limit status is returned in response headers. When limits are exceeded, the API returns 429 Too Many Requests.

HeaderDefaultDescription
X-RateLimit-Limit-RPM60Requests per minute limit
X-RateLimit-Remaining-RPMRequests remaining this minute
X-RateLimit-Limit-RPD10,000Requests per day limit
X-RateLimit-Remaining-RPDRequests remaining today

Note: Limits are set per client by your firm admin. Defaults above apply if no custom limit is configured. Contact your admin to request increased limits.

5

Images

Route image generation through Viapi for metered billing. Uses the OpenAI SDK's images.generate method — same base_url swap, no other changes.

python
from openai import OpenAI

client = OpenAI(
    api_key="vi_live_your_key_here",
    base_url="https://api.viapi.ai/v1/proxy"
)

response = client.images.generate(
    model="dall-e-3",
    prompt="A photorealistic sunset over the ocean",
    n=1,
    size="1024x1024",
    quality="hd",
)
print(response.data[0].url)
# viapi billing: response.viapi.billed_usd
6

Video Jobs

Video generation is asynchronous. Submit a job and poll /v1/video/jobs/{id} until completed. Credits are deducted at submission and reconciled to actual cost on completion.

python
import httpx, time

headers = {"X-Viapi-Key": "vi_live_your_key_here"}
base = "https://api.viapi.ai"

# Submit job
job = httpx.post(f"{base}/v1/video/jobs", headers=headers, json={
    "model": "runway-gen3-alpha",
    "prompt": "A cinematic drone shot over a city at dusk",
    "duration_seconds": 5,
}).json()
job_id = job["viapi_job_id"]

# Poll until complete
while True:
    result = httpx.get(f"{base}/v1/video/jobs/{job_id}", headers=headers).json()
    if result["status"] == "completed":
        print(result["result_url"])
        break
    elif result["status"] == "failed":
        raise RuntimeError("Job failed")
    time.sleep(5)
7

Cost Estimate

Get a cost estimate before generating — useful for showing clients a price preview in your UI. Estimates are informational; actual billed amount may differ slightly for video (reconciled on completion).

python
import httpx

resp = httpx.post(
    "https://api.viapi.ai/v1/estimate",
    headers={"X-Viapi-Key": "vi_live_your_key_here"},
    json={
        "model": "dall-e-3",
        "n": 1,
        "size": "1024x1024",
        "quality": "hd",
    },
).json()

cost_usd = resp["estimated_cost_cents"] / 100
print(f"Estimated cost: ${cost_usd:.4f}")
# {"estimated_cost_cents": 8, "provider": "openai",
#  "breakdown": {"provider_cost_cents": 8, "markup_cents": 0}}
8

MCP — Agent Control Plane

The Viapi MCP server exposes the control plane as native tools in Claude Code and other MCP-compatible agent CLIs. Connect once and manage clients, mint keys, and list models in plain English — no API calls, no copy-pasting IDs.

Connect

bash
claude mcp add viapi --transport http https://api.viapi.ai/mcp

Must use --transport http. On next startup Claude Code shows an Authenticate button — click it, sign in with your firm admin account, done.

Authentication

OAuthRecommended — one click

Use the Authenticate button in Claude Code. A browser window opens, you sign in, and the token is stored permanently. No manual token management.
Account requirement: Use a firm admin account (e.g. dawn.le@rennlabs.com). Platform admin accounts are rejected.

Personal Access TokenFor CI / scripts
bash
# Step 1: Get a Supabase JWT from the dashboard
#   DevTools → Application → Local Storage → access_token

# Step 2: Mint a PAT
curl -s -X POST https://api.viapi.ai/v1/auth/tokens \
  -H "Authorization: Bearer <supabase-jwt>" \
  -H "Content-Type: application/json" \
  -d '{"label": "claude-code-mcp"}' | jq .

# Step 3: Register with Claude Code
claude mcp add viapi \
  -e VIAPI_API_URL=https://api.viapi.ai \
  -e VIAPI_ADMIN_TOKEN=vi_pat_<your-token> \
  -- python3 -m viapi_mcp.server

Available Tools

ToolDescription
list_modelsList available models with context window size and ZDR capability
list_clientsList all client accounts under your firm
get_clientGet a single client's details by ID
create_clientCreate a new client account
update_clientUpdate a client's name or contact details
list_keysList active API keys for a client (prefix, caps, allowlists)
revoke_keyPermanently revoke a key — requires confirm=true to execute
update_keyUpdate guardrails on an existing key (cap, enforcement, model allowlist) — cap clamped at $500/month
list_routesList model routes for a client (alias → provider:model mappings)
create_routeAdd a model route for a client with optional fallback
get_spending_limitGet the client-level monthly spending limit and alert thresholds
set_spending_limitSet a client-level monthly spending cap — clamped at $500/month server-side
get_usageGet monthly cost, token, and request counts for a client
get_credit_balanceGet current prepaid credit balance (in cents) and auto-reload settings for a client
create_billing_portal_urlGenerate a one-time Stripe Checkout URL so a client can add their payment card (expires 24 h)
mint_guardrailed_keyCreate a vi_live_ key with spend cap, model allowlist, optional expiry — monthly limit capped at $500 server-side

Usage

text
# Plain English — Claude calls the right tool automatically

list my viapi clients

create a client called "Acme Corp", slug acme-corp, email ops@acme.com

mint a key for client <id> with a $100/month cap, allow dall-e-3 and gpt-4o-mini

list available models that support ZDR

Need help?

Check the full Swagger reference or reach out to your firm admin.