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 Method | Route | Action |
|---|---|---|
| GET | /todos | List all to-dos |
| POST | /todos | Create a new to-do |
| PUT | /todos/:id | Update a to-do |
| DELETE | /todos/:id | Delete 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.