Environment
This example uses Node.js with built-in fetch and no SDK. Configure GATEWAY_API_KEY in a server-side environment variable and optionally GATEWAY_BASE_URL. It calls the free sandbox-chat model; switch to a production alias from GET /v1/models when you use a production key.
A complete request
const baseURL = process.env.GATEWAY_BASE_URL ?? 'https://gateway.accountablehq.com';
const apiKey = process.env.GATEWAY_API_KEY;
if (!apiKey) throw new Error('Set GATEWAY_API_KEY in your environment');
const response = await fetch(`${baseURL}/v1/chat/completions`, {
method: 'POST',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
'Idempotency-Key': 'javascript-001',
},
body: JSON.stringify({
model: 'sandbox-chat',
messages: [{ role: 'user', content: 'Explain an AI gateway in one sentence.' }],
max_tokens: 64,
}),
});
const result = await response.json();
if (!response.ok) {
throw new Error(`${response.status}: ${result.error?.code ?? 'unknown_error'}`);
}
console.log(result.choices[0].message.content);
console.log({ requestId: result.id, usage: result.usage, cost: result.gateway.charged_usd });With the official OpenAI SDK
import OpenAI from 'openai';
const client = new OpenAI({
baseURL: 'https://gateway.accountablehq.com/v1',
apiKey: process.env.GATEWAY_API_KEY,
maxRetries: 0, // retry deliberately with an Idempotency-Key instead
});
const completion = await client.chat.completions.create(
{
model: 'sandbox-chat', // later: a production alias such as 'gpt-6-luna'
messages: [{ role: 'user', content: 'Explain an AI gateway in one sentence.' }],
max_tokens: 64,
},
{ headers: { 'Idempotency-Key': crypto.randomUUID() } },
);
console.log(completion.choices[0].message.content);Automatic SDK retries are turned off on purpose. A timeout does not prove the model did not run, so a blind retry can be billed twice. Retry only with the same Idempotency-Key; the gateway refuses a duplicate while the first attempt is pending or succeeded, and accepts the same key again after a failure that cost nothing. See idempotency.
Adapt for your service
- Discover the catalog before choosing a model in another environment.
- Generate and persist a non-sensitive logical request ID for each job; the fixed example idempotency key is only for a single run.
- Capture status and request IDs without logging authorization headers or sensitive content.
- Do not treat a network exception as proof that the provider did not run.
- Bound concurrency and implement outcome-aware retries.
Keep the key out of the browser
Run this integration behind your own authenticated backend. The Gateway API has no cross-origin browser support intended for exposing secrets directly. Do not use a public frontend environment variable or ship the key in a client bundle.