openapi to zod trpc

OpenAPI to Zod for tRPC

Use OpenAPI schemas with Zod validators around tRPC-style procedures when a TypeScript app needs contract-first API validation.

Open OpenAPI to Zod

Quick answer: does OpenAPI belong in a tRPC stack?

tRPC is usually code-first, while OpenAPI is contract-first. They can still meet when an external API, legacy service, or partner contract already owns the schema and your TypeScript app wants Zod validators at the procedure boundary.

Contract-first workflow

Start with OpenAPI when the API contract is already published or owned outside the tRPC app. Generate Zod schemas from components, review the output, then use those schemas near procedure inputs, API clients, or adapter boundaries.

  • Use OpenAPI as the source of truth when another team owns the contract.
  • Use Zod as the runtime guard inside TypeScript.
  • Do not duplicate schema ownership across OpenAPI, Zod, and manual types.

Generate Zod from OpenAPI components

A generated Zod schema gives the TypeScript side a real runtime parser instead of relying only on generated static types.

// Generated from an OpenAPI User component.
export const UserSchema = z.object({
  id: z.string(),
  email: z.string().email(),
  role: z.enum(["admin", "member"]),
});

export type User = z.infer<typeof UserSchema>;

Use schemas around tRPC procedures

Use generated schemas at boundaries where untrusted data enters or leaves the procedure. For internal procedures, prefer a single source of truth so the schema does not drift from the OpenAPI contract.

const UserInputSchema = z.object({
  id: z.string().uuid(),
});

export const userRouter = router({
  byId: publicProcedure
    .input(UserInputSchema)
    .query(async ({ input }) => {
      const response = await fetchUser(input.id);
      return UserSchema.parse(response);
    }),
});

Validate external API responses

The strongest fit is validating responses from REST services that are already documented with OpenAPI. The tRPC procedure can expose a typed result only after the response passes the generated Zod parser.

  • Treat REST response JSON as `unknown` before parsing.
  • Use generated Zod output for common object, enum, array, nullable, and required-field contracts.
  • Add hand-written refinements only when they are not represented in the OpenAPI schema.

Nullable and optional fields

OpenAPI nullable and optional fields need careful review because `nullable` means a value may be `null`, while optional means the property may be omitted. Generated Zod should preserve that distinction.

const ProfileSchema = z.object({
  website: z.string().url().nullable(),
  timezone: z.string().optional(),
});

When not to use this workflow

If the tRPC app owns every contract and no external system needs OpenAPI, a code-first Zod schema may be simpler. Use OpenAPI-to-Zod when the OpenAPI document is genuinely part of the product workflow.

  • Avoid converting just to add process around a purely internal router.
  • Avoid two-way syncing OpenAPI and Zod manually.
  • Prefer one contract owner and generated consumers.

Production checklist

Before relying on OpenAPI-to-Zod in a tRPC-style app, add fixtures for the generated schemas and keep the conversion step visible in PR review.

  • Pin the OpenAPI document version used to generate validators.
  • Test valid, invalid, nullable, optional, and enum payloads.
  • Document whether OpenAPI or TypeScript owns the source of truth.
  • Regenerate validators when the upstream contract changes.

Use FrameworkKit to generate the starter code, then review the output before shipping it in production.

Generate with OpenAPI to Zod

OpenAPI to Zod resources

FAQ

Can tRPC use OpenAPI schemas?

Yes, when an OpenAPI contract already exists. Use generated Zod schemas at procedure boundaries or REST adapter boundaries rather than making tRPC and OpenAPI compete as sources of truth.

Should tRPC be code-first or contract-first?

tRPC is naturally code-first. Contract-first OpenAPI is useful when external APIs, partners, or another team already own the schema.

Where should generated Zod schemas live?

Keep generated schemas close to the API client or procedure adapter that consumes the OpenAPI contract, and avoid hand-editing generated files without a clear regeneration path.

Does OpenAPI to Zod replace tRPC input schemas?

No. It can provide input or response schemas when OpenAPI owns the contract, but tRPC procedures can still use hand-written Zod schemas for app-owned inputs.

Related comparisons

Related tools