REST (Representational State Transfer) is an architectural style for distributed hypermedia systems first introduced in Roy Fielding’s 2000 doctoral dissertation “Architectural Styles and the Design of Network-based Software Architectures” at UC Irvine. Fielding, one of the principal authors of the HTTP protocol, analyzed the success factors of the web and systematized them into architectural principles. REST has become the de facto standard for modern web API design and is widely used for communication between various distributed systems including microservice architectures, mobile applications, and Single Page Applications (SPAs).

What is REST?

REST (Representational State Transfer) is a network-based software architectural style that identifies resources via URIs and transfers state through HTTP methods. “Representational” refers to resource representations (JSON, XML, etc.), while “State Transfer” refers to the transfer of resource state between client and server.

History and Background of REST

Evolution of Web Services

Before REST emerged, web services primarily used SOAP (Simple Object Access Protocol) and XML-RPC. These protocols required complex XML-based message formats, strict type systems, and service definitions through WSDL (Web Services Description Language), making implementation and maintenance difficult. SOAP had advantages in enterprise environments, supporting transactions, security, and message reliability, but had overhead of using complex XML envelopes even for simple data queries.

Roy Fielding’s Contribution

Roy Fielding was a principal author of the HTTP/1.0 and HTTP/1.1 specifications and co-founder of the Apache HTTP Server project, possessing deep understanding of web architecture. In his doctoral dissertation, he analyzed why the web succeeded and systematized these findings into the architectural style called REST. REST was designed to maximally leverage existing web infrastructure (HTTP, URI, caches, proxies) while building simple and scalable systems.

Spread of REST APIs

REST began to be widely adopted from the mid-2000s. When Flickr (2004), Amazon Web Services (2006), and Twitter (2006) released REST APIs, it became the standard for web APIs. Along with the rise of JSON format, REST became an attractive alternative for developers wanting to avoid SOAP’s complexity, and its popularity grew further with the emergence of Ajax and mobile apps.

The 6 Constraints of REST

REST is an architectural style, not a specific protocol or technology. Systems that follow these 6 constraints are considered RESTful.

1. Client-Server

A constraint that separates concerns between clients and servers, enabling independent evolution. Servers handle data storage and business logic while clients handle user interfaces, allowing each to be developed, deployed, and scaled independently.

Benefits of Separation of Concerns

Client-server separation improves scalability through server simplification, enables various clients (web, mobile, IoT) to use the same server API, and allows independent evolution of each component.

2. Stateless

A constraint where each request is independent and servers must not store client session state. All information needed for a request (authentication tokens, context data) must be included in the request itself.

GET /api/users/me HTTP/1.1
Host: api.example.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Accept: application/json

Advantages of Statelessness:

  • Scalability: Horizontal scaling is easy since servers don’t maintain sessions
  • Reliability: Other servers can handle requests during server failures
  • Simplicity: Server implementation becomes simpler and resource efficiency improves

Disadvantages of Statelessness:

  • Request size increases as authentication information must be included with every request
  • Client-side state management responsibility increases

3. Cacheable

Responses must explicitly indicate whether they are cacheable. Cacheable responses can be reused by clients or intermediate caches (CDN, proxies), reducing server load and shortening response times.

HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: max-age=3600, must-revalidate
ETag: "a1b2c3d4e5f6"
Last-Modified: Sat, 20 Jul 2024 10:00:00 GMT

{"id": 123, "name": "John Doe", "email": "[email protected]"}

Cache-Related Headers:

HeaderDescriptionExample
Cache-ControlSpecifies caching policymax-age=3600, private
ETagResource version identifier"a1b2c3d4e5f6"
Last-ModifiedLast modification timeSat, 20 Jul 2024 10:00:00 GMT
ExpiresCache expiration time (legacy)Sun, 21 Jul 2024 10:00:00 GMT

4. Layered System

A constraint where clients only need to know about the immediately adjacent layer and need not know the system structure beyond it. Adding intermediate layers like API Gateway, load balancers, cache servers, and CDN can improve system scalability, security, and performance.

[Client] → [CDN] → [Load Balancer] → [API Gateway] → [Microservices]

Benefits of Layering:

  • Security: Place firewalls, authentication servers in intermediate layers
  • Scalability: Horizontal scaling through load balancers
  • Performance: Shortened response time through CDN and cache servers
  • Flexibility: Internal structure can change without affecting clients

5. Uniform Interface

REST’s most important constraint that simplifies system architecture through consistent interfaces and reduces coupling between client and server.

4 Elements of Uniform Interface

  1. Resource Identification: Uniquely identify resources through URIs
  2. Resource Manipulation Through Representations: Transfer resource state through representations like JSON, XML
  3. Self-Descriptive Messages: Messages contain information about how to process them
  4. HATEOAS: Responses include hyperlinks to possible next actions

6. Code on Demand (Optional)

An optional constraint where servers can transfer executable code (JavaScript, etc.) to clients to dynamically extend client functionality. Web browsers downloading and executing JavaScript is a typical example. This is REST’s only optional constraint.

Richardson Maturity Model

Leonard Richardson presented a model classifying REST API maturity into 4 levels at the 2008 QCon conference. This model is widely used as a criterion for evaluating how RESTful an API is.

LevelNameCharacteristicsExample
Level 0The Swamp of POXSingle URI, single HTTP method (mainly POST)SOAP, XML-RPC
Level 1ResourcesURIs assigned to individual resources, single methodAll operations POST to /users/123
Level 2HTTP VerbsProper use of HTTP methods and status codesDistinguishing GET, POST, PUT, DELETE
Level 3Hypermedia ControlsHATEOAS implementation, links in responsesRelated resource links in _links field

RESTful API vs REST-like API

RESTful API means an API that fully complies with all REST constraints including HATEOAS, while REST-like API means an API that uses HTTP methods and resource-based URLs but doesn’t comply with some constraints like HATEOAS. In reality, most APIs are REST-like APIs at Richardson Maturity Model Level 2, and implementing complete RESTful APIs at Level 3 is rare.

REST API Design Principles

1. Resource-Centric URL Design

REST API URLs should represent resources, not actions. Use nouns and prefer plurals.

Good Examples:

GET    /users              # List users
GET    /users/123          # Get specific user
POST   /users              # Create new user
PUT    /users/123          # Update entire user info
PATCH  /users/123          # Partial user info update
DELETE /users/123          # Delete user

Bad Examples:

GET    /getUsers
POST   /createUser
POST   /deleteUser?id=123
GET    /user/123/get

Hierarchical Resource Representation:

GET /users/123/posts                    # User 123's post list
GET /users/123/posts/456               # User 123's post 456
GET /users/123/posts/456/comments      # Post 456's comment list

URL Design Rules:

  • Use lowercase
  • Use hyphens (-) for word separation (avoid underscores)
  • Don’t include file extensions
  • Don’t include trailing slashes (/)
  • Avoid nesting more than 3 levels

2. Proper Use of HTTP Methods

Each HTTP method has unique semantics. Understand and properly use safe and idempotent properties.

MethodPurposeSafeIdempotentRequest BodyResponse Body
GETRetrieve resourcesOOXO
POSTCreate resourcesXXOO
PUTUpdate entire resourceXOOO
PATCHPartial resource updateXXOO
DELETEDelete resourcesXOXX/O
HEADRetrieve headers onlyOOXX
OPTIONSQuery supported methodsOOXO

Safety and Idempotency

Safe: Requests don’t change server state (GET, HEAD, OPTIONS) Idempotent: Same result when executing the same request multiple times (GET, PUT, DELETE)

3. Proper Use of HTTP Status Codes

Clearly communicate request processing results through HTTP status codes.

Success Responses (2xx):

CodeMeaningUse Case
200 OKSuccessGET, PUT, PATCH success
201 CreatedCreation successResource created via POST (Location header required)
204 No ContentSuccess, no bodyDELETE success, PUT update only
206 Partial ContentPartial contentRange request processing

Client Errors (4xx):

CodeMeaningUse Case
400 Bad RequestInvalid requestRequest syntax error, invalid data
401 UnauthorizedAuthentication neededMissing or invalid credentials
403 ForbiddenNo permissionAuthenticated but insufficient permissions
404 Not FoundResource not foundNon-existent resource
409 ConflictConflictResource state conflict
422 Unprocessable EntityCannot processSyntax correct, semantic error
429 Too Many RequestsLimit exceededRate limiting

Server Errors (5xx):

CodeMeaningUse Case
500 Internal Server ErrorServer errorUnexpected server error
502 Bad GatewayGateway errorUpstream server response error
503 Service UnavailableService unavailableServer overload, maintenance
504 Gateway TimeoutGateway timeoutUpstream response timeout

4. Versioning Strategies

APIs may change over time, so versioning strategies are needed to add new features while maintaining backward compatibility.

URL Path Versioning:

GET /api/v1/users
GET /api/v2/users

Pros: Clear, intuitive, easy browser testing, simple caching Cons: URLs get longer, REST principle debate (URIs should identify resources)

Header Versioning:

GET /api/users HTTP/1.1
Accept: application/vnd.myapp.v1+json

Pros: Clean URLs, aligns with REST principles, uses content negotiation Cons: Difficult browser testing, complex caching configuration

Query Parameter Versioning:

GET /api/users?version=1

Pros: Simple implementation, easy browser testing Cons: Version may appear optional, complex caching

Practical Recommendation: URL path versioning is most widely used and adopted by most major APIs (Google, Facebook, Twitter).

5. Pagination Strategies

When returning large amounts of data, limit response size through pagination.

Offset-Based Pagination:

GET /api/users?page=2&per_page=20
GET /api/users?offset=20&limit=20

Cursor-Based Pagination:

GET /api/users?cursor=eyJpZCI6MTAwfQ==&limit=20
MethodProsConsSuitable For
Offset-basedSimple implementation, can jump to specific pagesPerformance degradation with large data, duplicates/omissions on data changesSmall datasets, page numbers needed
Cursor-basedConsistent performance with large data, stable with real-time dataCannot jump to specific pages, complex implementationLarge datasets, infinite scroll, real-time feeds

Pagination Response Example:

{
  "data": [...],
  "pagination": {
    "total": 1000,
    "page": 2,
    "per_page": 20,
    "total_pages": 50,
    "next_cursor": "eyJpZCI6MTIwfQ=="
  },
  "_links": {
    "self": "/api/users?page=2",
    "next": "/api/users?page=3",
    "prev": "/api/users?page=1",
    "first": "/api/users?page=1",
    "last": "/api/users?page=50"
  }
}

6. Filtering, Sorting, and Searching

Provide filtering, sorting, and search functionality through query parameters.

Filtering:

GET /api/users?status=active&role=admin
GET /api/posts?created_after=2024-01-01&tag=javascript

Sorting:

GET /api/users?sort=created_at           # Ascending
GET /api/users?sort=-created_at          # Descending (- prefix)
GET /api/users?sort=name,-created_at     # Multiple sorts

Searching:

GET /api/users?q=john
GET /api/posts?search=REST+API

Field Selection (Sparse Fieldsets):

GET /api/users?fields=id,name,email
GET /api/posts?fields[posts]=title,content&fields[author]=name

7. HATEOAS (Hypermedia as the Engine of Application State)

A core REST principle that includes links to related resources in responses, enabling clients to discover possible next actions.

{
  "id": 123,
  "name": "John Doe",
  "email": "[email protected]",
  "status": "active",
  "_links": {
    "self": {"href": "/api/users/123"},
    "posts": {"href": "/api/users/123/posts"},
    "deactivate": {"href": "/api/users/123/deactivate", "method": "POST"},
    "delete": {"href": "/api/users/123", "method": "DELETE"}
  }
}

Benefits of HATEOAS

Since clients follow response links rather than hardcoded URLs, servers can change URL structures without modifying clients. However, implementation complexity increases and most clients don’t utilize this, so it’s optionally implemented in practice.

8. Error Handling

Use consistent error response formats to improve developer experience.

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Request validation failed",
    "details": [
      {
        "field": "email",
        "message": "Invalid email format",
        "code": "INVALID_FORMAT"
      },
      {
        "field": "age",
        "message": "Age must be positive",
        "code": "INVALID_VALUE"
      }
    ],
    "timestamp": "2024-07-20T16:23:17Z",
    "path": "/api/users",
    "request_id": "req_abc123"
  }
}

Error Response Fields:

  • code: Error code for programmatic handling
  • message: Human-readable error description
  • details: Field-level detailed error information
  • request_id: Unique identifier for log tracing

Security Considerations

Authentication Methods

MethodCharacteristicsSuitable For
API KeySimple, included in request header or queryServer-to-server, internal systems
Basic AuthUsername:password Base64 encodedSimple auth, HTTPS required
Bearer Token (JWT)Stateless, self-contained tokenGeneral user authentication
OAuth 2.0Delegated authorizationThird-party app integration, social login

Rate Limiting

Set request limits to prevent API abuse and protect server resources.

HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1721484600
Retry-After: 3600
Content-Type: application/json

{
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Request limit exceeded. Please try again in 1 hour."
  }
}

Rate Limiting Algorithms:

  • Token Bucket: Allows burst traffic, complex implementation
  • Sliding Window: Accurate limiting, uses Redis
  • Fixed Window: Simple implementation, possible bursts at boundaries

CORS (Cross-Origin Resource Sharing)

Configure CORS headers to allow API access from different domains.

Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Max-Age: 86400

API Documentation

OpenAPI (Swagger)

OpenAPI Specification is the industry standard for defining REST APIs. It describes APIs in YAML or JSON format and can provide interactive documentation through Swagger UI.

openapi: 3.0.0
info:
  title: User API
  version: 1.0.0
paths:
  /users:
    get:
      summary: List users
      parameters:
        - name: page
          in: query
          schema:
            type: integer
            default: 1
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/User'

Documentation Tool Selection:

  • Public APIs: OpenAPI/Swagger (standard, rich tool ecosystem)
  • Internal APIs: Postman Collections (easy team collaboration)
  • Quick Prototyping: API Blueprint (Markdown-based)

Limitations and Alternatives to REST

REST is a versatile and widely adopted architectural style, but it’s not optimal for every situation.

TechnologyProsConsSuitable For
RESTSimple, standardized, easy cachingOver-fetching, multiple requests neededGeneral CRUD, public APIs
GraphQLPrecise data requests, single endpointComplex caching, learning curveComplex data requirements, mobile apps
gRPCHigh performance, strong typing, bidirectional streamingLimited browser support, difficult debuggingInter-microservice communication
WebSocketReal-time bidirectional communication, low latencyNot stateless, complex load balancingChat, real-time notifications, games

Conclusion

REST API design is a complex process that must consider not just technical decisions but also user experience and business requirements. Understanding REST’s 6 constraints and referencing the Richardson Maturity Model is important, but rather than blindly following them, it’s crucial to understand the trade-offs of each design decision and apply them flexibly according to project characteristics. Targeting practical and consistent REST-like APIs (Level 2) while emphasizing thorough documentation and developer experience is the key to successful API design, rather than implementing perfect RESTful APIs (Level 3).

References