Skip to main content

Body Validation

Validate request body (e.g. for POST/PUT) by defining a body schema for the method in your route's schema.ts. Validated body is on ctx.validated.body.

Example: export const POST = { body: z.object({ name: z.string().min(1), price: z.number().positive() }) }. When a body schema is declared, the body must be JSON (application/json or application/*+json); any other content type is rejected with 415 Unsupported Media Type. A request with no Content-Type must have an empty body: an empty body validates as undefined (so optional body schemas still work), and a non-empty body is rejected with 422. Malformed JSON is a 400. Unvalidated data never reaches the handler. When a declared body schema is present, ctx.validated.body is non-optional in the type: ctx.validated.body.name compiles without ?.. See Validation and Schema Definition.

Types for this feature​

The body schema types ctx.validated.body.

The types you use (from burger-api):

  • defineRoute(schema, handler): infers the handler type from schema; no generic to write
  • BurgerContext<typeof POST>: the same inference, written by hand
  • ctx.validated.body: the validated body, typed field by field

✅ Correct: validated body is typed from the schema:

api/products/schema.ts
import { z } from "zod";
export const POST = { body: z.object({ name: z.string().min(1), price: z.number().positive() }) };
api/products/route.ts
import { defineRoute } from "burger-api";
import { POST as PostSchema } from "./schema";

export const POST = defineRoute(PostSchema, (ctx) => {
const { name, price } = ctx.validated.body; // both typed
return Response.json({ name, price }, { status: 201 });
});

❌ Wrong: a body field that is not in the schema:

export const POST = defineRoute(PostSchema, (ctx) => {
ctx.validated.body.missing; // ❌ Property 'missing' does not exist
});

For an unannoted handler, ctx.validated is possibly undefined and its fields are untyped. Add the schema and wrap the handler with defineRoute (or annotate it by hand). See the TypeScript overview.

Check your code: bun run typecheck.