Documentation

BreignHUB speaks the OpenAI wire format. Point any client at the base URL below, use a BreignHUB key as the API key, and the rest of your code stays as it is.

Base URL and authentication

Your key goes in the Authorization header as a bearer token. Keys are created in the dashboard and shown once — BreignHUB does not store the secret and cannot show it to you again.

Base URL
https://hub.breign.eu/api/v1
API key
A key from the dashboard, starting with bh-

Call it from your server, not from a browser

/api/v1 sends no CORS headers, so a page on another origin cannot reach it. That is deliberate: a BreignHUB key in front-end code is a key you have published. Keep it on your own server, or behind a proxy you control.

Your first call

Model ids carry the provider that serves them, in the form providerId/modelName. List them with GET /models, or read them from the catalogue.

first-call.sh
curl https://hub.breign.eu/api/v1/chat/completions \
  -H "Authorization: Bearer $BREIGNHUB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "<providerId>/<modelName>",
    "messages": [{ "role": "user", "content": "Say hello." }]
  }'

From the OpenAI SDK

Nothing but the base URL changes. Streaming works the same way.

python
from openai import OpenAI

client = OpenAI(
    base_url="https://hub.breign.eu/api/v1",
    api_key=os.environ["BREIGNHUB_API_KEY"],
)

stream = client.chat.completions.create(
    model="<providerId>/<modelName>",
    messages=[{"role": "user", "content": "Say hello."}],
    stream=True,
)

for chunk in stream:
    print(chunk.choices[0].delta.content or "", end="")
typescript
import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://hub.breign.eu/api/v1",
  apiKey: process.env.BREIGNHUB_API_KEY,
});

const stream = await client.chat.completions.create({
  model: "<providerId>/<modelName>",
  messages: [{ role: "user", content: "Say hello." }],
  stream: true,
});

for await (const chunk of stream) {
  process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
}

Listing models

Returns the models the key’s organization can reach. Model availability comes from the organization, not from the key.

models.sh
curl https://hub.breign.eu/api/v1/models \
  -H "Authorization: Bearer $BREIGNHUB_API_KEY"

Embeddings

A batch is accepted and fanned out: the Breign gateway embeds one string per call, so BreignHUB caps a batch at 64 and reassembles the results in order.

embeddings.sh
curl https://hub.breign.eu/api/v1/embeddings \
  -H "Authorization: Bearer $BREIGNHUB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "<providerId>/<modelName>",
    "input": ["premier texte", "second texte"]
  }'

What the gateway does not support

The Breign gateway accepts a narrow subset of the OpenAI request. Fields that would change the answer are refused with a 400 naming them, rather than ignored — honouring a request while dropping its tools or its response_format would hand you a wrong answer that looks right.

FieldBehaviour
model, messages, max_tokens, temperature, stream, stream_optionsForwarded
user, metadata, store, service_tier, n: 1Accepted and ignored, listed in the X-BreignHub-Ignored-Fields response header
tools, tool_choice, functions, response_format, top_p, seed, stop, logprobs, presence_penalty, frequency_penalty, logit_biasRefused with a 400 naming the field
temperature > 1Refused above 1. OpenAI allows up to 2; clamping would silently change your results
image / audio content partsRefused — the gateway is text-only
role: developerMapped to system

Using BreignHUB from a coding agent

Any tool that lets you set an OpenAI-compatible base URL works. Two examples.

opencode

Add a provider to opencode.json. Use @ai-sdk/openai-compatible, which targets /v1/chat/completions. Then run /models and pick it.

opencode.json
{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "breignhub": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "BreignHUB",
      "options": {
        "baseURL": "https://hub.breign.eu/api/v1",
        "apiKey": "{env:BREIGNHUB_API_KEY}"
      },
      "models": {
        "<providerId>/<modelName>": {
          "name": "Qwen3.6 35B"
        }
      }
    }
  }
}

export BREIGNHUB_API_KEY=bh-…  ·  opencode  ·  /models

Anything else

Continue, Cline, aider, LangChain, the Vercel AI SDK — all of them take a base URL and an API key. Set those two and you are done. If a tool sends tools or response_format by default, BreignHUB will refuse the call with a message naming the field; disable that feature in the tool.

Errors

Failures use the OpenAI envelope. An error coming from the inference cluster is unwrapped rather than nested, so the message you read is the one the backend produced.

error.json
{
  "error": {
    "message": ""tools" is not supported: tool calling is not exposed by the Breign gateway.",
    "type": "invalid_request_error",
    "param": "tools",
    "code": "unsupported_parameter"
  }
}

# 401 missing_api_key · 401 invalid_api_key · 400 · 5xx

Create a key

Keys are created and revoked from the dashboard.

Create a key