Building a REST API (CRUD)
Put it together into a real API with Create, Read, Update and Delete — the core of every back-end.
What you will learn
- Understand REST and CRUD
- Build all four CRUD endpoints
- Return correct data and status codes
REST = HTTP methods as actions
Almost everything an app does to data is one of four actions: Create, Read, Update, Delete — together called CRUD. A REST API is simply a tidy convention for exposing those four actions over HTTP, by matching each one to an HTTP method:
| Action | HTTP method | Example route |
|---|---|---|
| Create | POST | POST /tasks |
| Read | GET | GET /tasks and GET /tasks/:id |
| Update | PUT | PUT /tasks/:id |
| Delete | DELETE | DELETE /tasks/:id |
Think of the whole API as managing one list of tasks. Each endpoint handles one step of the CRUD cycle:
- Read all —
GET /tasksreturns the whole list. - Read one —
GET /tasks/:idfinds a single task by its id (or replies 404 if there is none). - Create —
POST /taskstakes new data from the body, adds it to the list, and replies 201. - Delete —
DELETE /tasks/:idremoves the matching task from the list.
const express = require("express");
const app = express();
app.use(express.json());
let tasks = [{ id: 1, text: "Learn Express" }];
// READ all
app.get("/tasks", (req, res) => res.json(tasks));
// READ one
app.get("/tasks/:id", (req, res) => {
const task = tasks.find(t => t.id === Number(req.params.id));
if (!task) return res.status(404).json({ error: "Not found" });
res.json(task);
});
// CREATE
app.post("/tasks", (req, res) => {
const task = { id: Date.now(), text: req.body.text };
tasks.push(task);
res.status(201).json(task);
});
// DELETE
app.delete("/tasks/:id", (req, res) => {
tasks = tasks.filter(t => t.id !== Number(req.params.id));
res.json({ message: "Deleted" });
});
app.listen(3000, () => console.log("API on http://localhost:3000"));How each route works: READ all simply sends the whole tasks array as JSON. READ one uses tasks.find(...) to locate the task whose id matches the URL — note Number(req.params.id) converts the text id from the URL into a number so the comparison works; if nothing is found it returns status 404 (Not Found) and stops with return. CREATE builds a new task object (using Date.now() as a quick unique id and req.body.text from the posted JSON), pushes it onto the array, and returns 201 (Created). DELETE uses tasks.filter(...) to keep every task except the one with the matching id.
Note: Output (GET /tasks right after starting):
[{"id":1,"text":"Learn Express"}]
Output (POST /tasks with body {"text":"Build an API"}):
{"id":1717750000000,"text":"Build an API"}
Output (GET /tasks/999 when no such id exists):
{"error":"Not found"}
The new task’s id is whatever Date.now() returned (the current time in milliseconds), so yours will differ. After the POST, a fresh GET /tasks would show both tasks.
Note: Here tasks is just an array — a temporary “database”. In the MongoDB unit you will swap it for a real database so the data persists. The route structure stays the same.
Tip: Use status codes correctly: 200 OK, 201 Created, 404 Not Found, 400 Bad Request, 500 Server Error. They tell the front-end exactly what happened.
Q. In a REST API, which HTTP method creates a new resource?
✍️ Practice
- Build a CRUD API for “tasks” with GET (all + one), POST and DELETE.
- Test each endpoint with your browser or a tool like Postman / Thunder Client.
🏠 Homework
- Add a PUT route to update a task’s text, returning 404 if the id is not found.