FroquizFroquiz
HomeQuizzesSenior ChallengeGet CertifiedBlogAbout
Sign InStart Quiz
Sign InStart Quiz
Froquiz

The most comprehensive quiz platform for software engineers. Test yourself with 10000+ questions and advance your career.

LinkedIn

Platform

  • Start Quizzes
  • Topics
  • Blog
  • My Profile
  • Sign In

About

  • About Us
  • Contact

Legal

  • Privacy Policy
  • Terms of Service

Β© 2026 Froquiz. All rights reserved.Built with passion for technology
Blog & Articles

REST API Design Best Practices: A Complete Guide for Developers

Learn how to design clean, consistent REST APIs. Covers naming conventions, HTTP methods, status codes, versioning, pagination, authentication, and error handling.

Yusuf SeyitoğluMarch 11, 20262 views10 min read

REST API Design Best Practices: A Complete Guide for Developers

A well-designed REST API is a joy to use. A poorly designed one causes bugs, confusion, and hours of wasted time for everyone who consumes it. Whether you're building your first API or reviewing an existing one, these best practices will help you design endpoints that developers actually want to work with.

What Is REST?

REST (Representational State Transfer) is an architectural style for building APIs over HTTP. It is not a protocol or standard β€” it is a set of constraints that, when followed, produce predictable, scalable, and easy-to-understand APIs.

The six REST constraints are: statelessness, client-server separation, cacheability, layered system, uniform interface, and (optionally) code on demand. In practice, most "REST APIs" focus on the uniform interface β€” consistent URLs, HTTP methods, and response formats.

Use Nouns, Not Verbs in URLs

The most common REST design mistake: putting actions in the URL.

code
# Bad β€” verbs in URLs GET /getUsers POST /createUser PUT /updateUser/42 DELETE /deleteUser/42 # Good β€” nouns only, HTTP method carries the action GET /users POST /users PUT /users/42 DELETE /users/42

The HTTP method (GET, POST, PUT, DELETE) already expresses the action. The URL should describe the resource, not the operation.

Use Plural Nouns for Collections

code
# Inconsistent β€” avoid GET /user GET /users/42/order # Consistent β€” plural everywhere GET /users GET /users/42 GET /users/42/orders GET /users/42/orders/7

Using plural consistently makes the API predictable. /users is a collection, /users/42 is a single item β€” this pattern holds everywhere.

HTTP Methods and Their Meanings

MethodActionIdempotentSafe
GETReadYesYes
POSTCreateNoNo
PUTReplace (full update)YesNo
PATCHPartial updateNoNo
DELETEDeleteYesNo

Idempotent means calling it multiple times has the same effect as calling it once. DELETE /users/42 twice is the same as deleting once (second call might return 404, but the state is the same).

Safe means it does not modify server state.

HTTP Status Codes

Use the right status code β€” do not return 200 OK with {"error": "not found"} in the body.

Success codes

code
200 OK β€” successful GET, PUT, PATCH, DELETE 201 Created β€” successful POST (include Location header) 204 No Content β€” success with no response body (DELETE)

Client error codes

code
400 Bad Request β€” invalid input, validation failed 401 Unauthorized β€” not authenticated (no or bad token) 403 Forbidden β€” authenticated but not allowed 404 Not Found β€” resource does not exist 409 Conflict β€” duplicate resource, version conflict 422 Unprocessable β€” well-formed but semantically invalid 429 Too Many Requests β€” rate limit exceeded

Server error codes

code
500 Internal Server Error β€” unexpected server error 502 Bad Gateway β€” upstream service failed 503 Service Unavailable β€” server down or overloaded

Consistent Error Response Format

Always return errors in a consistent, machine-readable format:

json
{ "error": { "code": "VALIDATION_ERROR", "message": "Request validation failed", "details": [ { "field": "email", "message": "Must be a valid email address" }, { "field": "age", "message": "Must be at least 18" } ] } }

Include a human-readable message, a machine-readable code, and field-level details for validation errors. This makes debugging fast for API consumers.

Versioning

APIs change over time. Versioning protects existing clients when you make breaking changes.

The most common approaches:

code
# URL versioning β€” most visible, easiest to test in browser GET /v1/users GET /v2/users # Header versioning β€” cleaner URLs GET /users Accept: application/vnd.myapi.v2+json # Query parameter versioning β€” simple but messy GET /users?version=2

URL versioning (/v1/, /v2/) is the most widely used. It is easy to document, easy to test, and immediately obvious in logs.

Best practice: Version from day one, even if you only have v1. Retrofitting versioning later is painful.

Filtering, Sorting, and Searching

Use query parameters for these β€” never create separate endpoints.

code
# Filtering GET /users?status=active GET /orders?status=pending&created_after=2024-01-01 # Sorting GET /users?sort=created_at&order=desc GET /products?sort=price&order=asc # Searching GET /users?search=alice # Combining GET /products?category=electronics&sort=price&order=asc&search=laptop

Pagination

Never return unlimited collections β€” always paginate.

Offset pagination

GET /users?page=2&per_page=20

Response:

json
{ "data": [...], "pagination": { "page": 2, "per_page": 20, "total": 243, "total_pages": 13 } }

Simple but has performance issues on large datasets (database must count and skip rows).

Cursor pagination

code
GET /users?cursor=eyJpZCI6MTAwfQ&limit=20

Response:

json
{ "data": [...], "next_cursor": "eyJpZCI6MTIwfQ", "has_more": true }

More scalable for large datasets β€” no offset calculation needed. Preferred for real-time feeds (Twitter, Instagram style).

Nested Resources

Use nesting to express ownership relationships β€” but keep it shallow.

code
# Good β€” one level of nesting GET /users/42/orders POST /users/42/orders GET /users/42/orders/7 # Too deep β€” avoid GET /users/42/orders/7/items/3/reviews/1

If nesting goes more than two levels deep, consider using a flat endpoint with filter parameters instead:

code
# Instead of: GET /users/42/orders/7/items GET /order-items?order_id=7

Request and Response Design

Use JSON everywhere

code
Content-Type: application/json Accept: application/json

Return the created/updated resource in the response

http
POST /users Content-Type: application/json { "name": "Alice", "email": "alice@example.com" }

Response 201 Created:

json
{ "id": 42, "name": "Alice", "email": "alice@example.com", "created_at": "2025-03-11T10:00:00Z" }

Returning the full resource avoids a second GET request.

Use ISO 8601 for dates

json
{ "created_at": "2025-03-11T10:00:00Z", "expires_at": "2025-04-11T10:00:00Z" }

Always use UTC. Never return Unix timestamps without documentation.

Authentication

Use standard, well-understood auth patterns.

JWT Bearer tokens β€” most common for modern APIs:

http
GET /users/me Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5...

API Keys β€” for server-to-server or developer access:

http
GET /data X-API-Key: sk_live_abc123...

Never put credentials in query parameters β€” they appear in server logs and browser history:

code
# Never do this GET /users?api_key=secret123

Documentation

An undocumented API is an unusable API. Use tools like:

  • OpenAPI / Swagger β€” industry standard, generates interactive docs
  • Postman Collections β€” easy to share, test, and run
  • Redoc β€” beautiful rendered OpenAPI docs

Document every endpoint: what it does, what parameters it accepts, what it returns, and what errors it can produce.

Common Interview Questions

Q: What is the difference between PUT and PATCH?

PUT replaces the entire resource. PATCH applies a partial update. If you PUT a user with only {"name": "Bob"}, the email and other fields are cleared. With PATCH, only name changes.

Q: What does idempotent mean? Which HTTP methods are idempotent?

Calling an idempotent operation multiple times produces the same result as calling it once. GET, PUT, and DELETE are idempotent. POST is not β€” calling POST /orders twice creates two orders.

Q: What is HATEOAS?

Hypermedia As The Engine Of Application State β€” responses include links to related actions and resources. A true REST constraint, but rarely implemented fully in practice.

Practice API Design Questions on Froquiz

Understanding REST is essential for backend and full-stack developers. Test yourself with our backend quizzes on Froquiz β€” covering API design, databases, Docker, and more.

Summary

  • URLs describe resources (nouns), HTTP methods describe actions
  • Use plural nouns: /users, /orders, /products
  • Return correct HTTP status codes β€” never hide errors in 200 responses
  • Consistent error format with machine-readable codes
  • Version from day one: /v1/, /v2/
  • Paginate all collections β€” offset for simplicity, cursor for scale
  • Use ISO 8601 dates, JSON everywhere, Bearer tokens for auth
  • Document everything with OpenAPI

About Author

Yusuf Seyitoğlu

Author β†’

Other Posts

  • CSS Advanced Techniques: Custom Properties, Container Queries, Grid Masonry and Modern LayoutsMar 12
  • System Design Fundamentals: Scalability, Load Balancing, Caching and DatabasesMar 12
  • GraphQL Schema Design: Types, Resolvers, Mutations and Best PracticesMar 12
All Blogs