Menu

Topic 4 of 8

Designing RESTful Endpoints

Learn Designing RESTful Endpoints for free with explanations, exercises, and a quick test (for Backend Engineer).

Published: January 20, 2026 | Updated: January 20, 2026

Why this matters

Well-designed RESTful endpoints make your API predictable, easy to use, and scalable. As a Backend Engineer, you will:

  • Expose data through stable URLs clients can trust.
  • Model business concepts as resources, not ad-hoc actions.
  • Handle pagination, filtering, sorting, and errors consistently.
  • Support idempotent operations to avoid duplicate writes.
  • Evolve versions without breaking existing clients.

Who this is for

  • Backend Engineers building or refactoring HTTP APIs.
  • Developers moving from monolith controllers to resource-centric design.
  • Anyone integrating services that must communicate over HTTP.

Prerequisites

  • Basic HTTP knowledge (methods, status codes, headers).
  • Familiarity with JSON and request/response flow.
  • Comfortable with a server framework in any language.

Concept explained simply

RESTful endpoints treat your domain as resources (nouns), manipulated with standard HTTP methods (verbs):

  • GET: retrieve resources (safe, no side effects).
  • POST: create a new resource or trigger a non-idempotent action on a collection.
  • PUT: replace a resource (idempotent).
  • PATCH: partially update a resource (idempotent if designed so).
  • DELETE: remove a resource (idempotent by convention).

Keep paths noun-based and plural for collections. Use query parameters for filtering, sorting, and pagination. Return standard status codes and a consistent error body.

Mental model

Think in two layers:

  • Resource Map: a tree of collections and items (e.g., /orders, /orders/{id}, /orders/{id}/items).
  • Action Rules: which methods are allowed on each node and what they mean.
Step 1: Name resources as nouns (plural for collections).
Step 2: Decide which methods each resource supports and why.
Step 3: Add read-only server-driven behaviors via query params (filter, sort, pagination).
Step 4: Define response shapes, status codes, and error format.

Design principles in practice

Resource naming

  • Collections: /products, /users, /orders
  • Single resource: /products/{product_id}
  • Nested when it clarifies ownership: /users/{id}/orders (user’s orders)
  • Avoid verbs in paths: prefer POST /users over /createUser

Collections vs items

GET /tasks           # list tasks
POST /tasks          # create task (201 + Location)
GET /tasks/{id}      # fetch one
PUT /tasks/{id}      # full replace
PATCH /tasks/{id}    # partial update
DELETE /tasks/{id}   # delete

Filtering, sorting, pagination

GET /products?category=shoes&price_lt=100&sort=price,-rating&page=2&per_page=20
  • Use clear operators (e.g., price_lt, created_gte).
  • Return pagination metadata in response.
{
  "data": [ ... ],
  "page": 2,
  "per_page": 20,
  "total": 134,
  "total_pages": 7
}

Idempotency and updates

  • PUT is idempotent: same request repeated yields same state.
  • PATCH is partial update; design so repeated calls do not overshoot (e.g., set values, not increment counters).
  • DELETE can return 204 even if already deleted (idempotent behavior).

Status codes and responses

  • 200 OK for successful GET/PUT/PATCH with body.
  • 201 Created + Location header for POST creating a resource.
  • 204 No Content when no body is needed (DELETE, sometimes PATCH).
  • 400/422 for validation errors; 404 not found; 409 conflict; 500 server error.
{
  "error": {
    "code": "validation_error",
    "message": "Email is invalid",
    "details": { "email": ["must be valid"] }
  }
}

Versioning

  • Common: prefix path with /v1, /v2 when breaking changes are introduced.
  • Keep minor additions backward compatible to avoid version churn.

Worked examples

Example 1: To-do app
# Collections and items
GET  /v1/todos
POST /v1/todos
GET  /v1/todos/{id}
PATCH/PUT /v1/todos/{id}
DELETE /v1/todos/{id}

# Filtering and sorting
GET /v1/todos?status=open&due_lte=2026-01-31&sort=-priority,created_at

# Example create response
201 Created
Location: /v1/todos/123
{
  "id": "123",
  "title": "Ship release",
  "status": "open",
  "priority": 2
}
Example 2: E-commerce orders
# User orders
GET  /v1/users/{user_id}/orders
POST /v1/users/{user_id}/orders
GET  /v1/orders/{order_id}
PATCH /v1/orders/{order_id}   # update status, address

# Order items as a nested resource
GET    /v1/orders/{order_id}/items
POST   /v1/orders/{order_id}/items
DELETE /v1/orders/{order_id}/items/{item_id}

# Conflicts
PATCH /v1/orders/{id}  # 409 if state transition is invalid
Example 3: Blog posts and comments
# Posts
GET  /v1/posts?author_id=7&tag=rest
POST /v1/posts
GET  /v1/posts/{id}
PATCH /v1/posts/{id}

# Comments as child resource
GET  /v1/posts/{id}/comments
POST /v1/posts/{id}/comments
DELETE /v1/comments/{comment_id}

# Like as a subresource (avoid verbs)
POST   /v1/posts/{id}/likes
DELETE /v1/posts/{id}/likes/{user_id}

Exercises

Do these on paper or in a text editor. Then compare with the solutions.

Exercise 1 — Library API
Design endpoints for books, authors, and checkouts. Include listing, creating, fetching one, updating, deleting; relate books to authors; handle checkout/return of a book by a user; add filtering and pagination for books.
  • [ ] Collections and item routes for books and authors
  • [ ] Link books to authors
  • [ ] Checkout as an idempotent design
  • [ ] Filters: genre, author_id; pagination
Reveal sample solution for Exercise 1
GET  /v1/books?genre=fantasy&author_id=42&page=1&per_page=20
POST /v1/books
GET  /v1/books/{book_id}
PATCH/PUT /v1/books/{book_id}
DELETE /v1/books/{book_id}

GET  /v1/authors
POST /v1/authors
GET  /v1/authors/{author_id}
PATCH/PUT /v1/authors/{author_id}
DELETE /v1/authors/{author_id}

# Relationship (books of an author)
GET /v1/authors/{author_id}/books

# Checkouts as a subresource (idempotent by specific key)
POST   /v1/books/{book_id}/checkouts        # body includes user_id
DELETE /v1/books/{book_id}/checkouts/{user_id}

# Create responses
201 Created + Location: /v1/books/abc123
Exercise 2 — Streaming API
Design endpoints for movies and user ratings. Decide when to use POST vs PUT vs PATCH. Add pagination and sorting for top-rated movies.
  • [ ] Movies collection and items
  • [ ] Ratings as a user-movie relationship
  • [ ] Idempotent rating updates
  • [ ] Sorting and pagination for rankings
Reveal sample solution for Exercise 2
GET  /v1/movies?genre=sci-fi&year_gte=2020&sort=-rating_count,-avg_rating&page=1&per_page=50
POST /v1/movies
GET  /v1/movies/{movie_id}
PATCH /v1/movies/{movie_id}  # partial updates like title, year

# Ratings (one rating per user per movie)
PUT   /v1/movies/{movie_id}/ratings/{user_id}   # idempotent upsert of a rating
GET   /v1/movies/{movie_id}/ratings             # list ratings
GET   /v1/users/{user_id}/ratings               # user’s ratings across movies

# Delete a rating
DELETE /v1/movies/{movie_id}/ratings/{user_id}

# Top lists
GET /v1/movies?sort=-avg_rating,-rating_count&page=1&per_page=20

Common mistakes and self-check

  • Verb-y paths (e.g., /createUser). Self-check: Are all paths nouns? If not, move verbs into HTTP methods or subresources.
  • Inconsistent naming (singular vs plural). Self-check: Collections plural, items singular identifier?
  • Leaking business actions into paths (/users/{id}/activate). Self-check: Can this be a state change via PATCH or a subresource (e.g., /activations)?
  • Non-idempotent PUT/PATCH. Self-check: Repeat request; does state change again unexpectedly?
  • Ambiguous filtering. Self-check: Are query params documented and validated (e.g., price_lt vs priceLessThan)?
  • Wrong status codes. Self-check: Are you using 201 with Location for creations, 204 when no body is returned?

Practical projects

  • Build a small task API with users, tasks, and labels. Include filters (status, due date), sorting, and pagination. Add 201 + Location for creations.
  • Create an orders API that enforces valid status transitions. Return 409 on invalid transitions and document the allowed states.
  • Refactor a legacy API that uses verb paths into resource-based endpoints without breaking clients; add /v2 for breaking changes.

Learning path

  • Start: Model resources and relationships for your domain.
  • Then: Add filtering, sorting, pagination; define error formats.
  • Next: Enforce idempotency and proper status codes.
  • Finally: Plan versioning and deprecation strategy.

Mini challenge

Design a minimal REST API for a survey app with surveys, questions, and responses. Include:

  • [ ] Create/list surveys and questions
  • [ ] Submit a response to a given survey
  • [ ] Prevent duplicate responses by the same user per survey (idempotency)
  • [ ] Pagination on listing responses
Hint

Think of responses as a subresource of surveys; use a stable key like user_id to ensure idempotency.

Quick Test & Progress

Take the quick test below to check understanding. Anyone can take it for free; logged-in users will have progress saved automatically.

Next steps

  • Implement one practical project end-to-end and write short API docs.
  • Add rate limiting and request validation to harden your API.
  • Explore authentication/authorization patterns to secure endpoints.

Practice Exercises

2 exercises to complete

Instructions

Design endpoints for a library domain that includes books, authors, and checkouts. Requirements:

  • Collections and item routes for books and authors.
  • List books by author and by genre; add pagination.
  • Checkout and return a book by a user; treat repeat operations as idempotent.
  • Use appropriate status codes for create/update/delete.
Expected Output
A list of endpoints covering books, authors, relationships, and checkouts with HTTP methods, example query parameters, and expected status codes.

Designing RESTful Endpoints — Quick Test

Test your knowledge with 10 questions. Pass with 70% or higher.

10 questions70% to pass

Have questions about Designing RESTful Endpoints?

AI Assistant

Ask questions about this tool