Body Schemas

Validate POST/PUT/PATCH Bodies

Body Schemas

schema.body validates the request JSON body — required fields, types, formats, and nested shapes — before your handler runs.

4 min read Level 2/5 #fastify#schemas#body
What you'll learn
  • Declare body as a JSON Schema object
  • Mark required fields
  • Use formats like email, uri, and uuid

schema.body is the most-used schema slot. Fastify hands the raw JSON body to Ajv, validates it against your schema, and rejects bad requests with 400.

A Realistic Signup Body

app.post('/signup', {
  schema: {
    body: {
      type: 'object',
      required: ['email', 'password'],
      additionalProperties: false,
      properties: {
        email: { type: 'string', format: 'email' },
        password: { type: 'string', minLength: 8, maxLength: 128 },
        name: { type: 'string', minLength: 1, maxLength: 80 },
        marketingOptIn: { type: 'boolean', default: false },
      },
    },
  },
  handler: async (req) => createUser(req.body),
});

additionalProperties: false rejects requests that include unknown fields — useful for catching typos and stopping mass-assignment bugs.

Nested Objects and Arrays

const body = {
  type: 'object',
  required: ['address'],
  properties: {
    address: {
      type: 'object',
      required: ['street', 'city'],
      properties: {
        street: { type: 'string' },
        city: { type: 'string' },
        country: { type: 'string', enum: ['US', 'IN', 'DE'] },
      },
    },
    tags: {
      type: 'array',
      items: { type: 'string' },
      maxItems: 10,
      uniqueItems: true,
    },
  },
} as const;

Formats

Out of the box Ajv supports a few formats. Register ajv-formats to get email, uri, uuid, date-time, and more — covered in the Tuning Ajv lesson.

If validation fails, the response body looks like { "statusCode": 400, "error": "Bad Request", "message": "body must have required property 'email'" }.

Params Schemas →