Introduction
Structured outputs allow you to obtain AI responses that always conform to a precise format via JSON Schema. This approach eliminates parsing errors and guarantees immediately usable data. In 2026, it has become essential for professional applications that integrate language models. This tutorial guides you step by step to implement this feature with OpenAI and TypeScript.
Prerequisites
- Node.js 20+
- OpenAI account with API key
- Basic knowledge of TypeScript
- npm or pnpm installed
Installing Dependencies
npm install openai zod
npm install -D @types/node typescriptWe install the official OpenAI SDK and Zod for schema validation. These packages make it easy to define and validate the expected data structures.
Defining the JSON Schema
import { z } from 'zod';
export const UserSchema = z.object({
name: z.string().min(2),
email: z.string().email(),
age: z.number().int().min(18),
interests: z.array(z.string()).max(5)
});
export type User = z.infer<typeof UserSchema>;This Zod schema defines the expected structure. It will be converted to JSON Schema for the OpenAI API and enables strict validation on the client side.
Configuring the OpenAI Client
import OpenAI from 'openai';
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
export default openai;Initialize the client with the API key stored in environment variables. Always use environment variables for sensitive keys.
Calling with Structured Outputs
import openai from './openai';
import { UserSchema } from '../schemas/user';
export async function generateUser(prompt: string) {
const completion = await openai.chat.completions.create({
model: 'gpt-4o-2024-08-06',
messages: [{ role: 'user', content: prompt }],
response_format: {
type: 'json_schema',
json_schema: {
name: 'user',
schema: UserSchema,
strict: true
}
}
});
return UserSchema.parse(JSON.parse(completion.choices[0].message.content!));
}The response_format option with json_schema forces the model to exactly match the schema. The strict flag ensures full compliance without deviation.
Usage in an API Route
import { generateUser } from '@/lib/generateUser';
import { NextResponse } from 'next/server';
export async function POST(req: Request) {
const { prompt } = await req.json();
const user = await generateUser(prompt);
return NextResponse.json(user);
}Example integration in a Next.js API. The function returns a typed and validated object ready to be consumed by the frontend.
Best Practices
- Always enable strict mode to guarantee compliance
- Use clear descriptions in the schema
- Limit schema size to reduce costs
- Validate data client-side with Zod after receipt
- Version your schemas for model evolution
Common Errors to Avoid
- Forgetting the strict flag which allows non-compliant responses
- Defining overly complex schemas that cause the call to fail
- Not handling Zod validation errors
- Exposing the API key in frontend code
Going Further
Discover our advanced training on structured AI integration: https://learni-group.com/formations