Menu

Topic 2 of 7

REST Principles

Learn REST Principles for free with explanations, exercises, and a quick test (for API Engineer).

Published: January 21, 2026 | Updated: January 21, 2026

Why this matters

REST is the most common style for web APIs. As an API Engineer, you will design endpoints, choose HTTP methods, return meaningful status codes, handle errors, and make APIs reliable and cache-friendly. Mastering REST principles helps you deliver APIs that are predictable, scalable, and easy for clients to use.

  • Real tasks you will face:
    • Designing resource-oriented endpoints for products, orders, users.
    • Making POST operations idempotent to prevent duplicate charges.
    • Implementing pagination, filtering, sorting, and caching with ETags.
    • Defining consistent error responses and status codes.
    • Rolling out versioning safely without breaking existing clients.

Concept explained simply

REST treats your API as a set of resources (nouns) that clients manipulate via standard HTTP methods (verbs). Clients exchange representations (often JSON) of those resources over stateless requests.

Mental model

Imagine a well-organized library:

  • Resources: books, authors, patrons.
  • Addresses: each shelf and book has a stable location (URI).
  • Actions: you read, add, update, or remove books (GET, POST, PUT, PATCH, DELETE).
  • Rules: the librarian follows consistent procedures (status codes, headers, caching), so patrons always know what to expect.

Core REST principles you will apply

  • Resource orientation: Use nouns, plural collections. Example: /orders, /orders/{id}, /users/{id}/orders.
  • Statelessness: Each request carries all necessary context (auth, params). The server does not rely on session state.
  • Uniform interface via HTTP methods:
    • GET: retrieve (safe, idempotent).
    • POST: create or perform a non-idempotent action.
    • PUT: replace or create at a known URI (idempotent).
    • PATCH: partial update (not guaranteed idempotent).
    • DELETE: remove (idempotent).
    • HEAD/OPTIONS: metadata and capability discovery.
  • Representations: Clients and servers exchange JSON/JSON+HAL/etc. via Content-Type and Accept.
  • Idempotency: Repeating a request has the same effect (GET, PUT, DELETE, HEAD, OPTIONS). For POST, use an idempotency key to emulate idempotent behavior for critical operations.
  • Cacheability: GET responses can be cached using Cache-Control, ETag/If-None-Match, Last-Modified/If-Modified-Since.
  • Layered system: Clients shouldn’t care if requests pass through proxies or gateways.
  • Discoverability (optional/HATEOAS): Include links in responses to guide clients, e.g., links.next for pagination.
  • Consistent status codes and error shapes: 2xx success, 4xx client issues, 5xx server issues, consistent error body.
  • Versioning: Prefer backward-compatible changes. Use headers (e.g., Accept: application/vnd.api.v2+json) or URI (/v2) when required.

Worked examples

1) Designing resource endpoints for Orders

GET   /orders               - list orders (paginate, filter by status)
POST  /orders               - create an order
GET   /orders/{orderId}     - get a single order
PATCH /orders/{orderId}     - update specific fields (status, shipping)
PUT   /orders/{orderId}     - replace the order (rarely used in practice here)
DELETE /orders/{orderId}    - cancel/remove order (idempotent)
GET   /users/{id}/orders    - orders for a user

Notes:

  • Query parameters: /orders?status=shipped&page=2&limit=25.
  • Prefer nouns and avoid verbs like /createOrder.

2) Partial update with PATCH

PATCH /orders/123
Content-Type: application/json
{
  "status": "shipped",
  "trackingNumber": "1Z999"
}

Server behavior:

  • Validate allowed fields; ignore unknown ones.
  • Return 200 with the updated resource, or 204 if returning no body.
  • If conflict with current state, 409; if not found, 404.

3) Idempotent create vs non-idempotent

Using POST for creation is common. To avoid duplicates (e.g., payments), accept an Idempotency-Key:

POST /payments
Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000
{
  "amount": 4200,
  "currency": "USD",
  "source": "tok_abc"
}

Server stores the key and the result for a period. Repeated POST with the same key returns the same outcome (usually 201 the first time, 200 on repeats).

4) Caching GET with ETag

# First response
GET /products/42
--> 200 OK
ETag: "W/\"p42-v7\""
{
  "id": 42,
  "name": "Keyboard",
  "price": 49.99,
  "updatedAt": "2025-05-05T10:00:00Z"
}

# Conditional request
GET /products/42
If-None-Match: "W/\"p42-v7\""
--> 304 Not Modified (no body)

Clients save bandwidth; servers save CPU.

Hands-on exercises

Do these in a text editor or your API tool of choice. A quick checklist is provided for each.

Exercise 1: Design a RESTful resource model for a Library

Goal: propose endpoints, methods, and example responses for a simple library system.

  1. Define resources: books, authors, patrons, loans.
  2. Create collection and item URIs (plural nouns).
  3. Assign HTTP methods for read/write operations.
  4. Provide one example request/response pair in JSON.
  • Uses nouns and plural collections
  • Includes pagination/filtering for at least one collection
  • Uses correct methods (GET/POST/PUT/PATCH/DELETE)
  • Returns proper status codes (201 on create, 404 when missing)
Show solution
GET   /books?authorId=&q=&page=&limit=
POST  /books
GET   /books/{bookId}
PATCH /books/{bookId}
DELETE /books/{bookId}
GET   /authors
GET   /authors/{authorId}
GET   /authors/{authorId}/books
POST  /patrons
GET   /patrons/{patronId}
POST  /loans                # create a loan
GET   /loans?patronId=&status=
PATCH /loans/{loanId}

# Example create
POST /books
Content-Type: application/json
{
  "title": "Dune",
  "authorId": "a1",
  "publishedYear": 1965
}
--> 201 Created
Location: /books/b42
{
  "id": "b42",
  "title": "Dune",
  "authorId": "a1",
  "publishedYear": 1965,
  "links": {"self": "/books/b42"}
}

Exercise 2: Add caching and idempotency

Goal: make a product API efficient and safe against duplicate POSTs.

  1. For GET /products/{id}, add ETag-based caching flow.
  2. For POST /orders, design an Idempotency-Key header behavior.
  • GET uses ETag/If-None-Match and can return 304
  • POST accepts Idempotency-Key and deduplicates
  • Status codes: 201 on first success, 200 on repeated
  • Server stores key and response for a safe window
Show solution
# Caching
GET /products/9
--> 200 OK
ETag: "\"prod9-v3\""
{ ... product ... }

GET /products/9
If-None-Match: "\"prod9-v3\""
--> 304 Not Modified

# Idempotency
POST /orders
Idempotency-Key: 1b2e8400-e29b-41d4-a716-446655440000
{ "items": [ ... ], "total": 129.00 }
--> First time: 201 Created, Location: /orders/o777, body: { ... }
--> Repeat with same key: 200 OK, same body as original

Common mistakes and how to self-check

  • Verb-y endpoints (e.g., /createOrder). Self-check: replace with nouns and HTTP verbs.
  • Wrong status codes (200 on create). Self-check: use 201 + Location for creation.
  • Forgetting idempotency for critical POSTs. Self-check: add Idempotency-Key.
  • No pagination on large collections. Self-check: ensure page and limit exist.
  • Inconsistent error bodies. Self-check: adopt a single JSON error shape for all 4xx/5xx.
  • Missing caching for expensive GETs. Self-check: add ETag or Last-Modified.
Reference error shape
{
  "error": {
    "code": "RESOURCE_NOT_FOUND",
    "message": "Order not found",
    "details": [{"field": "orderId", "issue": "unknown"}]
  }
}

Practical projects

  • Catalog API: Build /products with filtering, sorting, pagination, ETags, and a consistent error format.
  • Payments-like API: Implement POST /payments with Idempotency-Key, GET /payments/{id}, and webhook-style event resources.

Mini challenge

Design pagination for /orders that supports filtering by status and stable page navigation.

  1. Choose query params (page, limit, status).
  2. Return metadata (total, page, limit) and links.next/links.prev.
  3. Decide between offset vs cursor pagination and justify your choice.
Hint

Cursor pagination is more stable under concurrent writes; offset is simpler but can skip/duplicate items when lists change.

Learning path

  • Now: REST basics (this lesson).
  • Next: Authentication and authorization (tokens, OAuth2), validation, and rate limiting.
  • Later: API documentation, testing strategies, and observability (logs, traces).

Who this is for

  • Backend and API engineers who need to design or refactor HTTP APIs.
  • Developers moving from monoliths to service-oriented systems.
  • Front-end engineers integrating with server APIs who want predictable contracts.

Prerequisites

  • Basic HTTP knowledge (methods, headers, status codes).
  • Comfort with JSON and reading API responses.
  • Ability to test endpoints using an HTTP client.

Next steps

  • Complete the exercises above.
  • Take the quick test to confirm understanding.
  • Apply these patterns to one of your current APIs.

Quick Test

Take the quick test below to check your understanding. Available to everyone; only logged-in users will have results saved to progress.

Practice Exercises

2 exercises to complete

Instructions

Define resources and endpoints for a library system with books, authors, patrons, and loans. Include collection/item URIs, HTTP methods, and one example request/response in JSON.

  1. List resources and their relationships.
  2. Create collection and item URIs.
  3. Map HTTP methods to operations.
  4. Provide one example create flow with status codes.
Expected Output
A set of URIs using nouns and plural collections, proper methods, 201 + Location on create, and a sample JSON request/response.

REST Principles — Quick Test

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

8 questions70% to pass

Have questions about REST Principles?

AI Assistant

Ask questions about this tool