Route Parameters

Capture Path Segments With @Param

Route Parameters

Mark path segments with `:name` in the route, then read them with the `@Param` decorator.

4 min read Level 2/5 #nestjs#routing#params
What you'll learn
  • Define `:params` in route paths
  • Read one parameter or all parameters at once
  • Coerce string params to numbers with ParseIntPipe

Route parameters are the dynamic bits of a URL — the :id in /users/:id. Nest captures them and hands them to your handler via the @Param() decorator.

Reading a Single Param

import { Controller, Get, Param } from '@nestjs/common';

@Controller('users')
export class UsersController {
  @Get(':id')
  findOne(@Param('id') id: string) {
    return { id };
  }
}

@Param('id') says “give me the segment named id from the route.” A request to GET /users/42 produces id === '42'.

Reading All Params at Once

If you have multiple params and don’t want to declare each:

@Get(':orgId/users/:userId')
findOne(@Param() params: { orgId: string; userId: string }) {
  return params; // { orgId: '...', userId: '...' }
}

It’s a touch less explicit but handy when you’re passing the whole bag through to a service.

Params Are Strings — Always

URLs are text, so every param arrives as a string. If your service wants a number, coerce it. The idiomatic Nest way is a pipe:

import { Controller, Get, Param, ParseIntPipe } from '@nestjs/common';

@Controller('users')
export class UsersController {
  @Get(':id')
  findOne(@Param('id', ParseIntPipe) id: number) {
    return { id, type: typeof id }; // → { id: 42, type: 'number' }
  }
}

ParseIntPipe runs before the handler, parses the value, and rejects the request with a 400 if it isn’t a valid integer. There are siblings: ParseFloatPipe, ParseBoolPipe, ParseUUIDPipe, ParseEnumPipe.

Optional Params

Nest doesn’t support optional path params directly (a :id? syntax). The clean fix is two routes that share a handler, or split into a list and single-item endpoint:

@Get()           list()                                   {}  // /users
@Get(':id')      findOne(@Param('id') id: string)         {}  // /users/:id

That mirrors how REST is usually designed anyway: a collection endpoint plus an item endpoint.

A Real Handler

Putting it together:

@Get(':id')
findOne(@Param('id', ParseIntPipe) id: number) {
  const user = this.users.find(id);
  if (!user) throw new NotFoundException();
  return user;
}

That’s idiomatic Nest: typed param, validated, business call, throw a structured exception for the not-found case.

Query Parameters →