OpenFill is in development. Inference is off, but is tested end to end, and will switch on at launch. All data currently on the site is for live testing: it will be erased at launch.

Skip to content
openfill

Integrations

Anything that speaks the OpenAI chat API can speak to OpenFill. Three values do it: the base URL, your key, and a model id. The fourth is where the max price goes, and that is what each section below settles.

Before any of them

  1. Set a max price on the key or on your account, on Bidding. A tool that cannot add a field or a header still works once that default exists, and a tool that can add one overrides it per request.
  2. Use https://api.openfill.ai/v1 as the base URL, with the /v1. Every tool below expects that shape.
  3. Verify from a shell before configuring the tool. The first call lists the models; the second is a completion that returns the receipt.

Set OPENFILL_API_KEY to a key from API keys before running an example. A key starts with of_live_ and is shown once.

bash
curl -s https://api.openfill.ai/v1/models -H "Authorization: Bearer $OPENFILL_API_KEY" curl -s https://api.openfill.ai/v1/chat/completions \  -H "Authorization: Bearer $OPENFILL_API_KEY" \  -H "Content-Type: application/json" \  -d '{"model": "placeholder-large", "messages": [{"role": "user", "content": "hi"}], "max_price": 0.10}'
Where the max price can goWhich tools
max_price in the bodyThe OpenAI SDKs (Python via extra_body, TypeScript via a cast), curl, any raw HTTP client.
The X-Max-Price headerThe TypeScript SDK, the Vercel AI SDK, LangChain, LiteLLM, the Agents SDK, OpenCode, Continue, Kilo Code.
The key or account defaultCline, Roo Code, Cursor, Aider, Open WebUI, and anything else with a settings screen and no header field.

The OpenAI SDKs

Point the client at the base URL and pass the max price by the route the SDK offers. Python takes unknown fields through extra_body. The TypeScript types refuse a field they do not declare, so the header is the plain route, and // @ts-expect-error above max_price is the body route.

Read docs
import osfrom openai import OpenAI client = OpenAI(    base_url="https://api.openfill.ai/v1",    api_key=os.environ["OPENFILL_API_KEY"],) r = client.chat.completions.create(    model="placeholder-large",    messages=[        {"role": "user", "content": "hi"}    ],    extra_body={"max_price": 0.10},)print(r.choices[0].message.content)print(r.usage)

Go, Java and Ruby have their own routes for an undeclared body field. They are on the compatibility page.

Any tool that reads the OpenAI variables

Both official SDKs, and most tools built on them, read OPENAI_BASE_URL and OPENAI_API_KEY from the environment. Set those two and code that names no base URL reaches OpenFill unchanged. The max price then comes from the key or the account.

bash
# A key from API keys, shown once when madeexport OPENFILL_API_KEY="of_live_..." # Any tool that reads the OpenAI variablesexport OPENAI_BASE_URL="https://api.openfill.ai/v1"export OPENAI_API_KEY="$OPENFILL_API_KEY" # The max price comes from the key or the# account default, set on Bidding.curl -s "$OPENAI_BASE_URL/models" \  -H "Authorization: Bearer $OPENAI_API_KEY"

Aider, CrewAI and Pydantic AI are among the tools that work this way. Aider also takes the same pair as OPENAI_API_BASE, and prefixes the model with openai/:

bash
export OPENAI_API_BASE="https://api.openfill.ai/v1"export OPENAI_API_KEY="$OPENFILL_API_KEY"aider --model openai/placeholder-large

Vercel AI SDK

Use the OpenAI-compatible provider package rather than the OpenAI one, which now defaults to the Responses API. headers carries the max price on every call; ask for includeUsage on a stream to see the receipt in the last chunk.

typescript
import { createOpenAICompatible } from "@ai-sdk/openai-compatible";import { generateText } from "ai"; const openfill = createOpenAICompatible({  name: "openfill",  baseURL: "https://api.openfill.ai/v1",  apiKey: process.env.OPENFILL_API_KEY,  headers: { "X-Max-Price": "0.10" },}); const { text } = await generateText({  model: openfill.chatModel("placeholder-large"),  prompt: "hi",});console.log(text);

LangChain

ChatOpenAI with a base URL. LangChain's OpenAI class keeps to the documented OpenAI response fields, so usage.x_market and reasoning_content are dropped on the way through. Read them from the dashboard, or through the raw SDK when you need them in code.

python
import osfrom langchain_openai import ChatOpenAI llm = ChatOpenAI(    model="placeholder-large",    base_url="https://api.openfill.ai/v1",    api_key=os.environ["OPENFILL_API_KEY"],    default_headers={"X-Max-Price": "0.10"},)print(llm.invoke("hi").content)

LlamaIndex uses the same three values through OpenAILike, with is_chat_model=True and is_function_calling_model=True.

LiteLLM

Prefix the model with openai/ and give api_base. The same three values in a proxy config.yaml put OpenFill behind LiteLLM's own endpoint, which is also the route for a tool that speaks a different API.

python
import osfrom litellm import completion r = completion(    model="openai/placeholder-large",    api_base="https://api.openfill.ai/v1",    api_key=os.environ["OPENFILL_API_KEY"],    messages=[        {"role": "user", "content": "hi"}    ],    extra_headers={"X-Max-Price": "0.10"},)print(r.choices[0].message.content)
yaml
# config.yaml, for litellm --config config.yamlmodel_list:  - model_name: placeholder-large    litellm_params:      model: openai/placeholder-large      api_base: https://api.openfill.ai/v1      api_key: os.environ/OPENFILL_API_KEY      extra_headers:        X-Max-Price: "0.10"

OpenAI Agents SDK

Give the SDK a client pointed at OpenFill and select the chat completions API, since the SDK's default is the Responses API. Tracing posts to OpenAI with whatever key the client holds, so switch it off.

python
import osfrom openai import AsyncOpenAIfrom agents import (    Agent, Runner,    set_default_openai_api,    set_default_openai_client,    set_tracing_disabled,) set_default_openai_client(AsyncOpenAI(    base_url="https://api.openfill.ai/v1",    api_key=os.environ["OPENFILL_API_KEY"],    default_headers={"X-Max-Price": "0.10"},))set_default_openai_api("chat_completions")set_tracing_disabled(True) agent = Agent(name="assistant", model="placeholder-large")print(Runner.run_sync(agent, "hi").final_output)

OpenCode

A custom provider in opencode.json, built on the AI SDK's OpenAI-compatible package. The key is read from the environment and the max price rides in options.headers.

json
// opencode.json{  "$schema": "https://opencode.ai/config.json",  "provider": {    "openfill": {      "npm": "@ai-sdk/openai-compatible",      "name": "OpenFill",      "options": {        "baseURL": "https://api.openfill.ai/v1",        "apiKey": "{env:OPENFILL_API_KEY}",        "headers": { "X-Max-Price": "0.10" }      },      "models": {        "placeholder-large": { "name": "placeholder-large" }      }    }  }}

Cline

Cline, Roo Code and Kilo Code share one settings screen for this: choose the OpenAI Compatible provider and fill in the base URL, the key and the model id. Cline and Roo Code have no header field, so set the max price on the key. Kilo Code has a headers field, which can carry X-Max-Price per tool.

text
# Cline, Roo Code and Kilo Code# Settings > API Provider: OpenAI Compatible Base URL   https://api.openfill.ai/v1API Key    (your OPENFILL_API_KEY)Model ID   placeholder-large # These tools send no max price of their# own. Set one on the key, on Bidding.

Roo Code uses native tool calling only, which OpenFill's chat endpoint supports. The input and output price fields these tools show are for a rate card; leave them empty, or fill them from the level of the moment, and read the real charge from your requests.

Cursor

  1. Open Cursor's settings and go to Models.
  2. Paste your OpenFill key into the OpenAI API key field.
  3. Turn on Override OpenAI Base URL and enter https://api.openfill.ai/v1.
  4. Add a custom model named placeholder-large and select it.

Cursor sends every request through its own servers, so your key and your prompts pass through them. Only its chat features use a custom key. Cursor has no header field, so the max price comes from the key.

Continue

A model block in config.yaml with the openai provider and an apiBase. The max price rides in requestOptions.headers.

yaml
models:  - name: OpenFill    provider: openai    model: placeholder-large    apiBase: https://api.openfill.ai/v1    apiKey: ${{ secrets.OPENFILL_API_KEY }}    requestOptions:      headers:        X-Max-Price: "0.10"

Open WebUI

Under the admin settings, add a connection of the OpenAI type with the base URL and your key. Open WebUI checks the connection by listing the models, which needs no key here, and then offers every served model in its picker. The max price comes from the key.

Gateways and routers

A gateway that proxies OpenAI-shaped providers takes OpenFill with the same three values, and carries the max price as a header if it forwards custom headers, or from the key default if it does not. The public market data is worth wiring into a router's cost logic: GET /v1/market/levels answers with every market's level, without a key.

Tools that need another API

Claude Code speaks the Anthropic Messages API and Codex CLI speaks the Responses API. OpenFill serves the OpenAI chat and completions shapes, so neither tool can be pointed at it directly today. A translating proxy is the route in the meantime, and a tool that offers an OpenAI-compatible provider is the direct one.

A native listing

OpenFill is served through the OpenAI Compatible slot in the tools above. A tool that lists OpenFill by name changes nothing about the request; it saves typing the base URL.