Gateway/Get started/Migrate from OpenRouter
Migrate from OpenRouter
Model slugs match OpenRouter. Swap the base URL and the key; the rest of your code stays.
Change two lines
const client = new OpenAI({
// baseURL: "https://openrouter.ai/api/v1",
baseURL: "https://api.inferencebureau.com/v1",
apiKey: process.env.IB_API_KEY,
});What stays the same
- Model slugs, such as
openai/gpt-4o-mini. - The chat completions request and response shape, including streaming, tools, and
response_format. - Token usage fields in the response.
What is different
| Inference Bureau | |
|---|---|
| AI SDK | Replace @openrouter/ai-sdk-provider with @inferencebureau/ai-sdk-provider: ib("openai/gpt-4o-mini") takes the same model slugs. See AI SDK. |
| Model fallback | Off. The model you request is the model that answers, unless model fallback is allowed in Directives. OpenRouter's models list is accepted and ignored. |
| Provider choice | Dispatch tries certified providers in a fixed order (see Routing). Limit them with allowedProviders or deniedProviders in Directives, not per request. |
| Presets | OpenRouter's @preset/… models become team aliases: send org/fast as the model, and define it once in Directives as a model id or a preset (model, fallback models, and defaults for temperature, top_p, max output tokens and reasoning effort). Values in the request win over the preset's. |
| data_collection | Instead of provider.data_collection: "deny" per request, set data.requireNoTraining in Directives to use only providers listed as not training on prompts; requireZdr requires zero data retention. Per-request provider preferences are not used. |
| max_tokens | Without max_tokens, output is limited to 4,096 tokens, because every request reserves its worst-case cost up front. Set it explicitly for longer answers. |
| Balance and limits | Prepaid: requests are refused with 402 when the balance can't cover them. Every team has default rate limits (600 requests and 2,000,000 tokens a minute, 10 at once); see Rate limits. |
| Costs | Look up any request with GET /v1/requests/:id for its final charge. |
| Headers | OpenRouter-specific headers such as HTTP-Referer and X-Title are not used. Send X-Client-Request-ID for your own correlation id. |
| Claude models | Chat completions works, but tools and tool_choice go through an OpenAI-shaped translation. For Claude tool use, especially forced tools, call POST /v1/messages with the Anthropic SDK: requests pass through natively. |
| Web search | OpenRouter's :online suffix and plugins aren't supported. Claude searches through the web_search tool, and Perplexity Sonar searches on every request. See Web search. |
| Retries | If a provider fails before it starts answering, the request is retried on the same model, at most three attempts in all. Each attempt is listed on the receipt. See Routing. |
| End users | The user field works as on OpenRouter: it is recorded as your end user and never forwarded. Logs, usage export and per-end-user limits and budgets in Directives use it. See End users and tags. |
| Tags | Send ib-tags (or ib.tags) to break costs down by feature. They are kept by Inference Bureau and cost nothing extra. |
| Embeddings | POST /v1/embeddings works for certified embedding models; GET /v1/models lists them with type: "embedding". |
| Responses API | POST /v1/responses works on models certified for it. Responses are kept only with store: true (OpenRouter keeps none), for 30 days, so previous_response_id can continue them. OpenAI's web_search needs max_tool_calls; its other hosted tools are refused. |
Only certified models can be called. GET /v1/models lists the ones your key may use, with their capabilities, and Models shows the full catalog with certification status.