Next.js

Run the SDK on the server only: Route Handlers, Server Actions, and Server Components that perform data work on the server. Do not put your Noryen API key in client bundles.

Environment variables

Add NORYEN_API_KEY to .env.local (no NEXT_PUBLIC_prefix). For hosted deployments, configure the same secret in your host's environment.

Optional: NEXT_PUBLIC_NORYEN_API_URL if you need the browser to know a public API URL for other features—it is also read by the SDK for endpoint resolution on the server when set.

Shared server module

Initialize once in a shared module and import noryen from it everywhere. Use setContext to stamp every trace with service-level fields.

lib/noryen.ts
// lib/noryen.ts
import { noryen } from "@noryen/sdk";
noryen.init({ apiKey: process.env.NORYEN_API_KEY! });
noryen.setContext({
service: "my-next-app",
env: process.env.VERCEL_ENV || process.env.NODE_ENV || "development",
});
export { noryen };

Route Handler (App Router)

app/api/chat/route.ts
import OpenAI from "openai";
import { noryen } from "@/lib/noryen";
export async function POST(req: Request) {
const openai = noryen.wrapOpenAI(
new OpenAI({ apiKey: process.env.OPENAI_API_KEY }),
{ metadata: { route: "api/chat" } },
);
const body = await req.json();
const completion = await openai.chat.completions.create({
model: "gpt-4o-mini",
messages: body.messages,
});
return Response.json(completion);
}

On a long-running Node server, batches flush in the background. If your handler runs in a serverless runtime (one invocation then freeze), call flush() before returning—see Serverless & edge.

Server Actions

actions.ts
"use server";
import OpenAI from "openai";
import { noryen } from "@/lib/noryen";
export async function runPrompt(prompt: string) {
const openai = noryen.wrapOpenAI(
new OpenAI({ apiKey: process.env.OPENAI_API_KEY }),
{ metadata: { action: "runPrompt" } },
);
const res = await openai.chat.completions.create({
model: "gpt-4o-mini",
messages: [{ role: "user", content: prompt }],
});
return res.choices[0].message.content || "";
}

OpenRouter

The OpenAI SDK with OpenRouter's base URL wraps the same way as the hosted OpenAI API.

lib/openrouter.ts
import OpenAI from "openai";
import { noryen } from "@/lib/noryen";
const openrouter = noryen.wrapOpenAI(
new OpenAI({
baseURL: "https://openrouter.ai/api/v1",
apiKey: process.env.OPENROUTER_API_KEY,
}),
{ metadata: { route: "openrouter/chat" } },
);
await openrouter.chat.completions.create({
model: "google/gemini-2.0-flash-001",
messages: [{ role: "user", content: "Hello" }],
});

More detail: OpenRouter guide.

Never call noryen.init with the secret key inside a Client Component. If you need streaming from the client, proxy through a Route Handler that owns the SDK and key.

All installation guides