GET and HEAD must be safe and idempotent. Never use GET to modify data (even though nothing prevents it technically). PUT must be idempotent — calling it multiple times produces the same result. POST creates a new resource each time (not idempotent).
🔗
URL Design
NAMING
URL Naming Conventions
Rule
Correct ✅
Wrong ❌
Nouns, not verbs
/users
/getUsers
Plural nouns
/users/42
/user/42
Lowercase
/user-profiles
/UserProfiles
Hyphens
/user-profiles
/user_profiles
No file extensions
/users
/users.json
No trailing slash
/users
/users/
Resource nesting
/users/42/posts
/getUserPosts
Actions as verbs
/users/42/activate
/users/42/active
Common URL Patterns
Pattern
Example
Description
Collection
GET /users
List resources
Resource
GET /users/42
Single resource
Sub-collection
GET /users/42/posts
Nested resource
Action
POST /users/42/activate
Non-CRUD action
Search
GET /users?search=john
Query params
Count
GET /users/count
Special endpoint
Relationship
GET /users/42/friends
Related resources
api/url-examples.http
# ── Well-designed REST API URLs ──
# Collections
GET /api/v1/users # List users
POST /api/v1/users # Create user
GET /api/v1/users/42 # Get user
PUT /api/v1/users/42 # Replace user
PATCH /api/v1/users/42 # Update user
DELETE /api/v1/users/42 # Delete user
# Sub-resources
GET /api/v1/users/42/posts # User's posts
POST /api/v1/users/42/posts # Create post for user
GET /api/v1/posts/10/comments # Post's comments
# Actions (non-CRUD operations)
POST /api/v1/users/42/activate # Activate user
POST /api/v1/posts/10/publish # Publish post
POST /api/v1/orders/42/cancel # Cancel order
# Filtering, sorting, pagination
GET /api/v1/users?role=admin&sort=created_at&order=desc&page=2&limit=20
GET /api/v1/users?fields=id,name,email
GET /api/v1/posts?search=hello&category=tech
GET /api/v1/users?created_after=2024-01-01
# Versioning
GET /api/v1/users # URL path versioning
GET /api/users # Header versioning (Accept: ...;v=2)
⚠️
Use plural nouns for resource names./users not /user. Keep URLs predictable and consistent. Use query parameters for filtering, sorting, and pagination — not path segments.
🔢
Status Codes
RESPONSES
2xx Success
Code
Name
Usage
200
OK
Successful GET/PUT/PATCH/DELETE
201
Created
Successful POST (new resource)
202
Accepted
Accepted for async processing
204
No Content
Successful DELETE (no body)
206
Partial Content
Range requests (byte serving)
3xx Redirection
Code
Name
Usage
301
Moved Permanently
Resource moved (update URL)
302
Found
Temporary redirect
304
Not Modified
ETag/Cache match (no body)
307
Temporary Redirect
Preserve method on redirect
308
Permanent Redirect
Preserve method on redirect
4xx Client Errors
Code
Name
Usage
400
Bad Request
Invalid request body/params
401
Unauthorized
Missing or invalid auth
403
Forbidden
Authenticated but no permission
404
Not Found
Resource does not exist
405
Method Not Allowed
Wrong HTTP method
409
Conflict
Duplicate resource / version conflict
415
Unsupported Media
Wrong Content-Type
422
Unprocessable
Valid syntax, semantic errors
429
Too Many Requests
Rate limit exceeded
5xx Server Errors
Code
Name
Usage
500
Internal Server Error
Unhandled exception
502
Bad Gateway
Upstream server error
503
Service Unavailable
Server down / overloaded
504
Gateway Timeout
Upstream server timeout
api/error-response.json
// ── Standard Error Response Format (RFC 7807) ──
{
"type": "https://api.example.com/errors/validation",
"title": "Validation Error",
"status": 422,
"detail": "The request body contains invalid fields.",
"instance": "/api/v1/users",
"errors": [
{
"field": "email",
"message": "Must be a valid email address",
"code": "INVALID_EMAIL"
},
{
"field": "name",
"message": "Name is required",
"code": "REQUIRED"
}
],
"trace_id": "abc-123-def",
"timestamp": "2024-01-15T10:30:00Z"
}
🚫
Return 422 (not 400) for validation errors. 400 means the request itself is malformed (bad JSON syntax). 422 means the JSON is valid but the data fails business rules (empty name, invalid email). Always include error details in the response body.
Store tokens in httpOnly cookies (not localStorage) to prevent XSS theft. Use SameSite=Strict or Lax, Secure flag, and short expiry. Implement refresh token rotation to detect token reuse.
📋
Versioning & Pagination
EVOLUTION
api/versioning-strategies.md
# ── API Versioning Strategies ──
1. URL PATH (most common):
/api/v1/users
/api/v2/users
+ Simple, visible, cacheable
- URL changes between versions
2. HEADER-BASED:
Accept: application/vnd.api+json;version=2
+ Clean URLs
- Harder to test in browser
3. QUERY PARAMETER:
/api/users?version=2
+ Easy to test
- Easy to miss, not restful
4. CONTENT NEGOTIATION:
Accept: application/vnd.example.v2+json
+ Standard approach
- Complex implementation
# ── When to Version ──
- Breaking changes (removing fields, changing types)
- Renaming fields
- Changing resource structure
- NOT for: adding new fields, adding new endpoints
api/pagination-types.http
# ── Pagination Strategies ──
# 1. OFFSET-BASED (simple, has issues at scale)
GET /api/v1/users?page=3&limit=20
# Response:
{
"data": [...],
"pagination": {
"page": 3,
"limit": 20,
"total": 1542,
"total_pages": 78,
"has_next": true,
"has_prev": true
}
}
# 2. CURSOR-BASED (better for large datasets, real-time)
GET /api/v1/users?cursor=eyJpZCI6NDJ9&limit=20
# Response:
{
"data": [...],
"pagination": {
"next_cursor": "eyJpZCI6NjJ9",
"prev_cursor": "eyJpZCI6MjJ9",
"has_next": true,
"has_prev": true
}
}
# 3. KEYSET / SEEK METHOD (fastest, no offset)
GET /api/v1/users?after_id=42&limit=20
# Query: SELECT * FROM users WHERE id > 42 ORDER BY id LIMIT 20
# Comparison:
# Offset: Simple, but slow at 1M+ rows (COUNT scans)
# Cursor: Consistent with inserts/deletes, no skips
# Keyset: Fastest (indexed), but limited sorting
Pagination Comparison
Method
Speed
Consistency
Random Access
Offset
Slow at depth
May skip/duplicate
Yes (page=N)
Cursor
Fast
Stable
No (sequential only)
Keyset
Fastest
Stable
No (sequential only)
HATEOAS Links (Hypermedia)
Link
Purpose
self
Current resource URL
next
Next page of results
prev
Previous page
first
First page
last
Last page
related
Related resource
💡
Use cursor-based pagination for large, frequently changing datasets. Offset-based is simpler but produces inconsistent results when data is inserted/deleted between pages. Keyset pagination is fastest but only works with ordered, indexed fields.
Always return 429 with Retry-After header when rate limited. Use tiered limits (e.g., free: 100/hr, pro: 1000/hr, enterprise: unlimited). Implement at the API gateway level for central control.
Write your OpenAPI spec first (design-first), then implement. This ensures API consistency, generates documentation automatically, and enables client SDK generation. Use tools like Swagger UI or Redoc for interactive documentation.
🎯
Interview Q&A
PREP
Q: What makes an API RESTful?REST = Representational State Transfer. Key constraints: Client-server architecture, stateless (no server sessions), cacheable, uniform interface (HTTP methods + resource URIs), layered system (load balancers/proxies). An API is RESTful if it uses HTTP methods correctly on resource URLs, returns proper status codes, and is stateless.
Q: PUT vs PATCH?PUT replaces the ENTIRE resource — the client must send all fields. Missing fields are set to null/default. PUT is idempotent (calling N times = same as 1). PATCH updates PARTIAL fields — only send what changes. PATCH may not be idempotent (depends on the patch format).
Q: What is idempotency?An operation is idempotent if calling it multiple times produces the same result as calling once. GET, PUT, DELETE are idempotent. POST is not (creates new resource each time). This matters for retries — if a request fails, you can safely retry idempotent operations.
Q: How to handle pagination?Three strategies: (1) Offset (page=3&limit=20) — simple but inconsistent with data changes. (2) Cursor (cursor=abc&limit=20) — stable, scalable, but no random access. (3) Keyset (after_id=42) — fastest using indexes, but sequential only. Use cursor for large/real-time datasets.
Q: OAuth 2.0 flow explained?Authorization Code: (1) Redirect user to auth server, (2) User logs in, (3) Auth server redirects with code, (4) Exchange code for tokens. PKCE extension for public clients (SPAs, mobile). Client Credentials for server-to-server. Implicit flow is deprecated.
Q: How to version an API?URL path (/v1/users) is most common and visible. Header-based (Accept: application/vnd.api+json;v=2) is cleaner but harder to test. Query param (?version=2) is least recommended. Only version on breaking changes, not for adding new fields.
Q: What is HATEOAS?Hypermedia as the Engine of Application State — responses include links to related actions (next page, related resource, delete link). Goal: the client discovers actions from the response, not hard-coded URLs. In practice, most APIs skip this for simplicity.
💡
Top REST API interview topics: HTTP methods & idempotency, status codes, URL design, authentication (JWT/OAuth2), versioning, pagination strategies, rate limiting, error handling (RFC 7807), OpenAPI/Swagger, caching (ETag), and HATEOAS.