Skip to content
IQ Routing

OpenAI · Node

The OpenAI Node/TypeScript SDK accepts baseURL and apiKey on the client constructor. Swap the base URL and your existing call sites route through the gateway. This recipe ships a runnable TypeScript file that you can drop into a fresh pnpm init project with openai installed.

Drop-in switch

const client = new OpenAI({
  baseURL: "https://gateway.iq-routing.com/v1",
  apiKey: process.env.IQ_GATEWAY_KEY,
});

Everything below this line (client.chat.completions.create, client.embeddings, client.models.list) routes through the gateway.

Verify it routes

import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://gateway.iq-routing.com/v1",
  apiKey: process.env.IQ_GATEWAY_KEY!,
  timeout: 60_000,
  maxRetries: 0,
});

const response = await client.chat.completions
  .create({
    model: "auto",
    messages: [{ role: "user", content: "Summarise: routing-aware gateway." }],
    max_tokens: 64,
  })
  .withResponse();

console.log("X-Request-Id:", response.response.headers.get("x-request-id"));
const telemetry = JSON.parse(response.response.headers.get("x-iq-routing") ?? "{}");
console.log("Model picked:", telemetry.chosen_model);
console.log("Provider:", telemetry.chosen_provider);
console.log("Cache hit:", telemetry.cache_hit);
console.log(response.data.choices[0].message.content);

Run with IQ_GATEWAY_KEY=... npx tsx verify.ts. The gateway emits two response headers per request: X-Request-Id (the correlation handle) and x-iq-routing (a JSON-encoded telemetry blob with the chosen model, provider, classifier verdict, cache-hit flag, latencies, and cost). The body is the standard OpenAI chat completion shape.

Using capability aliases

The cap:<name> syntax in the model field tells the gateway to pick a concrete model at routing time based on the capability's stable intent rather than a pinned model id. The operator's per-org overrides plus the focus-mode bias plus the circuit-breaker state shape the resolved tuple. The six default capabilities are reason-heavy, tool-call-strict, long-context-128k, vision, cheap-fast, and json-mode.

import OpenAI from "openai";

const openai = new OpenAI({
  baseURL: "https://gateway.iq-routing.com/v1",
  apiKey: process.env.IQ_GATEWAY_KEY!,
});

const completion = await openai.chat.completions.create({
  model: "cap:reason-heavy",
  messages: [{ role: "user", content: "Plan the migration in three phases." }],
});

The resolved provider plus model surface in the x-iq-routing response header (a JSON-encoded payload with chosen_provider and chosen_model fields, among others), so the SDK consumer can inspect which concrete model handled the request via .withResponse(). Decode the header with JSON.parse(response.response.headers.get("x-iq-routing")). See the capability aliases docs for the full resolver decision tree plus the override mechanics. The operator can override the default capability mapping via the capabilities dashboard editor at /settings/capabilities.

Common gotchas

Node's default fetch timeout depends on the runtime (Node 18+ uses undici, which has a default of 5 minutes for headers). Pass an explicit timeout on the client to align with the gateway's 30-second p99.

The SDK's maxRetries defaults to 2. The gateway's 429 carries a Retry-After header; SDK-side retries on top of the cooldown window double-bill. Set maxRetries: 0 and let your own queue handle backoff.

Streaming uses the standard stream: true flag. The gateway forwards the chunked SSE; the X-Request-Id arrives on the response headers before the first chunk, so you can log the correlation handle even on a streamed response.

If you use the SDK in a Next.js route handler, set runtime: "nodejs" on the route. Edge runtime works for the request itself but loses the streaming SSE shape on some Vercel regions; the Node runtime is the safe default for the gateway's response shape.

Try this in the playground

Run this snippet against your gateway key →