REST (Representational State Transfer) is the architectural standard for modern web services. This guide explains what APIs are, the specific rules of REST, and how to implement them using FastAPI.
Index
- What is an API
- What is a REST API
- The Six Constraints of REST
- RESTful APIs and Partial Adherence
- HTTP Methods: Safety and Idempotency
- HTTP Status Codes
- Example Implementation with FastAPI
What is an API
An API (Application Programming Interface) is a software intermediary that allows two applications to talk to each other. Think of it as a waiter in a restaurant: you (the client) give an order (the request) to the waiter (the API), who takes it to the kitchen (the server) and brings back your food (the response).
API Concept Diagram
What is a REST API
REST (Representational State Transfer) is not a protocol or a tool, but a set of architectural constraints. When an API follows these constraints, it is called a RESTful API. It uses standard HTTP requests to perform CRUD (Create, Read, Update, Delete) operations on resources.
The Six Constraints of REST
To be truly RESTful, an API must follow these six rules:
-
Uniform Interface: This is the most critical constraint. It simplifies the architecture by requiring a consistent way to interact with the server. It consists of four sub-parts:
-
Resource Identification in Requests: Unique URIs (e.g.,
/items/1). - Resource Manipulation through Representations: When a client has a representation of a resource, it has enough information to modify or delete it.
-
Self-descriptive Messages: Each message includes enough information to describe how to process the message (e.g., Media types like
application/json). - HATEOAS (Hypermedia as the Engine of Application State): This is the most "advanced" part of REST. It means the server response should include links to other related actions the client can take. Just like you navigate a website by clicking links rather than typing URLs, a REST client should navigate an API using links provided in the response.
-
Resource Identification in Requests: Unique URIs (e.g.,
Client-Server: The client (front-end) and server (back-end) are independent. They can be developed and scaled separately as long as the interface remains the same.
Stateless: Each request from the client must contain all the information needed to understand and process the request. The server does not store any "session" context about the client between requests.
Cacheable: Responses must define themselves as cacheable or not to prevent clients from reusing stale or inappropriate data.
Layered System: A client cannot ordinarily tell whether it is connected directly to the end server or to an intermediary (like a load balancer or proxy).
Code on Demand (Optional): Servers can temporarily extend or customize the functionality of a client by transferring executable code (e.g., JavaScript).
RESTful APIs and Partial Adherence: The Richardson Maturity Model
APIs that follow all of these rules are called RESTful APIs. However, in the industry, there is a big difference between what is "commonly" called REST and what is "truly" REST. This is best explained by the Richardson Maturity Model:
- Level 0 (The Swamp of POX): Using HTTP as a transport for remote procedure calls (like SOAP). No URIs, no methods—just one endpoint.
-
Level 1 (Resources): Introducing individual URIs for different resources (e.g.,
/items,/users), but still using one method (usually POST). - Level 2 (HTTP Verbs & Status Codes): This is where most developers stop. They use proper methods (GET, POST, PUT, DELETE) and status codes (200, 201, 404). In common conversation, these are called RESTful, but technically they are only "Level 2 REST."
- Level 3 (Hypermedia Controls / HATEOAS): This is True REST. At this level, the API provides links to guide the client. An API is not truly RESTful (in the sense intended by Roy Fielding) unless it reaches Level 3.
Interview Tip: If asked why most APIs aren't "truly" RESTful, mention that most stop at Level 2. To reach Level 3, you need HATEOAS, which makes the API self-discoverable but adds complexity that many teams choose to avoid.
HTTP Methods: Safety and Idempotency
REST relies on the strict semantic rules of HTTP. Two key terms you must know for interviews are Safety and Idempotency.
1. Safety
An HTTP method is Safe if it does not change the state of the server. In other words, it is a "read-only" operation.
- GET and HEAD are safe.
- POST, PUT, and DELETE are NOT safe because they modify data.
-
Interview Tip: If you fetch data using
GETand it also deletes a record in your database, you have violated the Safety rule of REST.
2. Idempotency
An HTTP method is Idempotent if making the same request multiple times has the same effect as making it once.
- GET, PUT, and DELETE are idempotent. (Deleting an item once is the same as deleting it ten times—the item stays gone).
- POST is NOT idempotent. (Sending a POST "Create Order" request five times will result in five different orders).
HTTP Status Codes
In a RESTful API, the server uses HTTP Status Codes to inform the client about the result of a request. This is part of the Uniform Interface constraint (specifically, Self-descriptive Messages).
Common status codes you MUST use correctly:
2xx: Success
- 200 OK: The request was successful (Standard for GET, PUT).
- 201 Created: A new resource was successfully created (Standard for POST).
- 204 No Content: The request was successful, but there is no data to return (Common for DELETE).
3xx: Redirection
- 304 Not Modified: Used for caching; the resource hasn't changed since the last request.
4xx: Client Errors
- 400 Bad Request: The request was invalid or cannot be served.
- 401 Unauthorized: Authentication is required and has failed or hasn't been provided.
- 403 Forbidden: The client does not have access rights to the content.
- 404 Not Found: The server cannot find the requested resource.
- 405 Method Not Allowed: The request method is known by the server but has been disabled and cannot be used.
5xx: Server Errors
- 500 Internal Server Error: A generic error message when the server encounters an unexpected condition.
Example Implementation with FastAPI
FastAPI allows us to return "links" alongside our data to satisfy the HATEOAS requirement.
from fastapi import FastAPI, HTTPException, Request, status
from pydantic import BaseModel
from typing import List, Optional, Dict
app = FastAPI()
# Placeholder database
items_db = [
{"id": 1, "name": "Laptop", "description": "High-end gaming laptop"}
]
class ItemResponse(BaseModel):
id: int
name: str
links: Dict[str, str]
# 1. GET Request: Returns 200 OK by default
@app.get("/items/{item_id}", response_model=ItemResponse)
def get_item(item_id: int, request: Request):
item = next((i for i in items_db if i["id"] == item_id), None)
if item is None:
# Rule: Return 404 if resource doesn't exist
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Item not found")
base_url = str(request.base_url).rstrip("/")
return {
"id": item["id"],
"name": item["name"],
"links": {
"self": f"{base_url}/items/{item_id}",
"all_items": f"{base_url}/items"
}
}
# 2. POST Request: Explicitly returns 201 Created
@app.post("/items", status_code=status.HTTP_201_CREATED)
def create_item(name: str):
new_id = len(items_db) + 1
items_db.append({"id": new_id, "name": name})
return {"message": "Created successfully", "id": new_id}
# 3. DELETE Request: Returns 204 No Content
@app.delete("/items/{item_id}", status_code=status.HTTP_204_NO_CONTENT)
def delete_item(item_id: int):
global items_db
if not any(i["id"] == item_id for i in items_db):
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Item not found")
items_db = [i for i in items_db if i["id"] != item_id]
return None # 204 means no content is returned
FastAPI Swagger UI with HATEOAS
To run this:
- Install FastAPI:
pip install fastapi uvicorn - Save the code to
main.py. - Run:
uvicorn main:app --reload - Visit
http://127.0.0.1:8000/docsto see the RESTful interface.



Top comments (0)