REST API for Todo App
Part of the Backend Developer Roadmap
In short
The todo API is the 'hello world' of backends for a reason: it uses every CRUD operation. Build it properly once and you'll reuse the pattern in every project.
A full CRUD API for managing todos — the classic first Express project, exercising routing, validation, and connecting to a real database.

Think of it like this
The sticky-note board
On your hostel wall, you stick notes, read them, tick some off, and peel others away. Create, read, update, delete. Your todo API does exactly this, except the board is a database and the notes are JSON.
Watch it happen
CRUD in five requests
POST /todos
1/6Body { "title": "Submit DBMS assignment" }. The API validates it.
The big ideas
What you need to know
Five endpoints
GET /todos, GET /todos/:id, POST /todos, PATCH /todos/:id, DELETE /todos/:id.
Correct status codes
201 on create, 204 on delete, 404 for a missing id, 400 for a bad body.
Validate every write
Title required and trimmed, sensible max length, done must be a boolean.
Filter the list
Support GET /todos?done=false so the app can show only pending tasks.
See it in code
Walk through the code
1const todos = new Map();2let nextId = 1;3app.patch("/todos/:id", (req, res) => {4 const todo = todos.get(Number(req.params.id));5 if (!todo) return res.status(404).json({ error: "Todo not found" });6 const { title, done } = req.body;7 if (title !== undefined && (typeof title !== "string" || !title.trim())) {8 return res.status(400).json({ error: "title must be a non-empty string" });9 }10 if (done !== undefined && typeof done !== "boolean") {11 return res.status(400).json({ error: "done must be true or false" });12 }13 if (title !== undefined) todo.title = title.trim();14 if (done !== undefined) todo.done = done;15 res.json(todo);16});1/4An in-memory Map is enough to start. Swap it for a database later.
PATCH is the trickiest route: every field is optional, but any field that is sent must still be valid.
Save yourself the pain
Common mistakes
Oops
Returning 200 with an empty body when a todo id doesn't exist.
Do this instead
Return 404 with a clear error. The client needs to tell 'gone' from 'success'.
Oops
Using PUT but only sending one field, wiping the rest.
Do this instead
Use PATCH for partial updates. PUT means 'replace the whole thing'.
Your mission
Milestone 1: working CRUD
Quick check
Which status code fits a successful DELETE /todos/1 that returns no body?
Go deeper
- 1Implement all 5 REST operations (list, get, create, update, delete) properly.
- 2Add request validation and consistent error responses.
- 3Connect it to a real database instead of an in-memory array.
More projects at this stop
Stuck on this topic? Ask an Insider
Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.