
REST Fundamentals: Resources, Methods, and URL Design
Master the core principles of REST architecture. Learn how to think in resources, map HTTP methods to CRUD operations, and design clean, professional API endpoints.
REST Fundamentals: Resources, Methods, and URL Design
Now that you understand what APIs are and how HTTP works, it is time to learn the philosophy behind REST. REST is not just a technology; it is a way of thinking about how to organize and expose data over the web.
In this module, you will learn to think in resources, understand how HTTP methods map to data operations, and design clean URLs that any developer can understand at a glance. These skills will make you not just a consumer of APIs but someone who can evaluate and design them.
1. Thinking in Resources
The single most important concept in REST is the resource. Everything in a REST API is a resource.
What Is a Resource?
A resource is any noun — any thing, object, or entity — that your API manages. Resources are not actions; they are the things that actions are performed on.
| Domain | Resources |
|---|---|
| Social Media | Users, Posts, Comments, Likes, Followers |
| E-Commerce | Products, Orders, Customers, Reviews, Carts |
| Banking | Accounts, Transactions, Transfers, Statements |
| Healthcare | Patients, Appointments, Prescriptions, Doctors |
| Education | Students, Courses, Lessons, Grades, Enrollments |
Each resource gets its own URL (endpoint). The URL is the address of that resource on the internet.
Resources as URLs
In REST, resources are represented as URL paths. The convention is simple:
/users → The collection of all users
/users/42 → A specific user with ID 42
/users/42/posts → All posts belonging to user 42
This is hierarchical and intuitive. You can read it like a sentence: "Give me user 42's posts."
graph TD
A["/"] --> B["/users"]
B --> C["/users/42"]
C --> D["/users/42/posts"]
D --> E["/users/42/posts/7"]
C --> F["/users/42/orders"]
A --> G["/products"]
G --> H["/products/100"]
H --> I["/products/100/reviews"]
style A fill:#4f46e5,color:#fff
style B fill:#0891b2,color:#fff
style C fill:#0891b2,color:#fff
style G fill:#0891b2,color:#fff
The Golden Rule: Resources Are Nouns, Not Verbs
This is the most common mistake beginners make. REST URLs should contain nouns (things), not verbs (actions). The action is determined by the HTTP method.
| Bad URL (Verb-Based) | Good URL (Noun-Based) | Method |
|---|---|---|
/getUsers | /users | GET |
/createUser | /users | POST |
/updateUser/42 | /users/42 | PUT |
/deleteUser/42 | /users/42 | DELETE |
/getUserOrders/42 | /users/42/orders | GET |
/searchProducts | /products?q=laptop | GET |
The verb is already in the HTTP method. Putting it in the URL is redundant and messy.
2. HTTP Methods and CRUD Operations
REST maps HTTP methods to CRUD operations (Create, Read, Update, Delete). This mapping is the backbone of every REST API.
The CRUD-to-HTTP Mapping
| CRUD Operation | HTTP Method | Description | Example |
|---|---|---|---|
| Create | POST | Add a new resource | POST /users |
| Read | GET | Retrieve a resource | GET /users/42 |
| Update (Full) | PUT | Replace a resource entirely | PUT /users/42 |
| Update (Partial) | PATCH | Modify part of a resource | PATCH /users/42 |
| Delete | DELETE | Remove a resource | DELETE /users/42 |
graph LR
subgraph CRUD Operations
C[Create]
R[Read]
U[Update]
D[Delete]
end
subgraph HTTP Methods
POST[POST]
GET[GET]
PUT[PUT / PATCH]
DEL[DELETE]
end
C --> POST
R --> GET
U --> PUT
D --> DEL
style C fill:#059669,color:#fff
style R fill:#0891b2,color:#fff
style U fill:#d97706,color:#fff
style D fill:#dc2626,color:#fff
Working with Collections vs Individual Resources
There is an important distinction between a collection of resources and a single resource:
| Operation | URL | Method | Description |
|---|---|---|---|
| List all users | /users | GET | Returns an array of users |
| Get one user | /users/42 | GET | Returns a single user object |
| Create a user | /users | POST | Adds a new user to the collection |
| Replace a user | /users/42 | PUT | Replaces user 42 entirely |
| Update a user | /users/42 | PATCH | Updates specific fields of user 42 |
| Delete a user | /users/42 | DELETE | Removes user 42 |
Notice the pattern:
- Collection endpoints (
/users) handle listing and creating. - Instance endpoints (
/users/42) handle reading, updating, and deleting specific items.
Complete Example with JSONPlaceholder
Let us demonstrate every CRUD operation using the free JSONPlaceholder API:
CREATE — Add a new post:
curl -X POST https://jsonplaceholder.typicode.com/posts \
-H "Content-Type: application/json" \
-d '{
"title": "Learning REST APIs",
"body": "REST APIs are amazing!",
"userId": 1
}'
Response (201 Created):
{
"title": "Learning REST APIs",
"body": "REST APIs are amazing!",
"userId": 1,
"id": 101
}
READ — Get all posts:
curl https://jsonplaceholder.typicode.com/posts
READ — Get a single post:
curl https://jsonplaceholder.typicode.com/posts/1
Response (200 OK):
{
"userId": 1,
"id": 1,
"title": "sunt aut facere repellat provident...",
"body": "quia et suscipit..."
}
UPDATE — Replace a post entirely:
curl -X PUT https://jsonplaceholder.typicode.com/posts/1 \
-H "Content-Type: application/json" \
-d '{
"id": 1,
"title": "Updated Title",
"body": "Completely new body content.",
"userId": 1
}'
UPDATE — Partially update a post:
curl -X PATCH https://jsonplaceholder.typicode.com/posts/1 \
-H "Content-Type: application/json" \
-d '{
"title": "Only the title is changed"
}'
DELETE — Remove a post:
curl -X DELETE https://jsonplaceholder.typicode.com/posts/1
3. REST URL Design Best Practices
Designing good URLs is an art. A well-designed API is self-documenting — developers can guess the endpoints without reading documentation.
Rule 1: Use Plural Nouns
Always use plural nouns for collection endpoints:
| Bad | Good |
|---|---|
/user | /users |
/product | /products |
/order | /orders |
Even when accessing a single resource, the collection name stays plural:
/users/42 ← Good (user 42 from the users collection)
/user/42 ← Bad (inconsistent naming)
Rule 2: Use Hierarchical Relationships
When resources belong to other resources, reflect this in the URL:
/users/42/posts → Posts created by user 42
/users/42/posts/7 → Post 7 by user 42
/posts/7/comments → Comments on post 7
/departments/5/employees → Employees in department 5
However, do not nest too deeply. More than two levels becomes unwieldy:
/users/42/posts/7/comments/15/likes ← Too deep
/comments/15/likes ← Better: flatten it
Rule 3: Use Lowercase and Hyphens
URLs should be lowercase, with hyphens separating words:
| Bad | Good |
|---|---|
/UserProfiles | /user-profiles |
/product_categories | /product-categories |
/OrderItems | /order-items |
Rule 4: Use Query Parameters for Filtering
Use the URL path to identify resources and query parameters to filter, sort, or paginate:
# Filter posts by user
curl "https://jsonplaceholder.typicode.com/posts?userId=1"
# Paginate results
curl "https://api.example.com/products?page=2&limit=20"
# Sort results
curl "https://api.example.com/users?sort=name&order=asc"
# Search
curl "https://api.example.com/products?q=laptop&category=electronics"
Rule 5: Version Your API
Always include a version number in your API URL. This allows you to make breaking changes without disrupting existing users:
https://api.example.com/v1/users
https://api.example.com/v2/users
Complete URL Design Example
Here is a well-designed API for an e-commerce platform:
graph TD
A["api.shop.com/v1"] --> B["/products"]
A --> C["/users"]
A --> D["/orders"]
A --> E["/categories"]
B --> B1["GET /products - List all"]
B --> B2["POST /products - Create new"]
B --> B3["GET /products/50 - Get one"]
B --> B4["PUT /products/50 - Update"]
B --> B5["DELETE /products/50 - Remove"]
B --> B6["GET /products?category=electronics"]
B --> B7["GET /products/50/reviews"]
C --> C1["GET /users/10/orders"]
C --> C2["GET /users/10/wishlist"]
D --> D1["GET /orders/300/items"]
D --> D2["PATCH /orders/300/status"]
style A fill:#4f46e5,color:#fff
style B fill:#0891b2,color:#fff
style C fill:#0891b2,color:#fff
style D fill:#0891b2,color:#fff
style E fill:#0891b2,color:#fff
4. PUT vs PATCH: The Critical Difference
One of the most confusing aspects of REST for beginners is the difference between PUT and PATCH. Let us clarify this once and for all.
PUT: Full Replacement
PUT replaces the entire resource. You must send all fields, even the ones that have not changed.
Original resource:
{
"id": 1,
"name": "John Doe",
"email": "john@example.com",
"role": "admin"
}
PUT request (updating just the email):
curl -X PUT https://api.example.com/users/1 \
-H "Content-Type: application/json" \
-d '{
"id": 1,
"name": "John Doe",
"email": "newemail@example.com",
"role": "admin"
}'
If you leave out the role field, it might be set to null or removed entirely.
PATCH: Partial Update
PATCH updates only the fields you specify. Everything else stays the same.
curl -X PATCH https://api.example.com/users/1 \
-H "Content-Type: application/json" \
-d '{
"email": "newemail@example.com"
}'
Only the email changes. The name and role remain untouched.
When to Use Each
| Scenario | Method |
|---|---|
| Updating a user's profile form (all fields submitted) | PUT |
| Toggling a user's active status | PATCH |
| Replacing configuration settings | PUT |
| Changing just a password | PATCH |
5. Idempotency: A Key REST Concept
Idempotency means that making the same request multiple times produces the same result as making it once.
| Method | Idempotent? | Explanation |
|---|---|---|
| GET | Yes | Reading the same resource 100 times gives the same data |
| PUT | Yes | Replacing a resource with the same data 100 times gives the same result |
| DELETE | Yes | Deleting an already-deleted resource still results in "deleted" |
| PATCH | Usually Yes | Depends on implementation |
| POST | No | Creating the same resource twice creates two copies |
Why does this matter? In real networks, requests can fail and be retried. If a PUT request fails and you retry it, you get the same result. If a POST request fails and you retry it, you might accidentally create a duplicate.
6. Safe Methods
A safe method is one that does not modify data on the server.
| Method | Safe? | Why |
|---|---|---|
| GET | Yes | Only reads data |
| HEAD | Yes | Like GET but returns only headers |
| OPTIONS | Yes | Returns supported methods |
| POST | No | Creates new data |
| PUT | No | Modifies data |
| PATCH | No | Modifies data |
| DELETE | No | Removes data |
This is important because browsers, proxies, and CDNs treat safe methods differently. They can cache GET responses but should never cache POST responses.
7. Statelessness in Practice
We mentioned in Module 1 that REST is stateless. Let us understand what this means in practice.
What Stateless Means
Every request must contain all the information the server needs to process it. The server does not remember who you are between requests.
sequenceDiagram
participant Client
participant Server
Note over Client,Server: Stateless - Each request is independent
Client->>Server: GET /profile<br/>Authorization: Bearer token123
Server-->>Client: 200 OK - Profile data
Client->>Server: GET /orders<br/>Authorization: Bearer token123
Note right of Server: Server does NOT remember<br/>the previous request.<br/>Client must send token again.
Server-->>Client: 200 OK - Orders data
Why Statelessness Matters
-
Scalability: Any server can handle any request. You can add 100 servers behind a load balancer, and it does not matter which one gets your request.
-
Reliability: If a server crashes, the next request just goes to another server. No session data is lost.
-
Simplicity: The server does not need to manage session storage for millions of users.
How Authentication Works Without State
If the server does not remember you, how does authentication work? The answer is tokens. Every request includes an authentication token (usually in the Authorization header). The server validates the token on each request independently.
# Every request includes the token
curl -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
https://api.example.com/users/me
curl -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
https://api.example.com/orders
8. REST API Design Checklist
Here is a professional checklist for evaluating any REST API design:
| Criteria | Good Practice |
|---|---|
| URLs use nouns | /users not /getUsers |
| Plural collection names | /products not /product |
| HTTP methods for actions | GET to read, POST to create |
| Consistent naming | All lowercase with hyphens |
| Logical hierarchy | /users/42/orders |
| Max 2 levels deep | Avoid /a/1/b/2/c/3/d |
| Query params for filtering | ?status=active&sort=name |
| API versioning | /v1/users |
| Meaningful status codes | 201 for created, 404 for not found |
| JSON response format | Standard content type |
Summary and Key Takeaways
- Resources are the core concept of REST — everything is a noun.
- HTTP methods map to CRUD: GET (Read), POST (Create), PUT/PATCH (Update), DELETE (Delete).
- Good URLs use plural nouns, hierarchy for relationships, and query parameters for filtering.
- PUT replaces the entire resource; PATCH updates only specific fields.
- Idempotency ensures safe retries for GET, PUT, and DELETE.
- Statelessness means every request is self-contained — the server remembers nothing.
- A well-designed REST API is self-documenting — developers can guess the endpoints.
Lesson Review Quiz
?Knowledge Check
Which URL follows REST best practices?
?Knowledge Check
What is the difference between PUT and PATCH?
?Knowledge Check
Why is POST not idempotent?
Practice Exercise
- Look at this API and identify what is wrong with each URL:
GET /fetchUser/42 → Problem: ___________
POST /user → Problem: ___________
GET /Users/42/Order → Problem: ___________
DELETE /removeProduct/5 → Problem: ___________
Answers:
/fetchUser/42→ Verb in URL; should beGET /users/42/user→ Singular noun; should bePOST /users/Users/42/Order→ Uppercase and singular; should beGET /users/42/orders/removeProduct/5→ Verb in URL; should beDELETE /products/5
- Design a REST API for a library system. Define endpoints for:
- Books (list, get, create, update, delete)
- Authors (list, get)
- A book's reviews (list, create)
- Search books by title
In the next module, we will get hands-on with cURL and start making real API calls from the command line.