Qubittron Bastion
API reference

Chat completions

POST /v1/chat/completions — OpenAI-compatible chat with optional streaming.

POST https://api.qubittron.ai/v1/chat/completions

The primary entry point for conversational LLMs. OpenAI-compatible — drop in your existing SDK code with baseURL swapped.

Authentication

Authorization: Bearer qbt_<key>

Request body

FieldTypeRequiredNotes
modelstringyesAny LLM model id (see below)
messagesMessage[]yesOpenAI message format
streambooleannoWhen true, returns SSE stream
max_tokens, temperature, top_p, tools, tool_choice, response_format, etc.variousnoPassed through to upstream

Unknown fields pass through unchanged — Bastion does not strip OpenAI fields it doesn't recognize.

Supported models

ModelCategory
gpt-oss-120bLLM
gpt-oss-20bLLM
Llama-3.1-8B-InstructLLM
Meta-Llama-3_3-70B-InstructLLM
Qwen3-32BLLM
Mistral-7B-Instruct-v0.3LLM
Mistral-Small-3.2-24B-Instruct-2506LLM
Mistral-Nemo-Instruct-2407LLM
Qwen3-Coder-30B-A3B-InstructCode
Qwen2.5-VL-72B-InstructVision
Qwen3Guard-Gen-8BSafety
Qwen3Guard-Gen-0.6BSafety

Tool/structured-output support is not enforced by Bastion — the request passes through unchanged. Models that don't support tools or response_format upstream may return a 502.

Use GET /v1/models for the live list on your account.

Examples

curl https://api.qubittron.ai/v1/chat/completions \
  -H "Authorization: Bearer $QUBITTRON_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-oss-120b",
    "messages": [{ "role": "user", "content": "Reply with exactly: ok" }],
    "max_tokens": 16
  }'

Non-streaming:

import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://api.qubittron.ai/v1",
  apiKey: process.env.QUBITTRON_API_KEY,
});

const res = await client.chat.completions.create({
  model: "gpt-oss-120b",
  messages: [{ role: "user", content: "Reply with exactly: ok" }],
  max_tokens: 16,
});
console.log(res.choices[0]?.message.content);

Streaming:

const stream = await client.chat.completions.create({
  model: "gpt-oss-120b",
  messages: [{ role: "user", content: "Count from 1 to 5." }],
  stream: true,
});
for await (const chunk of stream) {
  process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
}
const res = await fetch("https://api.qubittron.ai/v1/chat/completions", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.QUBITTRON_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    model: "gpt-oss-120b",
    messages: [{ role: "user", content: "Reply with exactly: ok" }],
    max_tokens: 16,
  }),
});
const json = (await res.json()) as {
  choices: { message: { role: string; content: string } }[];
  usage: { prompt_tokens: number; completion_tokens: number; total_tokens: number };
};
console.log(json.choices[0]?.message.content);

Response

Non-streaming:

{
  "id": "chatcmpl-...",
  "object": "chat.completion",
  "created": 1735689600,
  "model": "gpt-oss-120b",
  "choices": [
    {
      "index": 0,
      "message": { "role": "assistant", "content": "ok" },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 12,
    "completion_tokens": 1,
    "total_tokens": 13
  }
}

Streaming (stream: true) returns text/event-stream with OpenAI-format data: {…} chunks ending with data: [DONE].

Errors

StatusCodeWhen
400invalid_requestBody failed validation (messages missing, etc.)
400model_not_foundModel unknown or doesn't support chat
401invalid_api_keyMissing/invalid Bearer token
402insufficient_fundsAccount credit exhausted
429rate_limit_exceededRate limit hit
502upstream_errorUpstream model unreachable or 5xx

Pricing

Metered per token (input + output). Per-model rates are listed on your dashboard.

On this page