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
| Rule | Good | Avoid |
|---|---|---|
| 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
| Action | Request | Success response |
|---|---|---|
| List orders | GET /orders | 200 with a list |
| Get one order | GET /orders/42 | 200 with the order, or 404 |
| Create an order | POST /orders | 201 with the order and a Location header |
| Replace an order | PUT /orders/42 | 200 with the order |
| Change part of an order | PATCH /orders/42 | 200 with the order |
| Delete an order | DELETE /orders/42 | 204 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 path | Purpose | Success |
|---|---|---|
| GET /menu | List the menu items | 200 |
| POST /orders | Place an order | 201 |
| GET /orders/{id} | Read one order | 200, or 404 |
| PATCH /orders/{id}/status | Staff updates the status | 200 |
{
"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.
{
"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
- Always return JSON with
Content-Type: application/json. - Use the same field names and casing everywhere (this track uses snake_case).
- Return the created or updated resource so the client does not need a second call.
- Use correct status codes; do not return 200 with
{"error": ...}inside. - Use ISO 8601 for dates; store money as integers (rupees or paise), never floating point.
- 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
| Need | Example |
|---|---|
| Filter | GET /orders?status=ready |
| Several filters | GET /menu?category=coffee&max_price=200 |
| Sort | GET /orders?sort=-created_at (a minus means descending) |
| Pagination by page | GET /orders?page=2&limit=20 |
| Pagination by cursor | GET /orders?limit=20&after=42 |
{
"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.
{
"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?"
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
- REST models your API as resources named by plural nouns; the HTTP method is the verb.
- Use correct status codes: 201 for created, 204 for no content, 404 for missing, 422 or 400 for invalid input.
- The client sends ids and quantities; the server computes prices and totals.
- Add filtering, sorting and pagination to list endpoints, with a default and a maximum limit.
- Use one consistent JSON error format everywhere.
- 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.