Course:Node.js & Express/
Lesson

You ask AI to build a user management APIWhat is api?A set of rules that lets one program talk to another, usually over the internet, by sending requests and getting responses.. It generates POST /createUser, GET /getUserById, POST /deleteUser, and GET /getAllUsers. These routes work, but they violate every RESTWhat is rest?An architectural style for web APIs where URLs represent resources (nouns) and HTTP methods (GET, POST, PUT, DELETE) represent actions on those resources. convention. Any developer consuming your API will be confused, and every new feature you add makes the naming inconsistency worse.

Resources, not actions

RESTWhat is rest?An architectural style for web APIs where URLs represent resources (nouns) and HTTP methods (GET, POST, PUT, DELETE) represent actions on those resources. APIs are organized around resources, the things your APIWhat is api?A set of rules that lets one program talk to another, usually over the internet, by sending requests and getting responses. manages. Users, books, orders, comments. The URL identifies the resource. The HTTPWhat is http?The protocol browsers and servers use to exchange web pages, API data, and other resources, defining how requests and responses are formatted. verb says what you want to do with it.

# Wrong - verbs in URLs
POST /createUser
GET  /getUserById/42
POST /updateUser/42
POST /deleteUser/42

# Right - nouns in URLs, verbs are HTTP methods
POST   /users        (create)
GET    /users/42     (read)
PUT    /users/42     (update)
DELETE /users/42     (delete)
HTTP verbURLActionSQL equivalent
GET/usersList all usersSELECT * FROM users
GET/users/42Get one userSELECT * FROM users WHERE id = 42
POST/usersCreate a userINSERT INTO users ...
PUT/users/42Replace a userUPDATE users SET ... WHERE id = 42
PATCH/users/42Partially updateUPDATE users SET name = ... WHERE id = 42
DELETE/users/42Delete a userDELETE FROM users WHERE id = 42
AI pitfall
AI puts verbs in URLs because the prompt usually says "create an endpoint to delete a user." The AI translates the instruction literally: POST /deleteUser. You need to translate "delete a user" into DELETE /users/:id yourself, or tell the AI explicitly to follow REST conventions.
02

Plural nouns

Resource names should always be plural, even when you are accessing a single item.

# Consistent and correct
GET /users       → list of users
GET /users/42    → one user (still /users, not /user)

# Inconsistent and confusing
GET /user        → list of users? one user? unclear
GET /user/42     → works, but now you have two conventions

The rule is simple: the resource is always plural. /users/42 means "user 42 from the collection of users."

PatternExampleVerdict
Plural nouns/products, /orders, /reviewsCorrect
Singular nouns/product, /order, /reviewAvoid
Verbs in URL/getProducts, /createOrderWrong
Mixed casing/userProfiles, /OrderItemsUse kebab-case instead
Kebab-case/user-profiles, /order-itemsCorrect for multi-word resources
03

Nested routes for relationships

When resources belong to other resources, nest them in the URL to express the relationship.

// Orders belonging to a specific user
app.get('/users/:userId/orders', (req, res) => {
  const orders = db.findOrders({ userId: req.params.userId });
  res.json(orders);
});

// A specific order belonging to a specific user
app.get('/users/:userId/orders/:orderId', (req, res) => {
  const order = db.findOrder(req.params.orderId);
  if (order.userId !== req.params.userId) {
    return res.status(404).json({ error: 'Order not found' });
  }
  res.json(order);
});

// Comments on a specific post
app.get('/posts/:postId/comments', (req, res) => {
  const comments = db.findComments({ postId: req.params.postId });
  res.json(comments);
});

Nesting should go at most two levels deep. Beyond that, the URLs become unwieldy and hard to understand.

# Good - two levels
/users/42/orders
/posts/7/comments

# Too deep - flatten instead
/users/42/orders/7/items/3/reviews     # too nested
/order-items/3/reviews                  # better: promote to top-level

When to nest vs. flatten

RelationshipNested URLFlat URLRecommendation
Orders for a user/users/:id/orders/orders?userId=42Nest, strong ownership
Comments on a post/posts/:id/comments/comments?postId=7Either works
Reviews of an item/items/:id/reviews/reviews?itemId=3Either works
User profile picture/users/:id/avatar/avatars/:userIdNest, 1:1 relationship

If the child resource makes sense on its own (you often query reviews across all items), use a flat route with query filters. If the child only exists in context of the parent (a user's avatar), nest it.

04

PaginationWhat is pagination?Splitting a large set of results into smaller pages so the server and client only handle a manageable chunk at a time., filtering, and sorting

Never create separate endpoints for filtered views. Use query parameters on the collection endpointWhat is endpoint?A specific URL path on a server that handles a particular type of request, like GET /api/users..

# Pagination
GET /products?page=2&limit=20

# Filtering
GET /products?category=electronics&inStock=true

# Sorting
GET /products?sort=price&order=asc

# Combined
GET /products?category=electronics&sort=price&order=desc&page=1&limit=10

Implementing pagination

app.get('/products', (req, res) => {
  const page = parseInt(req.query.page) || 1;
  const limit = Math.min(parseInt(req.query.limit) || 20, 100); // Cap at 100
  const offset = (page - 1) * limit;

  const products = db.findProducts({ offset, limit });
  const total = db.countProducts();

  res.json({
    data: products,
    pagination: {
      page,
      limit,
      total,
      totalPages: Math.ceil(total / limit)
    }
  });
});
AI pitfall
AI-generated pagination often has no upper limit on limit. A client can request ?limit=1000000 and your server tries to load a million records into memory. Always cap the limit.

Pagination response shape

Your paginated responses should include enough metadata for the client to build pagination controls.

FieldPurposeExample
dataThe array of items for this page[{...}, {...}]
pagination.pageCurrent page number2
pagination.limitItems per page20
pagination.totalTotal items across all pages157
pagination.totalPagesTotal number of pages8
05

APIWhat is api?A set of rules that lets one program talk to another, usually over the internet, by sending requests and getting responses. versioning

When you change your API in ways that break existing clients, you need versioning. The most common approach is a URL prefix.

# Version in the URL
GET /v1/users
GET /v2/users     (new response format)

# In Express
const v1Router = require('./routes/v1');
const v2Router = require('./routes/v2');

app.use('/v1', v1Router);
app.use('/v2', v2Router);
StrategyExampleProsCons
URL prefix/v1/usersSimple, obvious, easy to routeDuplicates route definitions
HeaderAccept: application/vnd.api.v2+jsonClean URLsHarder to test, easy to forget
Query param/users?version=2Easy to addMuddies the query string

URL prefix versioning is the most common and the easiest to implement. Use it unless you have a specific reason not to.

06

Consistent error responses

Every error your APIWhat is api?A set of rules that lets one program talk to another, usually over the internet, by sending requests and getting responses. returns should follow the same shape. Clients should not have to guess the format.

// Consistent error format
function sendError(res, status, message, details = null) {
  const response = { error: { status, message } };
  if (details) response.error.details = details;
  return res.status(status).json(response);
}

// Usage
app.post('/users', (req, res) => {
  const { name, email } = req.body;

  if (!name) return sendError(res, 400, 'Name is required');
  if (!email) return sendError(res, 400, 'Email is required');

  if (db.userExists(email)) {
    return sendError(res, 409, 'Email already registered');
  }

  const user = db.createUser({ name, email });
  res.status(201).json(user);
});
AI pitfall
AI generates different error shapes for different routes. One returns { error: "message" }, another returns { message: "error" }, and a third returns { success: false, msg: "..." }. Clients cannot reliably parse these. Define one error format and use it everywhere.
07

A complete RESTWhat is rest?An architectural style for web APIs where URLs represent resources (nouns) and HTTP methods (GET, POST, PUT, DELETE) represent actions on those resources. APIWhat is api?A set of rules that lets one program talk to another, usually over the internet, by sending requests and getting responses. design checklist

When you review AI-generated API code, check each of these.

RuleBad exampleGood example
Use plural nouns/user, /getProduct/users, /products
Verbs are HTTP methodsPOST /deleteUser/42DELETE /users/42
Status codes match outcome200 for "not found"404 for "not found"
Consistent error format{ msg: "..." } in one place, { error: "..." } in another{ error: { status, message } } everywhere
Pagination has a max limit?limit=999999 acceptedCapped at 100
Nested max 2 levels/a/:id/b/:id/c/:id/d/a/:id/b and /c/:id/d
Kebab-case URLs/userProfiles/user-profiles
Created resources return 201POST /users returns 200POST /users returns 201