This guide walks an app developer from nothing to a first chat completion on the B3IQ hosted gateway. The gateway is OpenAI-compatible, so most existing clients work with a base URL and a key swap.

Use https://b3iq.org/v1/api as the gateway base URL for application traffic. Hosted inference is free — your keys route to the machines on your own account under B3IQ router policy.

Already using the OpenAI SDK?

Skip the raw HTTP below — the OpenAI SDK Quickstart covers the same flow as a base_url/api_key swap in Python or JavaScript.

B3IQ network inference rates

From Zero To A First Call

1

Create an account and a gateway key

Sign in to the dashboard and create a gateway key. Hosted keys are b3iq_gateway_ secrets — they are shown once, stored hashed, and revocable. Save the value to a file you control rather than pasting it into scripts.

2

Have a machine on your account

Your keys route 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 to bring one up, and Usage & Quotas for how free usage is metered.

3

List the live models

Read GET /v1/api/models with your key. The response is exactly the models the machines on your account serve right now — the set changes as your machines come and go.

4

Make your first chat call

Send POST /v1/api/chat/completions with a model id from the list and your gateway key. The request fails closed if no machine on your account can serve it or it is not allowed by policy.

5

Handle errors and add streaming

Read the stable machine code on any denial, then set stream: true once the non-streaming call works.

Store Your Key In A File

Keep the secret out of argv and shell history. Write it to a file, lock the permissions, and read it from there.

bash
umask 077printf '%s\n' 'b3iq_gateway_...' > "$HOME/.b3iq/gateway-key"chmod 600 "$HOME/.b3iq/gateway-key"
Never put the key in argv

Process arguments are visible to other processes and land in shell history. Read b3iq_gateway_ secrets from a chmod 600 file or an environment variable, and pass them to curl through a temporary config file — never as a literal -H flag on the command line.

The examples below expect two variables:

bash
export B3IQ_GATEWAY_BASE_URL="https://b3iq.org/v1/api"export B3IQ_GATEWAY_KEY_FILE="$HOME/.b3iq/gateway-key"

List Models First

Send your key with the list call. With a key, the response is not a network catalog — it is your machines' models, so an id you see is an id you can call.

bash
: "${B3IQ_GATEWAY_BASE_URL:?set B3IQ_GATEWAY_BASE_URL}": "${B3IQ_GATEWAY_KEY_FILE:?set B3IQ_GATEWAY_KEY_FILE}"cfg="$(mktemp)"chmod 600 "$cfg"trap 'rm -f "$cfg"' EXIT{ printf 'url = "%s/models"\n' "${B3IQ_GATEWAY_BASE_URL%/}" printf 'header = "Authorization: Bearer %s"\n' "$(sed -n '1p' "$B3IQ_GATEWAY_KEY_FILE")"} > "$cfg"curl --fail --silent --show-error --config "$cfg"
With your key, the list is your machines

The model field takes an id returned by GET /v1/api/models. Sent with your gateway key, that list is exactly the models the machines on your account serve right now — machines you've switched to Earn mode are excluded, and any node scope on the key is respected. The chat example below uses a representative id (qwen3-8b); always list the live models first, since the set changes as your machines come and go. Without a key the endpoint returns the public network-wide catalog instead, which says nothing about what your account can route to.

Or check with the CLI

The b3iq CLI makes the same call for you: install it, run b3iq login, then b3iq models list to see what your keys can route to before writing any application code.

First Chat Completion

bash
: "${B3IQ_GATEWAY_BASE_URL:?set B3IQ_GATEWAY_BASE_URL}": "${B3IQ_GATEWAY_KEY_FILE:?set B3IQ_GATEWAY_KEY_FILE}"cfg="$(mktemp)"chmod 600 "$cfg"trap 'rm -f "$cfg"' EXIT{ printf 'url = "%s/chat/completions"\n' "${B3IQ_GATEWAY_BASE_URL%/}" printf 'request = "POST"\n' printf 'header = "Authorization: Bearer %s"\n' "$(sed -n '1p' "$B3IQ_GATEWAY_KEY_FILE")" printf 'header = "Content-Type: application/json"\n'} > "$cfg"curl --fail --silent --show-error --config "$cfg" --data-binary @- <<'JSON'{ "model": "qwen3-8b", "messages": [{ "role": "user", "content": "Say hello from B3IQ." }], "max_tokens": 64}JSON

A successful response is an OpenAI-style chat completion, served free by a machine on your account. The X-B3IQ-Router-Node-ID response header tells you which one served it.

Handle Errors

Hosted chat fails closed rather than routing somewhere you did not intend. Common denials and what they mean:

  • no_eligible_nodes — no machine on your account serves the requested model right now. If you listed models with your key first, this mostly means a machine went offline in between; it is the expected failure only when the id came from the anonymous network-wide list.
  • Out-of-policy model or route tier.
  • Per-key or per-account rate limits exceeded.
  • account_token_quota_exceeded — the account's daily token quota is exhausted (the default quota is uncapped).

Every denial carries a stable machine code in an OpenAI-style error object. Branch on the code, not the human-readable message. See Errors for the full list.

Streaming

Set stream: true to receive Server-Sent Events. The gateway proxies the selected node stream and still parses final usage and receipt metadata, so streamed requests are metered the same as non-streamed ones.

json
{ "model": "qwen3-8b", "messages": [{ "role": "user", "content": "Stream a short response." }], "stream": true}

Get the non-streaming call working first, then flip stream on — error envelopes and metering behavior are otherwise identical.

OpenAI SDK Quickstart

The same flow with the official Python and JavaScript OpenAI SDKs instead of raw HTTP.

Learn More
Hosted gateway

Full endpoint list, headers, and the gate order a request passes.

Learn More
Usage & quotas

Free inference, per-key metering, rate limits, and the token quota.

Learn More
Errors

Stable machine codes for auth, policy, routing, and quota denials.

Learn More
Ask a question... ⌘I