Skip to main content

Command Palette

Search for a command to run...

REST APIs: Concepts, Methods & URL Anatomy (with NestJS examples)

Published
4 min read
M

As a former 3D Animator with more than 12 years of experience, I have always been fascinated by the intersection of technology and creativity. That's why I recently shifted my career towards MERN stack development and software engineering, where I have been serving since 2021.

With my background in 3D animation, I bring a unique perspective to software development, combining creativity and technical expertise to build innovative and visually engaging applications. I have a passion for learning and staying up-to-date with the latest technologies and best practices, and I enjoy collaborating with cross-functional teams to solve complex problems and create seamless user experiences.

In my current role as a MERN stack developer, I have been responsible for developing and implementing web applications using MongoDB, Express, React, and Node.js. I have also gained experience in Agile development methodologies, version control with Git, and cloud-based deployment using platforms like Heroku and AWS.

I am committed to delivering high-quality work that meets the needs of both clients and end-users, and I am always seeking new challenges and opportunities to grow both personally and professionally.

What is a REST API (in plain words)?

A REST API is an HTTP-based interface that follows the Representational State Transfer principles. If your API follows these principles, we call it “RESTful.”

At a high level: a client (browser, mobile app, another server) sends an HTTP request to a server, and the server returns an HTTP response. NestJS helps you build the server side cleanly.


The 6 REST principles (we’ll use 5 of them a lot)

  1. Client–Server: UI (client) and data/services (server) are separate. Clients consume endpoints; server doesn’t care who the client is.

  2. Stateless: Every request carries all info the server needs (e.g., an Authorization: Bearer <token> header). The server doesn’t keep a per-user session.

  3. Cacheable: Responses may be cached by clients or servers (independently) to improve speed and scalability.

  4. Uniform Interface: Consistent resource‑oriented URLs and standard methods (GET/POST/PUT/PATCH/DELETE). Same request → same shape of response, regardless of who sends it.

  5. Layered System: Requests often pass through layers (load balancer, cache, app servers, DB). Neither client nor server needs to know the intermediaries.

  6. Code on Demand (optional): Server can send executable code to clients. Rarely used in typical JSON APIs and not needed for this course.


HTTP methods you’ll use (cheat sheet)

MethodTypical UseBlog exampleIdempotent?
GETRead/fetch dataGET /posts, GET /posts/:id✅ Yes
POSTCreate a resourcePOST /posts❌ No
PUTReplace an entire resourcePUT /posts/:id (send full post)✅ Yes
PATCHUpdate part of a resourcePATCH /posts/:id (send only changed fields)Usually not
DELETERemove a resourceDELETE /posts/:id✅ Yes

Quick tip: If you’re updating everything, use PUT. If you’re updating just a few fields, use PATCH.


The anatomy of an API request

Example:

GET https://api.example.com/posts/author/42?limit=10&offset=20
  • Method: GET

  • Domain: https://api.example.com

  • Route (path): /posts/author/42

  • Params: author = 42 (often expressed as :author in route templates)

  • Query string: ?limit=10&offset=20 (extra filters/pagination)

  • Headers (not shown): e.g., Authorization: Bearer <token>

  • Body: Only for methods like POST/PUT/PATCH (usually JSON)

Example request bodies (JSON)

Create a post

{
  "title": "Why NestJS Rocks",
  "description": "A quick tour of modules and decorators",
  "modifiedAt": "2025-09-03T09:00:00.000Z",
  "authorId": 42
}

Partial update (PATCH)

{
  "title": "Why NestJS Still Rocks"
}

How this maps to NestJS (controllers)

// posts.controller.ts
import { Controller, Get, Param, Query, Post, Body, Put, Patch, Delete } from '@nestjs/common';

@Controller('posts')
export class PostsController {
  @Get()
  findAll(@Query('limit') limit?: number, @Query('offset') offset?: number) {
    return { message: 'List posts', limit, offset };
  }

  @Get('author/:authorId')
  findByAuthor(@Param('authorId') authorId: string) {
    return { message: 'Posts by author', authorId };
  }

  @Post()
  create(@Body() dto: any) {
    return { message: 'Create post', dto };
  }

  @Put(':id')
  replace(@Param('id') id: string, @Body() dto: any) {
    return { message: 'Replace post', id, dto };
  }

  @Patch(':id')
  update(@Param('id') id: string, @Body() dto: any) {
    return { message: 'Update post', id, dto };
  }

  @Delete(':id')
  remove(@Param('id') id: string) {
    return { message: 'Delete post', id };
  }
}

Key decorators

  • @Controller('posts') → base route /posts

  • @Get(), @Post(), @Put(), @Patch(), @Delete() → methods

  • @Param('id') → route params like :id

  • @Query('limit') → query string values

  • @Body() → JSON payload for create/update

We’ll later add DTOs and validation pipes to make inputs type‑safe and clean.


Testing your API during development

You don’t need a frontend to test. Use any of these:

  • Postman — GUI client for sending requests

  • httpyac (VS Code extension) — lets you save .http files inside your repo

  • curl — simple command‑line tool

Example .http (httpyac/REST Client)

### List posts (first page)
GET http://localhost:3000/posts?limit=10&offset=0

### Posts by author
GET http://localhost:3000/posts/author/42

### Create post
POST http://localhost:3000/posts
Content-Type: application/json
Authorization: Bearer {{token}}

{
  "title": "My first NestJS post",
  "description": "Hello, world!",
  "authorId": 42
}

Params vs Query (mental model)

  • Params (part of the path) = category or identity

    • /posts/:id → one specific post

    • /posts/author/:authorId → posts by an author

  • Query (after ?) = filters/sorting/pagination

    • ?limit=10&offset=20

    • ?sort=createdAt&order=desc


Common pitfalls

  • Mixing up PUT and PATCH (replace vs partial update)

  • Hiding state on the server (REST should be stateless — pass tokens on each request)

  • Inconsistent routes (stick to nouns and plural resources, e.g., /posts, /users)

  • Returning different shapes for the same endpoint (breaks uniform interface)


Practice (do this now)

  1. Create a PostsController with the handlers shown above and return simple JSON.

  2. Hit the endpoints with Postman or an .http file. Play with :authorId, limit, offset.

  3. Add a POST /posts that accepts the JSON body and echoes it back.

  4. Try PUT vs PATCH on the same :id and note the semantic difference.