skip to content
API reference

API

API reference

The cloud gateway and conifer serve answer the same wire. Everything below holds for both unless marked.


HostBase URLAuth
Cloudhttps://api.conifer.buildAuthorization: Bearer $CONIFER_API_KEY
conifer servehttp://127.0.0.1:8080none on loopback; any non-empty key satisfies clients that require one

Bearer is the only accepted auth form. x-api-key headers get a 401.

terminal
curl https://api.conifer.build/v1/chat/completions \
  -H "Authorization: Bearer $CONIFER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "conifer-swift",
    "max_tokens": 1024,
    "messages": [{"role": "user", "content": "three names for a build cache"}]
  }'

Routes

RouteWireNotes
POST /v1/chat/completionsOpenAI chatEvery model, including Conifer's own.
POST /v1/messagesAnthropic MessagesAnthropic model ids only. Prompt caching and live streaming ride this route.
POST /v1/messages/count_tokensAnthropicToken counting. Local door only today.
POST /v1/responsesOpenAI ResponsesStateless tool loop. What Codex speaks.
GET /v1/modelsOpenAIThe catalog your key can call, with prices.
GET /v1/balanceConiferYour balance, integers. Cloud only.
GET /healthConiferLiveness and served planes. Local door only.

Parameters

FieldBehavior
modelAn exact id from GET /v1/models. Unknown ids are refused by name, never served as something else.
max_tokensOptional on the chat wire (the server applies 4096). Required on /v1/messages. Conifer models enforce a per-model minimum; a too-small cap is a 400, not a truncated answer.
streamAccepted everywhere; see streaming below.
toolsPassed through. Check the model's caps field on the catalog first.

Streaming

stream: true always returns well-formed SSE. On /v1/messages, tokens arrive live. On the chat and Responses wires, most models currently deliver the completion as one burst at the end. Do not build a UI on incremental token timing there. On streams, the cost arrives as a terminal conifer_receipt event instead of a header.

Time bounds

A buffered call gets about 280 seconds. A stream is bounded by idle time (120 seconds between frames), not total time. For very long outputs, stream or split the request.

Receipt headers

Every cloud response carries its accounting:

HeaderMeaning
x-conifer-requested-modelWhat you asked for.
x-conifer-effective-modelThe exact model that served the admitted request.
x-conifer-receipt-reasonOpaque execution detail from the deciding native hop.
x-conifer-cost-nanousdThe settled cost of this request, in nanodollars (1e-9 USD).

One request header goes the other way: x-conifer-max-cost-nanousd sets a hard cost ceiling. A request whose worst case exceeds it is refused with a 402 before anything runs.

Prompt caching

Send cache_control breakpoints on /v1/messages; they pass through to the model unchanged. The response reports cache_read_input_tokens and cache_creation_input_tokens, billed at the cache rates on the catalog. The chat wire cannot carry cache directives. Nothing is ever cached on your behalf.

Errors

StatusMeaning
400The request itself. The body names the problem: a prompt over the model's context window, a cap under the model's floor, a non-Anthropic id on /v1/messages (wire_upstream_mismatch).
401Auth. Bearer missing, malformed, expired, or revoked.
402insufficient_allowance: billing isn’t set up or the balance can’t cover the worst case. Billing & caching covers it.
404model_not_found. The id isn't in your catalog; on a pinned local door, anything but the served model.
501Local thin builds only: an engine-only route on a machine with no engine.