Designing REST APIs
Model resources, choose methods and status codes, and handle pagination, errors and idempotency.
13 min read
You will learn
- Design resource-oriented URLs
- Map operations to HTTP methods and status codes
- Design pagination, filtering and error responses
- Explain idempotency and why it matters for retries
What an API is
An API (Application Programming Interface) is a contract that lets programs talk to each other. A web API exposes your backend's capabilities over HTTP so that your frontend, mobile apps, partners — or other backend services — can use them.
The most common style is REST (Representational State Transfer). Its core ideas:
- Expose resources (customers, orders, products) at URLs.
- Use the HTTP methods for actions, and status codes for outcomes.
- Each request is stateless and self-contained.
- Exchange representations of resources — usually JSON.
Resources and URLs
URLs are nouns, usually plural, nested where there's a clear ownership:
| ✅ Good | ❌ Avoid |
|---|---|
GET /products | GET /getAllProducts |
GET /products/42 | GET /product?id=42&action=get |
POST /orders | POST /createOrder |
GET /customers/7/orders | GET /ordersOfCustomer/7 |
POST /orders/42/cancellation | POST /cancelOrder?id=42 |
Actions that don't fit CRUD (cancel, refund, publish) can be modeled as sub-resources: create a cancellation of an order.
Methods and status codes together
| Operation | Request | Success response |
|---|---|---|
| List | GET /products?category=books | 200 OK + array |
| Read one | GET /products/42 | 200 OK, or 404 Not Found |
| Create | POST /products + JSON body | 201 Created + Location: /products/43 + the new resource |
| Replace | PUT /products/42 + full body | 200 OK (or 204 No Content) |
| Partial update | PATCH /products/42 + changed fields | 200 OK |
| Delete | DELETE /products/42 | 204 No Content |
Common failure codes: 400 invalid input, 401 not authenticated, 403 not allowed, 404 not found, 409 conflict (e.g. duplicate email, outdated version), 422 semantically invalid, 429 too many requests, 500 server bug, 503 temporarily unavailable.
Try the contract
Use the mock todo API: create, update and delete todos, and see which status codes and headers come back — including what happens with invalid data or a missing token.
HTTP Playground
Send requests to a mock todo API at https://api.example.com — it runs in your browser
Server state: 2 todos — #1 ✓ Learn HTTP, #2 ○ Build an API
Errors: Problem Details
Return errors in a consistent, machine-readable shape. The standard is Problem Details (RFC 9457), which ASP.NET Core produces for you:
{
"type": "https://example.com/errors/validation",
"title": "One or more validation errors occurred.",
"status": 400,
"errors": {
"quantity": ["Quantity must be at least 1."],
"email": ["'ada@' is not a valid email address."]
}
}Never leak stack traces or SQL to clients — log them on the server instead.
Filtering, sorting and pagination
Collections can be huge, so never return "everything":
GET /products?category=books&sort=-price&limit=20- Offset pagination:
?page=3&pageSize=20— simple, but deep pages are slow and items shift when data changes. - Cursor pagination:
?limit=20&after=eyJpZCI6MTIzNH0— the response includes anextcursor; stable and fast. Used by most large APIs.
Return paging metadata in the body ("next": "/products?after=...") or headers (Link).
Idempotency: safe to retry
Networks fail. If a client's request times out, did it succeed or not? Retrying is only safe if the operation is idempotent — repeating it has the same effect as doing it once:
GET,PUT,DELETEare idempotent by definition.POSTusually isn't: retrying "create payment" could charge twice.
For non-idempotent operations, APIs accept an idempotency key: the client generates a unique id per logical operation, and the server remembers which keys it has already processed.
POST /payments
Idempotency-Key: 5c1f9a7e-6a2b-4d0e-9e0b-1f8f3c7a2d11Versioning
APIs evolve, but published clients don't update instantly. Avoid breaking changes (removing fields, changing types); add instead. When you must break things, version: /v2/orders or a header like Api-Version: 2.
Key takeaways
- Resources are nouns at URLs; HTTP methods are the verbs; status codes report outcomes.
201 Created+Locationfor creation,204for deletes,4xxfor client errors, Problem Details for error bodies.- Paginate collections — cursors scale best.
- Make retried operations safe with idempotent methods or idempotency keys, and version carefully.
Quiz
4 questions · 3 correct to pass1.Which URL design is most RESTful for "the orders of customer 7"?
2.Which methods are idempotent — repeating the same request has the same effect as sending it once?
3.A client sends invalid data (a negative quantity). Which status code fits?
4.Why is cursor-based pagination often preferred over page numbers for large, changing data sets?
To complete this lesson
- ○ Pass the quiz (3/4 correct)