REST API Design Made Simple with Express.js
So after understanding how Node.js handles async stuff and the event loop, the next big thing which I had to figure out was - how do you actually build API with it ?
I have heard this word "REST API" around myself constantly in tutorials, job postings, project requirements almost everywhere and everyone assumes that you should know what it means. So let me explain this topic in the easy way that I had to figure it out.
What is a REST API?
API stands for Application Programming Interface. it is just a Fancy name, in simpler way it's just a way for two systems to talk to each other. it acts like a communication channel between two systems.
Your frontend needs data ? frontend asks the backend through an API. A mobile app needs to log a user in its application ? It talks to a server through an API. Even different backend services talk to each other through APIs.
REST is defined by set of rules for how that conversation should be structured. just think about it like grammar. technically if we think you can communicate without grammar in short run, but in long run it gets messy fastly. REST keeps things in a very organized and in a predictable manner. When people talks about "REST API" they just mean an API that follows REST rules.
What is a Resource ?
In REST, everything revolves around resources only
A resource is just a thing from which your API can easily deals with it. Users, Posts, Products, Orders each one of these behave like a resource, and your API gives people a way to interact with them.
The key idea is that your URL should represent the resource, not show the action.
Bad way :
/getUsers
/createUser
/deleteUser
Good way :
/users
/users/:id
Same resource, same way for URL. The action is determined by the HTTP method you use not by the URL.
HTTP Methods
If I say resources behaves as the nouns, then HTTP methods behaves like verbs. They tell us about the server that what you want to do with a resource.
There are four mainMethods that you'll use constantly while building REST APIs :
GET - This method is used for read something, to fetch a list of users, to fetch one user, or we can say fetch anything. No data is changed with it.
POST - This method is used for creating something new like POST Method is used in sending user data to create a new account. Body of the request that contains the new data.
PUT - This method is used for updating something that already exists, PUT method only sends updated info for a specific user.
DELETE - This method is used for removing something. Delete a user by their ID.
Status Codes
When your server replies, it doesn't just send back data. It also sends a status code a numberic data that informs the client what happened with the request by giving status code with response. You don't need to memorize all of them. Just have a knowldege of the common ones :
| Code | Meaning |
|---|---|
| 200 | OK request worked |
| 201 | Created new resource was made |
| 400 | Bad Request something wrong with what you sent |
| 401 | Unauthorized not logged in |
| 403 | Forbidden logged in but not allowed |
| 404 | Not Found resource doesn't exist |
| 500 | Internal Server Error something broke on the server |
These codes really matter because the client uses them to figure out what has been happened with the server when the certain data has been requested from server.
200 status code means "all good, here's your data."
404 means "that thing you're looking for doesn't exist."
500 means your server is messed up.
Building REST Routes for a users Resource
Let's use a users resource and try to build it out properly in Express.
First, basic Express setup:
const express = require("express");
const app = express();
app.use(express.json());
app.listen(3000, () => {
console.log("Server running on port 3000");
});
Now take a view of the routes:
GET /users - fetch all users
app.get("/users", (req, res) => {
const users = [
{ id: 1, name: "Ankur" },
{ id: 2, name: "Rahul" }
]
res.status(200).json(users)
})
GET /users/:id - fetch one user
app.get("/users/:id", (req, res) => {
const { id } = req.params;
const user = { id: id, name: "Ankur" };
if (!user) {
return res.status(404).json({ message: "User not found" });
}
res.status(200).json(user);
});
POST /users - create a new user
app.post("/users", (req, res) => {
const { name, email } = req.body;
const newUser = { id: 3, name, email };
res.status(201).json(newUser);
});
Notice it's 201 here, not 200. Because we're not just trying to fetch, we are trying to creating something which is new for us.
PUT /users/:id - update a user
app.put("/users/:id", (req, res) => {
const { id } = req.params;
const { name, email } = req.body;
const updatedUser = { id, name, email };
res.status(200).json(updatedUser);
});
DELETE /users/:id - delete a user
app.delete("/users/:id", (req, res) => {
const { id } = req.params;
res.status(200).json({ message: `User ${id} deleted` });
});
How It All Maps Together
Here's the full picture for the users resource in one clean table:
| Method | Route | What it does | Status Code |
|---|---|---|---|
| GET | /users | Get all users | 200 |
| GET | /users/:id | Get one user | 200 / 404 |
| POST | /users | Create a user | 201 |
| PUT | /users/:id | Update a user | 200 |
| DELETE | /users/:id | Delete a user | 200 |
This is REST , Same base URL /users, different methods for different actions which are clean, predictable, and something that any other developer can look at and immediately understand it.




