Node.js Integration
Use the OpenAI Node client with the documented Keeptrusts Chat Completions route and a client API token. Keep the client in a trusted server runtime; do not expose the token in browser code or infer support for an unlisted OpenAI route.
Prerequisites
-
Complete the Quickstart and keep the gateway running.
-
Create a client API token for the application.
-
Install the client:
npm install openai
Set the connection values in the server environment:
export KEEPTRUSTS_GATEWAY_URL="http://127.0.0.1:41002/v1"
export KEEPTRUSTS_REQUEST_TOKEN="kt_..."
export KEEPTRUSTS_MODEL="gpt-5.4-mini"
Send a chat request
import OpenAI from "openai";
function requiredEnv(name: string): string {
const value = process.env[name];
if (!value) throw new Error(`${name} is required`);
return value;
}
const model = requiredEnv("KEEPTRUSTS_MODEL");
const client = new OpenAI({
baseURL: requiredEnv("KEEPTRUSTS_GATEWAY_URL"),
apiKey: requiredEnv("KEEPTRUSTS_REQUEST_TOKEN"),
});
const response = await client.chat.completions.create({
model,
messages: [
{ role: "user", content: "Summarize this incident report." },
],
});
console.log(response.choices[0]?.message.content);
The model name must be exposed by the gateway. Setting the environment variable does not create an upstream provider target.
Stream a response
const stream = await client.chat.completions.create({
model,
messages: [{ role: "user", content: "Explain this change." }],
stream: true,
});
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta.content ?? "");
}
Input policies run before the upstream request. Policies that require the complete output can buffer streaming responses, so validate latency with the actual chain. See Streaming and SSE.
Use the client in a server route
Create one server-side client and inject it into the handlers that need model access. Never serialize the token into HTML, a client bundle, or a public runtime environment variable.
export async function summarize(input: string): Promise<string> {
const response = await client.chat.completions.create({
model,
messages: [{ role: "user", content: input }],
});
return response.choices[0]?.message.content ?? "";
}
Handle gateway decisions
try {
await summarize("Review this text.");
} catch (error) {
if (error instanceof OpenAI.APIError) {
if (error.status === 400 && error.code === "content_policy_violation") {
console.error("Blocked by policy");
} else if (error.status === 401 || error.status === 403) {
console.error("Client token rejected");
} else if (error.status === 429) {
console.error("Rate limited");
} else {
throw error;
}
} else {
throw error;
}
}
Do not blindly retry a model request. A timeout does not prove that the upstream call failed before it incurred usage.
Verify the governed path
curl -fsS \
-H "Authorization: Bearer ${KEEPTRUSTS_REQUEST_TOKEN}" \
"${KEEPTRUSTS_GATEWAY_URL}/models"
kt events tail --since 10m --follow
Send a representative request while the event tail is active. The matching event is the proof that the Node.js process used Keeptrusts.