OpenAI SDK Quickstart
Use the OpenAI Python or JavaScript SDK with B3IQ: configure your key and endpoint, select a served model, and send chat or streaming requests.
The hosted gateway is OpenAI-compatible, so the official openai SDK works
for the supported chat, streaming, and model-list methods. Start by changing
the base URL and key, then select a model your own machine is serving.
Set B3IQ_API_KEY to your gateway key as described below. These examples use
your-served-model-id; replace it with a model ID returned by client.models.list().
The model must be served by your machines and available to this key. Changing
the client configuration does not change an existing request's model value.
pythonimport osfrom openai import OpenAIclient = OpenAI( base_url="https://b3iq.org/v1/api", api_key=os.environ["B3IQ_API_KEY"],)reply = client.chat.completions.create( model="your-served-model-id", messages=[{"role": "user", "content": "Hi"}],)print(reply.choices[0].message.content)
typescriptimport OpenAI from "openai";const client = new OpenAI({ baseURL: "https://b3iq.org/v1/api", apiKey: process.env.B3IQ_API_KEY,});const reply = await client.chat.completions.create({ model: "your-served-model-id", messages: [{ role: "user", content: "Hi" }],});console.log(reply.choices[0].message.content);
chat.completions.create, streaming, and models.list() use the SDK methods
shown below. Provider-specific tools and unsupported endpoints do not become
available by changing the base URL. Requests are free and route only to
the machines on your own account.
Change base_url/baseURL and api_key/apiKey, then set model on each
request to an ID available to your B3IQ key. Model IDs and optional features
can differ between providers.
Before you start
Create a gateway key
Sign in to the dashboard and create a gateway key. Hosted keys are
b3iq_gateway_ secrets, shown once, stored hashed, and revocable.
Have a machine online
Your key routes only to machines on your own account, so you need at least one online machine serving the model you want to call. See Run your first node.
Install the SDK
bashpip install openai
bashnpm install openai
Read b3iq_gateway_ secrets from an environment variable, not a literal
string in committed code.
bashexport B3IQ_API_KEY="b3iq_gateway_..."
Create the client
pythonimport osfrom openai import OpenAIclient = OpenAI( base_url="https://b3iq.org/v1/api", api_key=os.environ["B3IQ_API_KEY"],)
typescriptimport OpenAI from "openai";const client = new OpenAI({ baseURL: "https://b3iq.org/v1/api", apiKey: process.env.B3IQ_API_KEY,});
List your models
Call models.list() before you call chat. It tells you exactly what you can
route to right now. Replace your-served-model-id in the examples with the exact
ID returned by the list, including any model tag. The placeholder is not a model
you can call.
pythonfor model in client.models.list(): print(model.id)
typescriptconst models = await client.models.list();for await (const model of models) { console.log(model.id);}
Called with your gateway key, models.list() returns only the models the
machines on your account serve right now: any node scope on the key is
respected, and machines you've switched to Earn mode are excluded. The list reflects
eligible routes at request time; the set changes as your
machines come and go, so list before you call rather than hardcoding an id.
Without an owner-scoped key, the same endpoint returns data: []. It does
not advertise a shared public pool. See Hosted Gateway.
If the list is empty or your expected model is missing, check that the key belongs to the intended account, its machine scope includes the serving machine, and that machine is online, serving the model, and not in Earn mode. Check the machine's model status in the dashboard, then list models again.
Chat completion
pythonresponse = client.chat.completions.create( model="your-served-model-id", # use an id from models.list() messages=[{"role": "user", "content": "Say hello from B3IQ."}],)print(response.choices[0].message.content)
typescriptconst response = await client.chat.completions.create({ model: "your-served-model-id", // use an id from models.list() messages: [{ role: "user", content: "Say hello from B3IQ." }],});console.log(response.choices[0].message.content);
A successful call returns a standard OpenAI ChatCompletion object, served
free by a machine on your account.
Streaming
Set stream=True / stream: true and iterate the SDK's stream object exactly
as you would against OpenAI.
pythonstream = client.chat.completions.create( model="your-served-model-id", messages=[{"role": "user", "content": "Stream a short response."}], stream=True,)for chunk in stream: delta = chunk.choices[0].delta.content if chunk.choices else None if delta: print(delta, end="", flush=True)
typescriptconst stream = await client.chat.completions.create({ model: "your-served-model-id", messages: [{ role: "user", content: "Stream a short response." }], stream: true,});for await (const chunk of stream) { const delta = chunk.choices[0]?.delta?.content; if (delta) process.stdout.write(delta);}
Streamed requests are metered the same as non-streamed ones. Get the
non-streaming call working first, then flip stream on.
Handling errors
Denials come back as a standard OpenAI-style error object, so SDK exceptions
behave the way they do against OpenAI. Catch the SDK's API error type and
branch on the stable machine code, not the human-readable message.
pythonfrom openai import APIStatusErrortry: client.chat.completions.create( model="your-served-model-id", messages=[{"role": "user", "content": "Say hello from B3IQ."}], )except APIStatusError as e: print(e.status_code, e.code)
typescriptimport OpenAI from "openai";try { await client.chat.completions.create({ model: "your-served-model-id", messages: [{ role: "user", content: "Say hello from B3IQ." }], });} catch (err) { if (err instanceof OpenAI.APIError) { console.error(err.status, err.code); }}
A no_eligible_nodes code means no machine on your account serves that model
right now. Call models.list() again rather than retrying blind. See
Errors for the full list of stable codes.
The b3iq CLI makes the same calls without writing code:
install it, run b3iq login, then b3iq models list to see what your keys
can route to.

