What Is REST?

REST (Representational State Transfer) is an architectural style for designing networked applications, defined by Roy Fielding in his 2000 doctoral dissertation. It is not a protocol or standard — it is a set of constraints that, when applied to web services, make them scalable, simple, and reliable.

REST has become the dominant approach for web APIs because it leverages the existing HTTP protocol, making it easy to understand and implement. When people say “REST API” or “RESTful API,” they mean a web service that follows REST architectural principles.

REST vs. Other Styles

Before REST became dominant, most web services used SOAP (Simple Object Access Protocol), which required XML messages, strict schemas, and was often complex. REST simplified everything by using standard HTTP methods and allowing flexible data formats (primarily JSON).

FeatureRESTSOAPGraphQL
ProtocolHTTPHTTP, SMTP, etc.HTTP
Data formatJSON, XML, etc.XML onlyJSON
ContractOptional (OpenAPI)Required (WSDL)Required (Schema)
Learning curveLowHighMedium
CachingBuilt-in (HTTP)CustomCustom

The Six REST Constraints

Roy Fielding defined six constraints that an API must follow to be considered RESTful. Understanding these is essential for testing because violations of these constraints often indicate design problems or potential bugs.

1. Client-Server Separation

The client (frontend) and server (backend) must be independent. The client only knows how to make requests; the server only knows how to process them and return responses. This separation allows each to evolve independently.

Testing implication: You can test the API independently of any specific client. A mobile app, web app, or cURL command should all get the same results for the same request.

2. Stateless

Each request from the client must contain all the information the server needs to process it. The server does not store session state between requests. Authentication tokens, user preferences, and any context must be sent with every request.

Testing implication: You can send any request in isolation without needing to send previous requests first (except for data dependencies). Each request should be independently verifiable.

3. Cacheable

Responses must indicate whether they can be cached. Proper caching reduces server load and improves performance. HTTP provides cache headers (Cache-Control, ETag, Last-Modified) to manage this.

Testing implication: Verify that cache headers are set correctly. GET requests for static data should be cacheable; POST/PUT/DELETE responses typically should not be.

4. Uniform Interface

This is the most distinctive REST constraint. It has four sub-constraints:

  • Resource identification — each resource has a unique URI (e.g., /users/42)
  • Resource manipulation through representations — clients work with representations (JSON, XML) of resources, not the resources directly
  • Self-descriptive messages — each message includes enough information to describe how to process it (Content-Type, methods)
  • HATEOAS — responses include links to related actions

5. Layered System

The client cannot tell whether it is connected directly to the server or to an intermediary (load balancer, CDN, API gateway). Each layer only knows about the layer it interacts with.

Testing implication: Test through the actual infrastructure (including load balancers and API gateways) in staging environments, not just against the bare server.

6. Code on Demand (Optional)

Servers can optionally send executable code (like JavaScript) to clients. This is the only optional constraint and is rarely used in API contexts.

Resource Design and URL Structure

One of the most visible aspects of REST is how URLs are structured. RESTful URLs represent resources (nouns), not actions (verbs).

Resource Naming Conventions

Good (RESTful):
GET    /users              → List all users
GET    /users/42           → Get user 42
POST   /users              → Create a new user
PUT    /users/42           → Update user 42
DELETE /users/42           → Delete user 42

Bad (not RESTful):
GET    /getUsers
POST   /createUser
GET    /getUserById?id=42
POST   /deleteUser

Nested Resources

When resources have relationships, nest them logically:

GET /users/42/orders           → Orders belonging to user 42
GET /users/42/orders/7         → Order 7 of user 42
POST /users/42/orders          → Create an order for user 42

Query Parameters for Filtering

Use query parameters for filtering, sorting, and pagination — not for identifying resources:

GET /users?role=admin          → Filter users by role
GET /users?sort=name&order=asc → Sort users by name
GET /users?page=2&limit=20     → Paginate results
GET /orders?status=pending&from=2025-01-01  → Combined filters

REST Maturity Model (Richardson)

Leonard Richardson defined a maturity model that classifies APIs by how well they implement REST principles. This is useful for evaluating APIs you test.

Level 0: The Swamp of POX

Single endpoint, single HTTP method (usually POST), actions encoded in the request body. Essentially RPC over HTTP.

POST /api
Body: { "action": "getUser", "userId": 42 }

Level 1: Resources

Different URLs for different resources, but still using a single HTTP method.

POST /users/42
Body: { "action": "get" }

Level 2: HTTP Methods

Proper use of HTTP methods (GET, POST, PUT, DELETE) with resource-based URLs. Most APIs that claim to be RESTful are at this level.

GET    /users/42
POST   /users
PUT    /users/42
DELETE /users/42

Level 3: HATEOAS (Hypermedia Controls)

Responses include links to related actions and resources. This is the highest level of REST maturity and is rarely fully implemented.

{
  "id": 42,
  "name": "Alice",
  "links": [
    { "rel": "self", "href": "/users/42" },
    { "rel": "orders", "href": "/users/42/orders" },
    { "rel": "update", "href": "/users/42", "method": "PUT" },
    { "rel": "delete", "href": "/users/42", "method": "DELETE" }
  ]
}

Testing REST Compliance

When testing an API, evaluate its adherence to REST principles with this checklist:

URL Structure Tests

  • URLs use nouns (resources), not verbs (actions)
  • Resources are plural (/users, not /user)
  • Nested resources reflect real relationships
  • Query parameters are used for filtering, not resource identification
  • URLs are lowercase and use hyphens for readability (/order-items, not /orderItems)

HTTP Method Tests

  • GET requests never modify data
  • POST creates new resources and returns 201
  • PUT replaces the entire resource
  • PATCH partially updates a resource
  • DELETE removes a resource and returns 204 or 200

Statelessness Tests

  • Requests work without prior session setup
  • Authentication is sent with each request (not stored server-side)
  • Sending the same request twice produces the same result (idempotency for GET, PUT, DELETE)

Response Format Tests

  • Content-Type header matches the actual response format
  • JSON responses follow consistent structure
  • Error responses include meaningful messages and proper status codes
  • Collection responses include pagination metadata

Common REST Anti-Patterns

Knowing what to look for when testing:

Anti-PatternExampleShould Be
Verbs in URLsPOST /createUserPOST /users
Tunneling through POSTPOST /api?action=delete&id=42DELETE /api/resources/42
Ignoring status codesAlways returning 200Using 201, 204, 400, 404, etc.
Session-based stateRequiring login endpoint firstToken in Authorization header
Inconsistent naming/users/42 but /getOrdersConsistent noun-based URLs

Hands-On Exercise

Analyze these three public APIs for REST compliance:

  1. JSONPlaceholder (https://jsonplaceholder.typicode.com)

    • Send GET /posts, GET /posts/1, POST /posts, PUT /posts/1, DELETE /posts/1
    • Rate its REST maturity level (0-3)
  2. GitHub API (https://api.github.com)

    • Examine the response from GET / — does it include HATEOAS links?
    • Check /repos/{owner}/{repo}/issues for proper resource nesting
  3. Create a REST compliance report covering: URL conventions, HTTP method usage, response codes, statelessness, and HATEOAS presence

Key Takeaways

  • REST is an architectural style with six constraints: client-server, stateless, cacheable, uniform interface, layered system, and code on demand
  • RESTful URLs use nouns (resources) rather than verbs (actions) and follow consistent patterns
  • The Richardson Maturity Model classifies APIs from Level 0 (RPC-style) to Level 3 (full HATEOAS)
  • Most production APIs operate at Level 2 — proper resources and HTTP methods
  • Testing REST compliance helps identify design issues, inconsistencies, and potential bugs early