What You'll Build

In this tutorial, you'll create a simple but complete REST API for managing a to-do list. By the end, you'll understand how HTTP methods map to CRUD operations, how to structure an Express app, and how to handle errors gracefully.

Prerequisites

  • Node.js (v18 or later) installed on your machine
  • Basic familiarity with JavaScript
  • A terminal and a code editor (VS Code recommended)
  • Postman or a similar tool for testing API endpoints

Step 1: Initialize Your Project

Create a new directory and initialize a Node.js project:

mkdir todo-api
cd todo-api
npm init -y
npm install express

This sets up a basic package.json and installs Express as your only dependency for now.

Step 2: Create the Express Server

Create a file called index.js and add the following:

const express = require('express');
const app = express();
app.use(express.json());

const PORT = 3000;
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));

The express.json() middleware is critical — it parses incoming JSON request bodies so you can read req.body in your route handlers.

Step 3: Define Your Routes

REST APIs map HTTP verbs to actions. Here's the pattern you'll follow:

HTTP MethodRouteAction
GET/todosList all to-dos
POST/todosCreate a new to-do
PUT/todos/:idUpdate a to-do
DELETE/todos/:idDelete a to-do

Step 4: Implement the Handlers

Add an in-memory store and your route handlers:

let todos = [];
let nextId = 1;

app.get('/todos', (req, res) => res.json(todos));

app.post('/todos', (req, res) => {
  const todo = { id: nextId++, text: req.body.text, done: false };
  todos.push(todo);
  res.status(201).json(todo);
});

app.put('/todos/:id', (req, res) => {
  const todo = todos.find(t => t.id === +req.params.id);
  if (!todo) return res.status(404).json({ error: 'Not found' });
  todo.text = req.body.text ?? todo.text;
  todo.done = req.body.done ?? todo.done;
  res.json(todo);
});

app.delete('/todos/:id', (req, res) => {
  todos = todos.filter(t => t.id !== +req.params.id);
  res.status(204).send();
});

Step 5: Test Your API

Run your server with node index.js and use Postman to fire requests at http://localhost:3000/todos. Try creating a few to-dos, updating them, and deleting them to confirm everything works.

Next Steps

This tutorial used in-memory storage, which resets when the server restarts. To make it production-ready, consider:

  • Connecting to a real database like MongoDB or PostgreSQL
  • Adding input validation with a library like Zod or Joi
  • Implementing authentication with JWT
  • Writing automated tests with Jest and Supertest

Once you're comfortable with the basics, you'll find that every REST API you build follows this same structural pattern — just with more complexity layered on top.