# REST API Design Made Simple with Express.js

## What Is an API?

API stands for Application Programming Interface. Ignore the formal definition for a moment and think about what's actually happening.

You have a client a browser, a mobile app, a CLI tool, another server and you have a server that knows things or can do things the client needs. The API is the agreed upon language they use to talk.

When a user logs into an app, the frontend doesn't just magically know their data.

It sends a request to the server:  
*"Hey, here's a username and password — does this check out? If so, give me this user's profile."*

The server checks, and responds:  
*"Yes, here it is."*

That exchange, the format of the request, the format of the response is the API.

REST is a specific way of designing that exchange. It uses HTTP (the same protocol your browser uses to load web pages) and a set of conventions that make APIs predictable and consistent.

## The Core Idea

REST stands for Representational State Transfer. The jargon doesn't help much. What *does* help is understanding the concept of a **resource**.

In REST, everything you expose through your API is a *resource* — a noun, a thing. Users are a resource. Posts are a resource. Orders, products, comments — all resources.

Each resource has a URL that identifies it. That URL is called an **endpoint**. The naming convention is clean: always use plural nouns, always lowercase, no verbs.

```plaintext
Good:
  /users
  /users/42
  /posts
  /posts/7/comments

Bad:
  /getUsers
  /deleteUser?id=42
  /createNewPost
```

The bad examples describe *actions*, not resources. The action is communicated via the HTTP method, not the URL. The URL should only tell you *what* you're operating on the HTTP method tells you *how*.

## HTTP Methods: The Verbs of REST

HTTP ships with a set of methods sometimes called verbs that describe the intended operation on a resource. REST maps these directly to the four classic database operations known as CRUD: Create, Read, Update, Delete.

**GET** — Retrieve a resource. Read-only. Should never modify anything. Safe to call multiple times.

**POST** — Create a new resource. Sends data in the request body. Used when the server generates the ID.

**PUT** — Replace an existing resource entirely. You send the full updated version, the server stores it as-is.

**DELETE** — Remove a resource.

There's also **PATCH**, which is worth knowing even though it's less universal: it partially updates a resource. Where `PUT` replaces everything, `PATCH` just changes the fields you send. For a user profile, `PUT` would require sending name + email + age + every other field even if you're only changing the email. `PATCH` lets you send just `{ "email": "`[`new@email.com`](mailto:new@email.com)`" }`.

![](https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/e884c1ec-8734-4245-bf68-0fb252c54183.png align="center")

## Status Codes: The Server's Reply

When your server responds, it includes a status code a three-digit number that tells the client whether things went well, and if not, why not. Most developers know 404. There are many more.

The codes are grouped by their first digit:

**2xx — Success**

*   `200 OK` — generic success. Used for successful GET, PUT, PATCH responses.
    
*   `201 Created` — resource was successfully created (POST responses).
    
*   `204 No Content` — success, but nothing to return (DELETE responses).
    

**4xx — Client errors** (the request was wrong)

*   `400 Bad Request` — the client sent malformed data.
    
*   `401 Unauthorized` — no authentication was provided.
    
*   `403 Forbidden` — authenticated but not allowed.
    
*   `404 Not Found` — the resource doesn't exist.
    
*   `409 Conflict` — the request conflicts with current state (e.g. duplicate email).
    
*   `422 Unprocessable Entity` — data was well-formed but failed validation.
    

**5xx — Server errors** (something broke on your end)

*   `500 Internal Server Error` — generic catch-all server failure.
    
*   `503 Service Unavailable` — server is down or overloaded.
    

`401` vs `403` is a distinction almost every junior API makes incorrectly. `401` means "who are you? I don't know you." `403` means "I know who you are, but you can't do this." If a user is logged in and tries to access another user's private data, that's a `403`, not a `401`. If there's no token at all, it's a `401`.

Also: `404` vs `403` for private resources is a deliberate security decision. If a user asks for `/users/99` and that user exists but belongs to someone else, should you return `404` (pretend it doesn't exist) or `403` (admit it exists but deny access)? Returning `404` is often the more secure choice it doesn't reveal which IDs exist.

## Designing the Users Resource

Let's build a complete CRUD API for a `users` resource. In a real app you'd use a database here we'll use an in-memory array to keep the focus on the API design.

GET /users — List all users

GET /users/:id — Get one user

POST /users — Create a new user

PUT /users/:id — Replace a user

DELETE /users/:id — Remove a user

## Route Naming: The Conventions That Actually Matter

These conventions aren't enforced by any framework. They're just what every experienced developer expects, which is exactly why they matter:

**Use nouns, not verbs in URLs.**

*   `/users` not `/getUsers`, `/createUser`, `/deleteUser`
    

**Use plural nouns for collections.**

*   `/users` not `/user`
    
*   `/posts` not `/post`
    

**Use URL parameters for specific resources.**

*   `/users/42` not `/users?id=42`
    

**Use query strings for filtering, sorting, pagination.**

*   `/users?role=admin` — filter by role
    
*   `/users?sort=created_at&order=desc` — sorted list
    
*   `/users?page=2&limit=20` — pagination
    

**Nested resources for relationships.**

*   `/users/42/posts` — all posts by user 42
    
*   `/users/42/posts/7` — a specific post by user 42
    

**What most developers don't think about:** versioning. When your API is public or consumed by mobile apps you don't control, you'll eventually need to change it in a breaking way. The standard solution is URL versioning: `/api/v1/users`, `/api/v2/users`. It's something you should add from the start, not retrofit later.

## Error Consistency:

One thing that separates a professional API from a tutorial API: consistent error responses. Your errors should all look the same.

![](https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/423ba235-a707-413d-9fa7-0fed05cbf944.png align="center")

REST API design is largely a discipline of making decisions *before* you start coding and sticking to them. The decisions aren't hard: plural nouns, HTTP methods as verbs, correct status codes, consistent error shapes. None of these require advanced knowledge they just require intention.

Express.js gives you the minimum to implement all of this. No magic, no opinions just a router, middleware support, and `req`/`res`. The REST conventions layer on top cleanly.

Master one resource, get all the conventions right, and every other resource you add will look exactly the same. That's the whole point of REST: uniformity. Once a developer learns how one endpoint works, they understand how all of them work.

I’m currently deep-diving into the **JavaScript**, building projects and exploring the internals of the web. If you're on a similar journey or just love talking about JavaScript, let’s stay in touch!

*   **Connect on LinkedIn:** [**Satpalsinh's Profile**](https://www.linkedin.com/in/satpalsinhrana)
    
*   **Follow my Blog:** [**blogs.satpal.cloud**](http://blogs.satpal.cloud)
    

**Keep coding and keep building.**
