Master the principles, HTTP semantics, and real-world implementation of RESTful APIs in modern full-stack engineering. Learn how to design clean resource-oriented endpoints, leverage standardized status codes, execute stateful requests in an interactive API playground, and seamlessly bridge frontend UI interactions with database persistence.
An API (Application Programming Interface) is a defined contract that allows two separate software systems to exchange data. A REST API (Representational State Transfer) is an architectural style designed around resources and standard HTTP protocol semantics.
The client (e.g. React browser app or mobile client) manages the user interface and user interactions. The server (e.g. Node.js Express) manages business logic, authorization, and database persistence. They operate independently, communicating solely via HTTP requests and responses.
Each request from client to server must contain all the necessary information to understand and complete the request. The server never stores conversational session state between requests, allowing backends to scale horizontally across multiple instances effortlessly.
❌ RPC / Action-Heavy Anti-Pattern (URLs contain verbs): POST /api/createTask GET /api/getTasks GET /api/getTaskById?id=42 POST /api/updateTaskTitle POST /api/deleteTask ✅ RESTful Resource-Oriented Design (Clean plural nouns + HTTP verbs): GET /api/tasks -> Retrieve tasks collection GET /api/tasks/42 -> Retrieve specific task #42 POST /api/tasks -> Create a new task in the collection PATCH /api/tasks/42 -> Partially modify task #42 DELETE /api/tasks/42 -> Remove task #42
By relying on standard HTTP methods to express the action, REST URLs remain clean, predictable, and strictly noun-focused (/api/tasks).
Throughout this entire module, we model a standard production resource: Tasks (id, title, completed). Here is the complete REST interface:
| Method | Endpoint | Purpose / Semantic Meaning | Expected Status |
|---|---|---|---|
| GET | /api/tasks | Retrieve a collection of tasks (supports query filtering) | 200 OK |
| GET | /api/tasks/:id | Retrieve a single task representation by unique identifier | 200 OK / 404 Not Found |
| POST | /api/tasks | Submit data to create a new subordinate task in the collection | 201 Created |
| PATCH | /api/tasks/:id | Apply partial modifications to targeted fields of task :id | 200 OK / 404 Not Found |
| DELETE | /api/tasks/:id | Permanently remove task :id from the database | 204 No Content / 404 Not Found |
{ "completed": true }). The remaining fields stay untouched.Every communication between a frontend application and a REST backend consists of an explicit request and an explicit response:
POST /api/tasks HTTP/1.1
Host: api.example.com
User-Agent: Mozilla/5.0
Content-Type: application/json
Accept: application/json
{
"title": "Learn REST APIs",
"completed": false
}HTTP/1.1 201 Created
Content-Type: application/json; charset=utf-8
Location: /api/tasks/42
{
"id": 42,
"title": "Learn REST APIs",
"completed": false
}HTTP transmits raw text streams. The Content-Type: application/json request header tells server-side body parsers (e.g. express.json() in Node.js) to deserialize the raw string into a native JavaScript object at req.body. If this header is omitted, req.body will be undefined!
Status codes are standardized 3-digit numbers that immediately communicate the outcome of an operation to the client. Rather than memorizing an abstract list, learn them through real full-stack scenarios:
Standard success for GET requests returning data or PATCH updates returning modified entities.
Returned when POST /api/tasks successfully persists a new task into the database.
Returned when DELETE /api/tasks/42 succeeds. The server has no payload to return, and client bodies are omitted.
The client sent malformed syntax, such as invalid JSON syntax or unparseable query parameters.
Authentication is required (e.g. missing or expired JWT bearer token in Authorization header).
The client is authenticated, but does not possess permission to modify or access this specific task.
The requested endpoint or resource identifier (e.g. GET /api/tasks/999) does not exist.
The request conflicts with current server state (e.g. attempting to register an email or slug that already exists).
RFC 9110 standard: JSON syntax is valid, but the data fails business validation (e.g. empty task title).
An unexpected runtime exception occurred on the backend (e.g. database connection dropped).
Test real REST requests against an interactive, stateful tasks database. Modify the HTTP method, endpoint, headers, and JSON body to observe how the backend processes your requests and mutates the database:
[
{
"id": 1,
"title": "Configure PostgreSQL database",
"completed": true
},
{
"id": 2,
"title": "Build REST API endpoints",
"completed": false
},
{
"id": 3,
"title": "Connect React frontend fetch",
"completed": false
}
]| id | title | completed |
|---|---|---|
1 | Configure PostgreSQL database | TRUE |
2 | Build REST API endpoints | FALSE |
3 | Connect React frontend fetch | FALSE |
Understand how frontend UI events seamlessly propagate through HTTP into backend controllers and SQL queries:
async function handleAddTask(title) {
const response = await fetch('/api/tasks', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ title, completed: false })
});
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.error || 'Failed to create task');
}
const createdTask = await response.json();
setTasks((prev) => [...prev, createdTask]); // UI updates immediately!
}app.post('/api/tasks', async (req, res) => {
const { title, completed } = req.body;
// 1. Semantic Input Validation
if (!title || title.trim() === '') {
return res.status(422).json({ error: 'Title is required' });
}
// 2. Database Operation
const query = 'INSERT INTO tasks (title, completed) VALUES ($1, $2) RETURNING *;';
const result = await db.query(query, [title.trim(), Boolean(completed)]);
// 3. Return Standardized 201 Created Status + Serialized Entity
res.status(201).json(result.rows[0]);
});Diagnose real-world API defects encountered in production web applications:
FRONTEND: fetch('/api/tasks', { method: 'POST', body: JSON.stringify({ title: 'Deploy App' }) })
BACKEND LOG: TypeError: Cannot read properties of undefined (reading 'title')
SERVER STATUS: 500 Internal Server ErrorWhy is req.body undefined on the backend server?
CLIENT REQUEST: PATCH /api/tasks/9999
CLIENT BODY: { "completed": true }
SERVER LOG: UPDATE tasks SET completed = true WHERE id = 9999 (0 rows affected)
SERVER RESPONSE: 200 OK -> { "message": "Updated successfully" }What REST violation occurred in this API handler?
PAYLOAD:
{
"title": "Study HTTP Protocols",
"completed": false,
}
SERVER RESPONSE: 400 Bad Request
ERROR: SyntaxError: Unexpected token } in JSON at position 52Why did the API reject this request?
CLIENT REQUEST: POST /api/tasks
BODY: { "title": "" }
SERVER CODE: if (!title) return res.status(400).json({ error: "Title required" });Under RFC 9110, which status code more accurately communicates this business validation failure?
Design and validate a production-ready REST interface for a notes resource (id, title, content, pinned):