When you open a weather app on your phone, the app does not contain weather data. It asks for it — from a server somewhere else that has current conditions for your location. When you post a photo on a social platform, the photo does not travel directly from your device to every follower's screen. It goes to a server, which stores it and makes it available. When an e-commerce site checks your card and confirms an order, it is communicating with a payment processor's system in real time.
All of this cross-system communication has to happen in a structured way. Systems developed by different companies, in different programming languages, running on different hardware, need a common language for asking and answering questions about data.
For most of the web's history, that common language has been REST — Representational State Transfer. It is not a protocol, a tool, or a standard in the formal sense. It is an architectural style: a set of constraints for how systems should be designed to communicate over HTTP. Understanding REST means understanding how the modern web actually works.
The Origins: Roy Fielding's Dissertation
REST was defined in 2000 by Roy Fielding in his doctoral dissertation at UC Irvine, titled "Architectural Styles and the Design of Network-based Software Architectures." Fielding was not working in the abstract — he was one of the principal authors of the HTTP/1.1 specification and was trying to articulate the architectural principles that had made the World Wide Web scale so successfully.
Fielding's insight was that the web worked as well as it did because of specific constraints: the way HTTP worked, the way URLs identified resources, the way responses could be cached. He formalized these as a set of architectural principles that, if applied consistently, would produce systems with the same desirable properties — scalability, simplicity, loose coupling, visibility.
Those principles became REST, and they have since been applied to build the APIs that power almost every digital product and service.
The Six REST Constraints
Fielding defined six constraints that characterize a REST architecture. Not all REST-style APIs implement all of them perfectly, but understanding them clarifies what REST is trying to achieve and why.
1. Client-Server Architecture
The client (a browser, mobile app, or other API consumer) and the server (which stores and manages data) are separated. The client is responsible for the user interface; the server is responsible for data storage and business logic. Neither knows the implementation details of the other.
This separation allows each to evolve independently. A mobile app can be updated without changing the server; the server can be refactored without changing the client, as long as the interface between them remains consistent.
2. Statelessness
Statelessness is the most operationally significant REST constraint. It means that each request from a client to a server must contain all of the information the server needs to process it. The server does not store any client context between requests.
No session state. No "remember who I am from the last request." If authentication is required, the credentials or token must be sent with every request. If context is needed, it must be sent in the request.
Statelessness makes REST APIs dramatically easier to scale. Because no server needs to remember which client it has been talking to, any server instance can handle any request. Add more servers, and you can handle more requests — no shared session storage or complex state synchronization required.
3. Cacheability
Responses should explicitly indicate whether they can be cached. Cached responses reduce server load and latency. HTTP already has rich caching semantics (Cache-Control, ETag, Last-Modified headers), and REST leverages these fully.
A GET request for a product's details might be cached for 60 minutes; a POST request to create an order should never be cached. Proper cache control headers communicate this to clients and any intermediary caches between them.
4. Uniform Interface
The uniform interface is what makes REST recognizable and interoperable. It means that all REST APIs follow the same conventions for identifying and manipulating resources:
- Resource identification: every resource is identified by a URL (Uniform Resource Locator)
- Resource manipulation through representations: clients interact with resources through representations (typically JSON or XML) and include enough information to modify or delete the resource
- Self-descriptive messages: each message includes enough information to describe how to process it
- Hypermedia as the engine of application state (HATEOAS): responses can include links to related resources and available actions (this constraint is the most rarely implemented in practice)
5. Layered System
A client cannot tell whether it is connected directly to the server or through an intermediary (a load balancer, a cache, a gateway, a security proxy). This allows intermediaries to be inserted and removed without affecting the client.
CDNs, API gateways, and load balancers all operate as intermediaries in this sense. The client sends its request; it reaches a server; it does not need to know how many layers it passed through.
6. Code on Demand (Optional)
Servers can extend client functionality by sending executable code (like JavaScript) that the client runs. This is the only optional constraint. In practice, it applies mainly to web browsers (which receive and execute JavaScript) rather than typical API clients.
Resources and URLs: The Nouns of REST
In REST, everything is a resource: a user, an order, a product, a message, an article. Resources are the nouns of the API. They are identified by URLs.
Good REST URL design follows conventions that make APIs intuitive:
GET /articles → list all articles
GET /articles/42 → get article with ID 42
POST /articles → create a new article
PUT /articles/42 → replace article 42 entirely
PATCH /articles/42 → partially update article 42
DELETE /articles/42 → delete article 42
Resources can be nested to express relationships:
GET /users/7/orders → all orders for user 7
GET /users/7/orders/12 → order 12 belonging to user 7
The URL identifies what the resource is. The HTTP method identifies what to do with it.
HTTP Methods: The Verbs of REST
| Method | Purpose | Safe | Idempotent |
|---|---|---|---|
| GET | Retrieve a resource | Yes | Yes |
| POST | Create a new resource | No | No |
| PUT | Replace a resource entirely | No | Yes |
| PATCH | Partially update a resource | No | No* |
| DELETE | Remove a resource | No | Yes |
| HEAD | Retrieve headers only (no body) | Yes | Yes |
| OPTIONS | List allowed methods for a resource | Yes | Yes |
Safe means the operation does not modify the resource. Idempotent means calling it multiple times has the same effect as calling it once. These properties matter for caching and retry logic: safe methods can be cached; idempotent methods can be retried on network failure without risk of creating duplicate records.
The GET/POST/PUT/DELETE pattern maps roughly to the classic database CRUD operations (Create, Read, Update, Delete), though the correspondence is not exact.
HTTP Status Codes: How Servers Respond
REST uses standard HTTP status codes to communicate what happened. A well-designed API uses these codes precisely rather than returning 200 OK for every response (including errors).
| Code | Meaning | Common Use |
|---|---|---|
| 200 OK | Success | Successful GET, PUT, PATCH |
| 201 Created | Resource created | Successful POST |
| 204 No Content | Success, no body | Successful DELETE |
| 400 Bad Request | Client error in request | Invalid parameters |
| 401 Unauthorized | Authentication required | Missing or invalid token |
| 403 Forbidden | Authenticated but not permitted | Insufficient permissions |
| 404 Not Found | Resource does not exist | Wrong ID or URL |
| 409 Conflict | Resource conflict | Duplicate unique field |
| 422 Unprocessable Entity | Validation failed | Missing required fields |
| 429 Too Many Requests | Rate limited | Client is sending too fast |
| 500 Internal Server Error | Server error | Something went wrong server-side |
| 503 Service Unavailable | Server temporarily unavailable | Maintenance or overload |
Status codes allow clients to handle different response types programmatically without parsing the response body. A client that receives a 401 knows to re-authenticate; a client that receives a 429 knows to slow down.
Authentication in REST APIs
Because REST is stateless, authentication credentials must be sent with every request. The most common patterns are:
API Keys
The simplest approach: a secret string sent in a request header. Used for server-to-server communication and developer tool access where the client is trusted.
Authorization: ApiKey your-api-key-here
Bearer Tokens (JWT)
JSON Web Tokens (JWT) are signed tokens that encode claims about the user (who they are, what they can do, when the token expires). The server validates the signature without needing to consult a database, making JWT authentication scalable.
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
OAuth 2.0
The industry standard for delegated authorization — allowing a third-party application to access resources on a user's behalf without receiving their password. OAuth 2.0 issues access tokens with defined scopes and expiration times. It is the mechanism behind "Sign in with Google" and "Connect with GitHub."
JSON: The Default Language
While REST does not mandate any particular data format, JSON (JavaScript Object Notation) has become the overwhelming standard. It is lightweight, human-readable, and natively supported in virtually every programming language.
A REST response for a single article might look like:
{
"id": 42,
"title": "What Is REST API",
"author": {
"id": 7,
"name": "Jane Smith"
},
"published_at": "2024-03-15T10:30:00Z",
"tags": ["api", "web development", "programming"]
}
JSON replaced XML as the preferred format for web APIs because it is more compact, less verbose, and maps naturally to data structures in most programming languages. XML remains in use in some enterprise and legacy contexts.
REST vs. GraphQL vs. gRPC
REST is dominant but not universal. Two alternatives have gained significant adoption for specific use cases.
GraphQL
Developed by Facebook and released publicly in 2015, GraphQL is a query language for APIs where clients specify exactly what data they need.
Where REST requires you to consume whatever data structure the server defines for each endpoint, GraphQL lets the client say: "Give me the user's name and their last five orders, including each order's total and status, but not the full order details."
GraphQL solves two specific REST problems:
- Over-fetching: getting more data than needed (downloading a full user object when you only need their name)
- Under-fetching: needing multiple requests to get related data (fetching a user, then fetching their orders in a separate request)
The trade-offs: GraphQL has a steeper learning curve, more complex server implementation, less straightforward caching (because queries are POST requests, not GETs), and less universal tooling. For simple, stable data structures, REST is typically simpler. For complex, interconnected data or highly variable client needs, GraphQL can be significantly more efficient.
gRPC
gRPC (Google Remote Procedure Call) uses Protocol Buffers — a binary serialization format — rather than JSON, and HTTP/2 rather than HTTP/1.1. It is significantly faster and more efficient than REST for high-volume, low-latency communication, particularly between internal microservices.
gRPC is not human-readable (binary format requires tooling to inspect) and requires clients and servers to share the schema definition file. It is the right choice for internal service-to-service communication where performance is critical; REST remains the standard for public-facing APIs.
| Feature | REST | GraphQL | gRPC |
|---|---|---|---|
| Protocol | HTTP/1.1 | HTTP/1.1 | HTTP/2 |
| Format | JSON (typical) | JSON | Protocol Buffers |
| Client flexibility | Low | High | Low |
| Caching | Easy (HTTP caching) | Complex | Requires custom implementation |
| Browser support | Native | Native | Requires proxy |
| Learning curve | Low | Medium | High |
| Best for | Public APIs, simple CRUD | Complex data, flexible clients | Internal services, performance-critical |
What Makes a REST API "Good"
A technically RESTful API can still be frustrating to use if it violates common conventions. Signs of a well-designed REST API:
- Consistent naming: plural nouns for collections (
/articles, not/articleor/getArticles) - Meaningful status codes: errors return appropriate 4xx/5xx codes with useful error messages
- Versioning: major breaking changes are introduced through versioned URLs (
/v1/articles) to avoid breaking existing clients - Pagination: list endpoints return paginated results with metadata about total count and next page
- Filtering and sorting: list endpoints support query parameters for filtering (
?status=published) and sorting (?sort=created_at&order=desc) - Documentation: Swagger/OpenAPI specification documents endpoints, parameters, and response schemas
"A REST API is a product. Its users are developers. Good API design means those developers can figure out how to use it without reading the source code."
Key Takeaways
- REST is an architectural style — a set of constraints — not a protocol or specification; it was defined by Roy Fielding in his 2000 dissertation
- The six REST constraints are client-server separation, statelessness, cacheability, uniform interface, layered system, and optional code on demand
- Statelessness is the most operationally significant constraint: every request is self-contained, enabling horizontal scaling
- HTTP methods map to operations on resources: GET retrieves, POST creates, PUT replaces, PATCH partially updates, DELETE removes
- HTTP status codes communicate outcomes precisely and should be used correctly rather than defaulting to 200 for everything
- Authentication in REST is typically handled via API keys, JWT bearer tokens, or OAuth 2.0
- GraphQL solves over-fetching and under-fetching problems for complex data needs; gRPC is faster for internal service communication where performance is critical
Frequently Asked Questions
What is a REST API?
A REST API (Representational State Transfer Application Programming Interface) is a way for software systems to communicate with each other over HTTP using a set of architectural constraints defined by Roy Fielding in his 2000 doctoral dissertation. It uses standard HTTP methods (GET, POST, PUT, DELETE) to perform operations on resources identified by URLs, and returns data — typically in JSON format — that represents the current state of those resources.
What are the six REST constraints?
Roy Fielding defined six architectural constraints that make a system RESTful: client-server architecture (separating UI concerns from data storage), statelessness (each request must contain all information needed to process it), cacheability (responses should indicate whether they can be cached), uniform interface (standardized resource identification and manipulation), layered system (clients cannot tell whether they are connected directly or through intermediaries), and optional code on demand (servers can extend client functionality by sending executable code).
What is the difference between GET, POST, PUT, and DELETE in REST?
These HTTP methods correspond to the four basic data operations. GET retrieves a resource without modifying it — it is safe and idempotent. POST creates a new resource; calling it multiple times creates multiple resources. PUT updates an existing resource by replacing it entirely; it is idempotent (calling it multiple times has the same effect as calling it once). DELETE removes a resource. PATCH, a related method, partially updates a resource rather than replacing it entirely.
What is statelessness in a REST API?
Statelessness means that each HTTP request must contain all the information the server needs to process it — the server does not store any session state between requests. Authentication credentials, context, and any other required information must be sent with every request. This makes REST APIs highly scalable because any server instance can handle any request without needing shared session storage.
What is the difference between REST and GraphQL?
REST uses multiple endpoints (one per resource type) where the server defines what data is returned. GraphQL uses a single endpoint where clients specify exactly what data they need using a query language. GraphQL eliminates over-fetching (getting more data than needed) and under-fetching (needing multiple requests to get related data). REST has simpler caching, broader tooling support, and lower learning curve. GraphQL is often preferred for complex, interconnected data or when clients have highly variable data needs.