LinuxAir
Docs / API reference

API reference

LinuxAir implements the OpenAI Chat Completions API. Existing SDKs work unchanged — only the base URL and key differ.

Base URL & authentication

https://ai.linuxair.com/v1

Send your LinuxAir key as a bearer token, or in an x-api-key header:

http
Authorization: Bearer la-xxxxxxxxxxxxxxxxxxxxxxxx

Keys issued before the LinuxAir rebrand (prefix rq-) continue to work. Each key has its own requests-per-minute limit.

Create a chat completion

POST/v1/chat/completions

Routes the request and returns a standard chat completion.

Body

FieldTypeDescription
messagesarrayRequired. OpenAI-format messages.
modelstringauto (default), la/quality, la/balanced, la/economy, or the id of a model in your workspace to pin it.
streambooleanStream tokens as server-sent events.
temperature, top_p, max_tokens, stop, presence_penalty, frequency_penalty, seed, userPassed through to the chosen model.
response_format, tools, tool_choicePassed through. Answer checks are skipped when tools are used.
laobjectOptional routing controls (below). Also accepted as linuxair.

Routing controls

FieldTypeDescription
lambdanumber 0–2Price weight. 0 = quality first, 2 = savings first.
tolerancenumber 0–0.3Max predicted-quality loss accepted, as a fraction (0.02 = 2 pts). Defaults from λ.
min_qualitynumber 0–1Exclude models predicted below this quality.
max_costnumberEstimated USD ceiling for this request.
modelsarrayOnly consider these models (ids or names).
excludearrayNever use these models.
latency_weightnumber 0–1Prefer faster models among near-equals.
cascadebooleanEnable or disable answer checks for this request.
cachebooleanSet false to bypass the semantic cache for this request.
r = client.chat.completions.create(
    model="auto",
    messages=[{"role": "user", "content": "Classify this ticket: ..."}],
    extra_body={"la": {"tolerance": 0.02, "max_cost": 0.002, "exclude": ["gpt-4o"]}},
)
const r = await client.chat.completions.create({
  model: "auto",
  messages: [{ role: "user", content: "Classify this ticket: ..." }],
  // @ts-ignore — extra routing controls
  la: { tolerance: 0.02, max_cost: 0.002, exclude: ["gpt-4o"] },
});
curl https://ai.linuxair.com/v1/chat/completions \
  -H "Authorization: Bearer $LINUXAIR_KEY" -H "Content-Type: application/json" \
  -d '{"model":"auto","messages":[{"role":"user","content":"Classify this ticket"}],
       "la":{"tolerance":0.02,"max_cost":0.002}}'

Response

A standard chat completion, plus a linuxair object and headers X-LinuxAir-Request-Id, X-LinuxAir-Model and X-LinuxAir-Cache (hit or miss).

json
{
  "id": "chatcmpl-rq_8f3a...",
  "object": "chat.completion",
  "model": "gpt-4.1-mini",
  "choices": [{ "index": 0, "message": { "role": "assistant", "content": "..." }, "finish_reason": "stop" }],
  "usage": { "prompt_tokens": 212, "completion_tokens": 96, "total_tokens": 308 },
  "linuxair": {
    "request_id": "rq_8f3a...",
    "model_label": "GPT-4.1 Mini",
    "cluster": 2,
    "lambda": 0.35,
    "tolerance": 0.026,
    "predicted_quality": 0.93,
    "predicted_error": 0.07,
    "uncertainty": 0.018,
    "reason": "within 1.1 pts of the best model, 6.2x cheaper",
    "escalated": false,
    "cached": false,
    "judge_score": null,
    "cost_usd": 0.00024,
    "baseline_cost_usd": 0.00149,
    "saved_usd": 0.00125,
    "candidates": [
      { "model": "gpt-4.1-mini", "predicted_quality": 0.93, "in_tolerance": true, "est_cost_usd": 0.00024, "why": "..." },
      { "model": "gpt-4.1", "predicted_quality": 0.94, "in_tolerance": true, "est_cost_usd": 0.00149, "why": "..." }
    ]
  }
}

Streaming

Set stream: true to receive OpenAI-format server-sent events ending with data: [DONE]. The chosen model is in the X-LinuxAir-Model response header. Failover happens before the first token; answer checks are not applied to streamed responses.

python
stream = client.chat.completions.create(model="la/balanced", stream=True,
    messages=[{"role": "user", "content": "Draft a polite payment reminder"}])
for chunk in stream:
    print(chunk.choices[0].delta.content or "", end="")

Embeddings

POST/v1/embeddings

Same base URL and key as completions, so one endpoint covers both.

python
r = client.embeddings.create(model="auto", input=["first text", "second text"])
print(len(r.data[0].embedding))

Batch

POST/v1/batches

Send up to 500 requests at once. They run in the background at a reduced platform fee and are routed, logged and metered exactly like live requests.

bash
curl https://ai.linuxair.com/v1/batches \
  -H "Authorization: Bearer $LINUXAIR_KEY" -H "Content-Type: application/json" \
  -d '{"requests": [
    {"custom_id": "row-1", "messages": [{"role":"user","content":"Classify: ..."}]},
    {"custom_id": "row-2", "messages": [{"role":"user","content":"Classify: ..."}]}
  ]}'
POST/v1/batches/retrieve
bash
curl https://ai.linuxair.com/v1/batches/retrieve \
  -H "Authorization: Bearer $LINUXAIR_KEY" -H "Content-Type: application/json" \
  -d '{"id": "batch_id_here"}'

The response carries status, counts, total cost and savings, and once finished a results array keyed by your custom_id.

List models

GET/v1/models

Returns the routing aliases and every active model in your workspace, with its quality and prices per million tokens.

json
{ "object": "list", "data": [
  { "id": "auto", "object": "model", "owned_by": "linuxair" },
  { "id": "la/quality", "object": "model", "owned_by": "linuxair" },
  { "id": "gpt-4.1-mini", "object": "model", "owned_by": "workspace",
    "quality": 0.88, "input_price_per_mtok": 0.4, "output_price_per_mtok": 1.6 }
] }

Send feedback

POST/v1/feedback
FieldDescription
request_idThe linuxair.request_id, or the completion id (the chatcmpl- prefix is accepted).
score"up" / "down", 1 / -1, or a number from 0 to 1.

Feedback updates the chosen model's live error for the prompt's clusters. Re-sending the same prompt within the retry window (two minutes by default) is also treated as negative feedback automatically.

Errors

Errors use the OpenAI shape: {"error": {"message": "...", "type": "...", "code": "..."}}.

StatusCodeMeaning
400invalid_request_errorMalformed body, for example missing messages.
400no_modelsThe workspace has no active models yet.
400no_eligible_modelConstraints (context window, max_cost, min_quality, allow-list) or a missing capability — tools, JSON mode — excluded every model.
401invalid_api_keyMissing, wrong or revoked key.
402insufficient_creditsTop up your wallet to continue.
402budget_exceededA daily or monthly spend cap was reached. Raise it or wait for the period to roll over.
404not_foundUnknown request_id for feedback.
429rate_limit_exceededThe key's requests-per-minute limit was reached.
502upstream_errorEvery candidate model failed at the provider.
503not_readyThe routing space hasn't been built yet (operator action).