Backend Development
ConceptBeginner 18 min· Foundations · 3 of 20

Designing REST APIs

A well-designed API is easy to guess, easy to use and hard to misuse. Learn REST resource naming, how to map methods to actions, plus filtering, pagination, versioning and error format, using the Brew & Bean API.

An API (application programming interface) is the set of URLs your backend offers to other programs. REST is a popular style for designing them over HTTP. REST is a set of conventions, not a library: if you follow them, any developer can guess how your API works without reading a manual.

The core idea: your API is a collection of resources (things like menu items and orders). Each resource has a URL. You use standard HTTP methods to act on it. You have seen the methods and status codes in *HTTP in depth*; here we apply them.

Resources and URLs

A resource is a noun. The URL names the noun; the method is the verb. So we do not write /getMenu or /createOrder. We write GET /menu and POST /orders.

Naming rules

RuleGoodAvoid
Use nouns, not verbs/orders/getOrders, /createOrder
Use plural collections/orders, /orders/42/order/42
Lowercase, hyphens for words/menu-items/MenuItems, /menu_items
Nest only to show ownership, one or two levels/customers/7/orders/a/1/b/2/c/3/d/4
No file extensions or trailing slashes/orders/42/orders/42.json
IDs identify; filters go in the query string/orders?status=ready/orders/ready

Methods map to actions

CRUD on the orders resource

ActionRequestSuccess response
List ordersGET /orders200 with a list
Get one orderGET /orders/42200 with the order, or 404
Create an orderPOST /orders201 with the order and a Location header
Replace an orderPUT /orders/42200 with the order
Change part of an orderPATCH /orders/42200 with the order
Delete an orderDELETE /orders/42204 with no body

Not every action is a clean CRUD operation. Changing an order's status is a good example. The Brew & Bean API uses PATCH /orders/{id}/status, a sub-resource that stands for one part of the order with its own rules (only received → preparing → ready → picked_up is allowed). For real actions that do not fit, use a verb sub-path with POST, for example POST /orders/42/cancel, and keep it rare.

The Brew & Bean API

Our four endpoints

Method and pathPurposeSuccess
GET /menuList the menu items200
POST /ordersPlace an order201
GET /orders/{id}Read one order200, or 404
PATCH /orders/{id}/statusStaff updates the status200
POST /orders request body
{
  "customer_name": "Asha",
  "phone": "9876543210",
  "items": [
    {"item_id": "cappuccino", "qty": 1},
    {"item_id": "croissant", "qty": 2}
  ],
  "pickup_time": "2026-11-02T09:30:00+05:30"
}

The client sends ids and quantities only. It never sends prices or totals.

201 Created response
{
  "id": 42,
  "customer_name": "Asha",
  "phone": "9876543210",
  "items": [
    {"item_id": "cappuccino", "qty": 1},
    {"item_id": "croissant", "qty": 2}
  ],
  "total": 480,
  "status": "received",
  "pickup_time": "2026-11-02T09:30:00+05:30",
  "created_at": "2026-11-02T08:55:12+05:30"
}

The total is 180 + 2 x 150 = 480, computed by the server. Use ISO 8601 for dates and keep the format identical across the API.

Good response design

Response habits

  1. Always return JSON with Content-Type: application/json.
  2. Use the same field names and casing everywhere (this track uses snake_case).
  3. Return the created or updated resource so the client does not need a second call.
  4. Use correct status codes; do not return 200 with {"error": ...} inside.
  5. Use ISO 8601 for dates; store money as integers (rupees or paise), never floating point.
  6. Never leak internals: no stack traces, SQL or passwords in responses.

Filtering, sorting and pagination

A list endpoint that returns everything breaks once you have 100,000 orders. Let clients narrow and page the results using query parameters.

Query parameters

NeedExample
FilterGET /orders?status=ready
Several filtersGET /menu?category=coffee&max_price=200
SortGET /orders?sort=-created_at (a minus means descending)
Pagination by pageGET /orders?page=2&limit=20
Pagination by cursorGET /orders?limit=20&after=42
A paginated list response
{
  "items": [ {"id": 42, "status": "ready"}, {"id": 41, "status": "ready"} ],
  "page": 1,
  "limit": 20,
  "total": 57
}

Always set a default and a maximum limit on the server (for example 20 and 100).

Page numbers are simple but can skip or repeat rows when new data arrives while the client is paging. Cursor pagination ("give me 20 orders after id 42") is steadier and faster on big tables. Start with page and limit; move to cursors when you need to.

A consistent error format

Clients need to show a helpful message and decide what to do next. Pick one error shape and use it for every error.

422 Unprocessable Content
{
  "error": {
    "code": "validation_error",
    "message": "One or more fields are invalid.",
    "details": [
      {"field": "items[0].qty", "message": "Must be at least 1"},
      {"field": "phone", "message": "Must be a 10-digit number"}
    ]
  }
}

A machine-readable code, a human-readable message, and per-field details.

Versioning and compatibility

Once a mobile app is in users' hands, you cannot force everyone to update. If you rename a field or change a response shape, old apps break. Two ways to stay safe:

- Additive changes are fine: adding a new field or a new endpoint does not break clients. Clients should ignore fields they do not know. - Breaking changes need a new version: put it in the path (/v1/orders, then /v2/orders) and keep v1 running until clients move. Path versioning is the simplest to understand and test.

REST is not the only style

Some teams use GraphQL (the client asks for exactly the fields it wants) or gRPC (fast binary calls between services). They are covered in *GraphQL and gRPC: other API styles*. REST remains the default for public and web APIs, and the most asked about in interviews.

How this comes up in interviews

Expect: "Design the endpoints for a library / to-do app / e-commerce cart". A strong answer lists the resources, uses plural nouns and the right methods, shows the status codes, covers pagination and an error format, and mentions authentication. Others: "What makes an API RESTful?" (resources, standard methods, stateless requests, consistent representations), "PUT versus PATCH", and "How do you version an API?"

Prompt · Review my API design
You are a senior backend engineer reviewing an API design. Here is my design for [app, e.g. a library system]:

---
[list your endpoints with method, path, request and response]
---

Review it against REST conventions: resource naming, correct methods and status codes, pagination, error format and versioning. List problems in order of importance and show the corrected endpoint list as a table.

What to expect: Check that the answer notices verbs in URLs, wrong status codes and missing pagination, and then confirm each suggestion makes sense for your app.

Try it: Design a library API

Design the REST endpoints for a small library with books and members, where a member can borrow and return a book. List each endpoint with method, path and success status code. Include one list endpoint with filtering and pagination, and show one error response.

Try it: Fix the bad API

Rewrite these endpoints in proper REST style: GET /getAllOrders, POST /createOrder, POST /deleteOrder?id=5, GET /order/5/markReady.

Key takeaways

  1. REST models your API as resources named by plural nouns; the HTTP method is the verb.
  2. Use correct status codes: 201 for created, 204 for no content, 404 for missing, 422 or 400 for invalid input.
  3. The client sends ids and quantities; the server computes prices and totals.
  4. Add filtering, sorting and pagination to list endpoints, with a default and a maximum limit.
  5. Use one consistent JSON error format everywhere.
  6. Adding fields is safe; breaking changes need a new version such as /v2.

Check yourself

Finishing the quiz marks the lesson as done.

1. Which is the best REST endpoint to cancel and delete an order with id 7?

2. A POST /orders request succeeds and creates a new order. What should the response be?

3. Why should the server compute an order's total instead of reading it from the request?

4. What is a key advantage of cursor pagination over page numbers?

5. You rename the field phone to mobile in your live API. What is the safest approach?

Saved on this device. Create a free account to keep it on every device.

Practise this with Sam

A real mock interview, out loud, with an honest scorecard. Free to start.

Start free