The Request Body

@Body Reads Parsed JSON From the Client

The Request Body

POST, PUT, and PATCH usually carry a JSON payload. `@Body` exposes it to your handler, typed if you want.

4 min read Level 2/5 #nestjs#routing#body
What you'll learn
  • Use `@Body()` to read the whole body
  • Use `@Body('field')` to read a single key
  • Use a DTO class to type the body

For write requests (POST, PUT, PATCH) the payload arrives as the HTTP body. Nest auto-parses JSON and hands it to your handler through the @Body() decorator.

Reading the Whole Body

import { Controller, Post, Body } from '@nestjs/common';

@Controller('users')
export class UsersController {
  @Post()
  create(@Body() body: { name: string; email: string }) {
    return this.users.create(body);
  }
}

Send JSON to POST /users and body is the parsed object. Nest configures the body parser for you with sensible defaults (1 MB JSON limit by default).

Picking a Single Field

If you only need one key, name it:

@Post('rename')
rename(@Body('name') name: string) {
  return this.users.rename(name);
}

Handy for tiny endpoints. For anything with multiple fields, prefer a DTO so validation and types are explicit.

Use a DTO for Typed, Validated Bodies

A DTO (Data Transfer Object) is a class that describes the shape of the input. Combined with class-validator decorators and a global ValidationPipe, you get runtime checks for free:

import { IsEmail, IsString, MinLength } from 'class-validator';

export class CreateUserDto {
  @IsString() @MinLength(2)
  name!: string;

  @IsEmail()
  email!: string;
}
@Post()
create(@Body() dto: CreateUserDto) {
  return this.users.create(dto);
}

Bad input (name too short, malformed email) gets a structured 400 response — your handler never runs.

Why Classes, Not Interfaces

TypeScript interfaces vanish at compile time, so Nest can’t see them at runtime. Classes survive, and that’s what class-validator reads. Always use a class for DTOs even though you’ll be tempted to use an interface.

Quick Test

curl -X POST http://localhost:3000/users \
  -H 'content-type: application/json' \
  -d '{"name":"Ada","email":"ada@example.com"}'

Returns the new user. Try sending an invalid email and you’ll see a 400 with the validation error message — courtesy of the ValidationPipe you turn on in main.ts.

Headers — Reading & Setting →