REST API Design

beginner 0-2 YOE REST API HTTP API-design pagination

REST is the most common way to build web APIs. When we open a mobile app and it loads our feed, it’s almost certainly making REST API calls behind the scenes. Understanding REST API design is fundamental for system design interviews because every system we design will have an API layer.

What Is REST?

REST stands for Representational State Transfer. In simple language, it’s a set of conventions for building APIs over HTTP. We use URLs to identify resources, HTTP methods to define actions, and JSON to send data back and forth.

REST isn’t a protocol or a standard — it’s an architectural style. That means there’s no strict spec, just widely accepted conventions.

Core Principles

  1. Resource-based — Everything is a resource (user, post, order) with a URL
  2. Stateless — Each request contains everything the server needs. No session state stored between requests.
  3. Uniform interface — Consistent URL patterns and HTTP methods
  4. Client-server — Frontend and backend are separate and can evolve independently

HTTP Methods

Each method maps to a CRUD operation:

MethodPurposeIdempotent?Example
GETRead a resourceYesGET /users/123
POSTCreate a new resourceNoPOST /users
PUTReplace an entire resourceYesPUT /users/123
PATCHUpdate part of a resourceYesPATCH /users/123
DELETERemove a resourceYesDELETE /users/123

Idempotent means calling it multiple times has the same effect as calling it once. GET, PUT, PATCH, and DELETE are idempotent. POST is not — calling POST /orders three times creates three orders.

Status Codes

We don’t just return data — we return a status code that tells the client what happened:

Success (2xx)

  • 200 OK — Request succeeded. Used for GET, PUT, PATCH.
  • 201 Created — Resource created. Used for POST.
  • 204 No Content — Success but nothing to return. Used for DELETE.

Client Error (4xx)

  • 400 Bad Request — The request body is malformed or invalid.
  • 401 Unauthorized — Not authenticated. “Who are you?”
  • 403 Forbidden — Authenticated but not allowed. “I know who you are, but you can’t do this.”
  • 404 Not Found — Resource doesn’t exist.
  • 409 Conflict — Conflicts with current state (e.g., duplicate email).
  • 429 Too Many Requests — Rate limit exceeded. Slow down.

Server Error (5xx)

  • 500 Internal Server Error — Something broke on our end.
  • 502 Bad Gateway — Our server got a bad response from an upstream service.
  • 503 Service Unavailable — Server is overloaded or down for maintenance.

A good rule: 4xx means the client did something wrong. 5xx means we did something wrong.

URL Design

Good REST URLs are intuitive and consistent:

# Resources are nouns, not verbs
✅ GET  /users/123
❌ GET  /getUser?id=123

# Plural nouns for collections
✅ GET  /users
❌ GET  /user

# Nested resources for relationships
✅ GET  /users/123/posts        (posts by user 123)
✅ GET  /users/123/posts/456    (specific post by user 123)

# Query params for filtering, sorting, searching
✅ GET  /posts?status=published&sort=created_at&order=desc
✅ GET  /users?search=manish

# Actions that don't fit CRUD → use sub-resources
✅ POST /orders/123/cancel
✅ POST /users/123/verify-email

API Design Example: Blog Platform

# Posts
GET    /posts                    → List all posts
GET    /posts/123                → Get post 123
POST   /posts                    → Create a new post
PUT    /posts/123                → Replace post 123
PATCH  /posts/123                → Update post 123 partially
DELETE /posts/123                → Delete post 123

# Comments on a post
GET    /posts/123/comments       → List comments on post 123
POST   /posts/123/comments       → Add comment to post 123
DELETE /posts/123/comments/456   → Delete comment 456

# User's posts
GET    /users/789/posts          → All posts by user 789

A response might look like:

{
  "id": 123,
  "title": "REST API Design Guide",
  "content": "...",
  "author": {
    "id": 789,
    "name": "Manish"
  },
  "created_at": "2024-03-15T10:30:00Z",
  "tags": ["api", "design"]
}

Pagination

When a collection has thousands of items, we can’t return them all at once. Two main approaches:

Offset-Based Pagination

GET /posts?page=2&limit=20

Simple but has problems:

  • If items are added/deleted between pages, we might skip or duplicate items
  • OFFSET 10000 in SQL is slow — the DB still scans 10,000 rows to skip them

Cursor-Based Pagination

GET /posts?after=abc123&limit=20

The cursor (abc123) is an opaque token pointing to the last item we saw. The server fetches the next 20 items after that cursor.

  • No skipping or duplicates even if data changes
  • Fast — uses an index scan instead of OFFSET
  • Used by Twitter, Facebook, Slack — basically everyone at scale

Response includes the next cursor:

{
  "data": [...],
  "pagination": {
    "next_cursor": "def456",
    "has_more": true
  }
}

API Versioning

APIs evolve. We can’t break existing clients when we change things.

URL versioning (most common):

GET /v1/users/123
GET /v2/users/123

Header versioning:

GET /users/123
Accept: application/vnd.myapi.v2+json

Query parameter:

GET /users/123?version=2

URL versioning is the most explicit and easiest to understand. It’s what most APIs use.

Other Best Practices

  • Use JSON for request and response bodies (set Content-Type: application/json)
  • Use ISO 8601 for dates2024-03-15T10:30:00Z, not “March 15, 2024”
  • Return meaningful errors — Include an error code and message
  • Rate limiting — Protect our API from abuse with 429 Too Many Requests
  • HTTPS everywhere — Never serve an API over plain HTTP
  • Authentication — Use Bearer tokens (JWT) or API keys in the Authorization header
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Email is required",
    "field": "email"
  }
}

Key Takeaway

In simple language, REST is about using URLs to identify things (resources), HTTP methods to do things to them (GET, POST, PUT, DELETE), and status codes to say what happened. Keep URLs clean and consistent, use cursor-based pagination for large datasets, version our API from day one, and always return helpful error messages. REST isn’t perfect for every use case, but it’s the default for good reason — it’s simple, well-understood, and works great for most APIs.