Quickstart

Flow AI is an OpenAI-compatible API. Point any OpenAI SDK at our base URL and use your Flow AI key — every request is routed to the cheapest model that can do the job.

python
from openai import OpenAI

client = OpenAI(
    base_url="https://api.flowaiapi.com/v1",
    api_key="fa-...",          # from your dashboard
)

r = client.chat.completions.create(
    model="flow-1",            # Flow's model — routes to the cheapest capable supply for you
    messages=[{"role": "user", "content": "Summarize this ticket: ..."}],
)
print(r.choices[0].message.content)
print(r.model_dump()["_flowaiapi"])   # which model served it, price, your cost
curl
curl https://api.flowaiapi.com/v1/chat/completions \
  -H "Authorization: Bearer fa-..." \
  -H "Content-Type: application/json" \
  -d '{"model":"auto","messages":[{"role":"user","content":"hello"}]}'

Authentication

Pass your API key as a bearer token: Authorization: Bearer fa-.... Create and manage keys (and per-key budgets) in the dashboard. A key is shown in full only once at creation — store it securely. New accounts get a 7-day free trial; after that an active membership ($4.99/mo or $45/yr) is required to make requests.

Chat completions

POST /v1/chat/completions — accepts the standard OpenAI request body (messages, max_tokens, temperature, tools, response_format, stream, …) and returns the standard OpenAI response shape plus a _flowaiapi block. Both streaming (SSE) and non-streaming are supported.

Flow AI adds two optional fields:

FieldValuesMeaning
route_strategyauto · cascade · cheapest · balanced · fastest · <model_id>Default auto runs the cascade: serve the cheapest capable model, judge the output, and escalate to a stronger model only if it fails. cheapest is single-shot. A concrete model id pins it.
task_hintfree string (e.g. code)Helps the classifier choose a capable model.
verifytrue · "council"Verification before trust (non-streaming): the answer comes back with _flowaiapi.verification — verdict (pass/fail), confidence, and concrete issues. true runs free heuristics + one cheap judge pass; "council" adds diverse models re-judging with majority vote. Fail-open, never rewrites the answer; verification legs bill at pass-through like any request.
priority / X-FlowAI-Priority headerlatencyThe fast lane for synchronous, user-facing calls: routes to the fastest-decode models and never to slow/free tiers. Big structured outputs (response_format: json_object + max_tokens ≥ 1000) get the fast lane automatically.
imagesimage_url partsBase64 data URIs recommended. Remote http(s) URLs are auto-fetched by the gateway (8s timeout, 5MB cap) and inlined; a failed fetch returns a clear 400.

Routing

On each request Flow AI classifies the task with cheap, non-LLM heuristics (length, code, tool/JSON schema, multimodal parts), then picks the cheapest model whose capabilities cover the task — looked up against the live per-minute price. So a vision prompt goes to a multimodal model, a long-context prompt to a 1M-context model, and plain text to the cheapest capable one. The decision is cached by system prompt, so agent traffic pays near-zero routing overhead.

Free models are in the pool. Flow AI continuously discovers free-tier models (e.g. OpenRouter :free hosts), canary-tests each one for real tool-calling and output quality, and promotes the ones that pass into the default routing pool. When a free model can genuinely do your task, you pay $0 for the tokens — only the 2.5% fee on a $0 cost, i.e. nothing. No flag to set; auto already includes them.

Cascade (default). Rather than guess upfront, auto serves the cheapest capable model, runs a fast judge over the output (empty / refusal / malformed-JSON checks), and escalates to a stronger model only if it fails — you pay cheap by default and only pay up when the task actually needs it. Rejected cheap attempts aren't charged. The _flowaiapi.cascade array shows each tier tried. If a provider errors, it also fails over to the next capable one (failover: true).

Response metadata

Every non-streamed response includes a _flowaiapi object so the route is fully transparent:

_flowaiapi
"_flowaiapi": {
  "seller_id": "api:deepseek-v4-flash",
  "model_used": "deepseek-v4-flash",
  "input_tokens": 412, "output_tokens": 188,
  "clearing_price_per_1k_in": 0.00014,
  "clearing_price_per_1k_out": 0.00028,
  "cost_usd": 0.0000934,
  "buyer_charge_usd": 0.0000962,
  "interval_id": 29695141,
  "routing_reason": "auto__cheapest_capable",
  "latency_ms": 885,
  "failover": false,
  "budget_alerts": []
}

You pay cost_usd × 1.025 (buyer_charge_usd) — the model's pass-through cost plus a flat 2.5% spread. The commercial price is always the ceiling.

Models

GET /v1/models lists the currently available models. You can pin one by passing its id as model or route_strategy, but auto is recommended — it tracks price changes for you. For strict, guaranteed pinning (experiments, model panels) see Panel Mode.

Cortex — agent analytics

Cortex is the completion-intelligence layer: it tracks whether each agent's work actually finished (from tool-use and completion signals — never your prompt content), and both feeds the router and reports back to you. To get per-agent attribution, tag requests with optional body fields:

FieldMeaning
appWhich application sent the request (e.g. "support-bot").
agentWhich agent within the app.
run_idYour run/session id — groups a multi-request run so completion is judged per run, and keeps model affinity within a run.

Run attribution — send X-FlowAI-Run. A run usually spans many requests; give them one stable id (any string — a job id, session id, ticket) via the X-FlowAI-Run header orrun_id body field. Flow then attributes completion outcomes to the exact models that servedthat run, and keeps model affinity within the run (better prompt-cache hits). Without it, outcome attribution falls back to a coarser time-window match — it works, but per-run ids make the learning precise.

examples
# Anthropic-protocol harnesses (Claude Code etc.)
export ANTHROPIC_CUSTOM_HEADERS="x-flowai-app: my-fleet
x-flowai-run: $JOB_ID"

# OpenAI SDK
client = OpenAI(base_url="https://api.flowaiapi.com/v1", api_key="fa-...",
                default_headers={"X-FlowAI-Run": job_id, "X-FlowAI-App": "my-fleet"})

Then read your account's learned picture (API-key auth, same Authorization: Bearer fa-…):

EndpointReturns
GET /v1/cortex/overview?days=7Spend, requests, action-rate and cost-per-completed-task trends.
GET /v1/cortex/routingPer-model: requests, measured action rate, spend — the routing evidence.
GET /v1/cortex/cachingPrompt-cache hit rates and savings.
GET /v1/cortex/contextYour resolved context-management settings (compaction mode, external memory, retrieval).

Text-to-speech

POST /v1/audio/speech — OpenAI-compatible TTS with automatic provider failover. Send input (required), and optionally voice (default nova), response_format (mp3 default), speed (0.25–4.0), and model (auto routes it). Returns the audio bytes; billing is per character at pass-through cost + 2.5%, reported in the usual ledger.

curl — TTS
curl https://api.flowaiapi.com/v1/audio/speech \
  -H "Authorization: Bearer fa-..." -H "Content-Type: application/json" \
  -d '{"input":"Your build passed.","voice":"nova"}' --output speech.mp3

MCP server

Flow AI ships a Model Context Protocol server, so any MCP-capable agent (Claude Code, Claude Desktop, Cursor, ChatGPT connectors) can search the live catalog and market from inside its own session. Streamable HTTP, stateless, read-only — no API key needed for the discovery tools.

Claude Code
claude mcp add --transport http flow-ai https://api.flowaiapi.com/mcp
ToolReturns
search_modelsLive catalog matches: id, provider, context window, prices, verified caps.
get_live_pricesThe market book — clearing vs published list prices, savings %.
list_free_modelsThe canary-verified free models currently serving at $0.
about_flow_aiWhat Flow is + exact base-URL setup for OpenAI/Anthropic/Codex clients.
convene_council 🔑A diverse council of models independently critiques a plan you're unsure about, then a synthesis merges agreements, disagreements, and a recommendation — with total cost.
delegate_task 🔑Hand a self-contained subtask to the cheapest capable model; returns result, serving model, and exact cost. Add verify: true to get a verdict on the delegated work too.

🔑 = billed tools: pass your fa-… key as the Authorization header on the MCP connection. Real trace from launch testing: delegate_task("Reply with exactly: DELEGATE-OK") → served by byo:MiniMax-M3 for $0.0000030 in 1.2s. Both tools work with any active key — no extra setup.

Panel Mode — pinned models

Routing by default, any model on demand. Flow AI's default product is smart routing — flow-1 picks the cheapest capable model for every request. But some workloads need a specific model, or a panel of genuinely different ones: judge ensembles, consensus scoring, cross-model evals, A/B model tests, reproducible research. Panel Mode is strict, opt-in pinning for exactly those cases.

Enable it per key in the dashboard (Keys → "Panel Mode"). It's off by default — leave agent keys off, since routing is what saves you money.

The contract

GuaranteeWhat it means
Exact serveA pinned request is answered by exactly the model you pinned. No cascade, no failover.
Truthful echo_flowaiapi.served_model is the real upstream model string (e.g. claude-sonnet-4-5-20250929). Never a silent substitution.
Fail loudUnknown model → 400. Pinned model can't serve → 503 model_unavailable. Never a fallback answer from a different model.
Fresh callsPinned requests bypass all response caching — each call really hits the model, so experiments reproduce.
Real-rate billingEach pinned request bills at that model's actual rate. A 5-model panel bills 5 distinct rates.

Pin a single model

Prefix the model id with pin: — or send the header X-FlowAI-Route: pinned with a plain model id. Accepts a registry id (gpt-4o-mini) or a provider-prefixed name (openai/gpt-4o-mini).

curl — pinned request
curl https://api.flowaiapi.com/v1/chat/completions \
  -H "Authorization: Bearer fa-..." -H "Content-Type: application/json" \
  -d '{"model":"pin:gpt-4o-mini","messages":[{"role":"user","content":"..."}]}'
# -> _flowaiapi: { "served_model": "gpt-4o-mini", "pinned": true, ... }

The pinnable catalog: GET /v1/models?pinnable=true — id, provider, family, context window, per-token price, capabilities.

Fan out a panel — POST /v1/panel

One prompt across up to 10 pinned models in a single call. Legs run concurrently (a 5-model panel takes about as long as its slowest model), each leg bills at its own model's rate, and a model that can't serve returns an error entry while the rest still answer.

curl — 3-model panel
curl https://api.flowaiapi.com/v1/panel \
  -H "Authorization: Bearer fa-..." -H "Content-Type: application/json" \
  -d '{"models":["gpt-4o-mini","gemini-2.5-flash","claude-sonnet-4.6"],
       "max_tokens":256, "temperature":0,
       "messages":[{"role":"user","content":"Would you cite this source? ..."}]}'
response
{
  "object": "panel.result",
  "results": [
    { "model": "gpt-4o-mini", "status": "ok", "served_model": "gpt-4o-mini",
      "message": {"role":"assistant","content":"..."}, "usage": {...},
      "cost": {"buyer_charge_usd": 3.1e-06, "rate_per_1k_in": 0.00015, "rate_per_1k_out": 0.0006},
      "latency_ms": 812 },
    { "model": "gemini-2.5-flash", "status": "ok", ... },
    { "model": "claude-sonnet-4.6", "status": "ok", ... }
  ],
  "summary": { "requested": 3, "ok": 3, "failed": 0, "total_charge_usd": 0.00012 }
}

Shared parameters (messages, max_tokens, temperature, top_p, response_format, tools, stop, seed) apply to every leg. An unknown model anywhere in the list fails the whole call with 400 — a partial panel you didn't ask for is never run. Non-streaming only. Panel Mode errors: 403 — not enabled for this key · 400 — unknown model · 503 — pinned model unavailable (never a fallback).

Quick setup for agent frameworks

Flow AI is a drop-in backend for any agent stack — Paperclip, Hermes, OpenClaw, Claude Code, Codex, and anything OpenAI- or Anthropic-compatible. You only change the base URL and the API key; pass auto as the model and Flow AI picks the cheapest capable model per request. Pick the block that matches your framework's protocol:

Anthropic protocol — Claude Code, OpenClaw, Paperclip (claude_local)

env
export ANTHROPIC_BASE_URL="https://api.flowaiapi.com"
export ANTHROPIC_AUTH_TOKEN="fa-..."     # your Flow AI key (also accepted: ANTHROPIC_API_KEY / x-api-key)
# model: pass "auto" (any Claude model name also works and auto-routes)

OpenAI Chat protocol — Hermes, LangChain, opencode, most SDKs

env
export OPENAI_BASE_URL="https://api.flowaiapi.com/v1"
export OPENAI_API_KEY="fa-..."
# model: "flow-1"   (Flow's model — routes to the cheapest capable supply; "auto" also works)

OpenAI Responses protocol — Codex CLI (v0.132+)

~/.codex/config.toml
model = "auto"
model_provider = "flowai"

[model_providers.flowai]
name = "Flow AI"
base_url = "https://api.flowaiapi.com/v1"
wire_api = "responses"
env_key = "FLOWAI_KEY"        # then: export FLOWAI_KEY=fa-...
FrameworkUse the blockEndpoint
Paperclip — claude_localAnthropic/v1/messages
Paperclip — opencode / OpenAI adapterOpenAI Chat/v1/chat/completions
Paperclip — codex_localResponses/v1/responses
HermesOpenAI Chat/v1/chat/completions
OpenClawAnthropic/v1/messages
Claude CodeAnthropic/v1/messages
Codex CLIResponses/v1/responses

All three protocols support full tool-calling, streaming, and multi-turn loops, so agents do real work — see below. An active membership + balance are required (top up in the dashboard).

Tool calling & agents

Flow AI speaks all three major agent protocols with full tool-calling parity — point your framework at the matching endpoint and Flow's routing, failover, ledger, and tool handling all apply. Unknown model ids auto-route to the cheapest capable model.

FrameworkEndpointAuth header
OpenAI SDK / LangChain / etc.POST /v1/chat/completionsAuthorization: Bearer fa-…
Claude Code · Claude Agent SDKPOST /v1/messagesx-api-key: fa-…
Codex CLI (v0.132+)POST /v1/responsesAuthorization: Bearer fa-…

All three accept tools, return tool calls, and accept tool results on follow-up turns, in both streaming and non-streaming modes — so multi-step agents complete real work, not just text.

Anthropic Messages

Anthropic-style clients use POST /v1/messages with the key as an x-api-key header. Full tool support: Anthropic tools (input_schema) and tool_choice are translated to the router's function-calling; responses return tool_use content blocks with stop_reason: "tool_use", and tool_result blocks on the next turn continue the loop. Streaming emits protocol-correct Anthropic SSE (incl. input_json_delta for tool input). Point Claude Code at it with ANTHROPIC_BASE_URL.

curl — /v1/messages with a tool
curl https://api.flowaiapi.com/v1/messages \
  -H "x-api-key: fa-..." -H "anthropic-version: 2023-06-01" \
  -H "Content-Type: application/json" \
  -d '{"model":"auto","max_tokens":256,
       "tools":[{"name":"get_weather","description":"Get weather",
         "input_schema":{"type":"object","properties":{"city":{"type":"string"}},"required":["city"]}}],
       "messages":[{"role":"user","content":"Weather in Tokyo? Use the tool."}]}'
# -> stop_reason: "tool_use", content: [{"type":"tool_use","name":"get_weather","input":{"city":"Tokyo"}}]

OpenAI Responses

POST /v1/responses implements the OpenAI Responses API, which the current Codex CLI requires. It accepts input (a string or an array of message / function_call / function_call_output items), instructions, flattened tools, tool_choice, and max_output_tokens, and returns output items (message with output_text, and function_call). Streaming emits the Responses event set (response.createdoutput_item.addedoutput_text.delta / function_call_arguments.deltaresponse.completed).

curl — /v1/responses with a tool
curl https://api.flowaiapi.com/v1/responses \
  -H "Authorization: Bearer fa-..." -H "Content-Type: application/json" \
  -d '{"model":"auto","max_output_tokens":256,
       "tools":[{"type":"function","name":"get_weather","description":"Get weather",
         "parameters":{"type":"object","properties":{"city":{"type":"string"}},"required":["city"]}}],
       "input":"Weather in Tokyo? Use the tool."}'
# -> output: [{"type":"function_call","name":"get_weather","arguments":"{\"city\":\"Tokyo\"}"}]

For Codex, set the base URL to https://api.flowaiapi.com/v1 and your fa-… key.

Errors

StatusMeaning
401Missing or invalid API key.
402Membership inactive, or insufficient balance — top up to continue.
429Rate limit or per-key budget exceeded — back off and retry (honor Retry-After).
502All capable providers failed for this request.