Designing REST APIs
Why Learn REST API Design?
Section titled “Why Learn REST API Design?”Imagine you’re organizing a library. You need to decide:
- What things do we have? (books, members, loans)
- How do we organize them? (by category, alphabetically)
- How do people find what they need? (catalog system, clear signs)
Designing a REST API is exactly the same! You’re creating an organized system that lets other programs find, create, update, and delete data in your application.
By the end of this guide, you’ll be able to:
- Identify the “things” (resources) in any system
- Organize them into logical URL structures
- Connect them with the right HTTP operations
- Design responses that are easy to understand and navigate
The Design Workflow
Section titled “The Design Workflow”REST API design is about modeling your domain as resources (nouns), not actions (verbs). Follow these 6 steps to design a clean, intuitive API.
Step 1: Identify Resources
Section titled “Step 1: Identify Resources”Look at your domain and extract the nouns—the “things” your system manages.
Example Domain: Space Mission Management
“Space agencies plan missions to planets. Astronauts are assigned to missions and use spacecraft to collect scientific data.”
Let’s circle all the nouns: Space agencies plan missions to planets. Astronauts are assigned to missions and use spacecraft to collect scientific data.
Resources identified:
- Mission — A space expedition
- Astronaut — A crew member
- Planet — A celestial body
- Spacecraft — A vehicle
- Data — Scientific information collected
Avoid action-oriented thinking:
| Wrong (verbs) | Right (nouns) |
|---|---|
| getMission | Mission |
| createAstronaut | Astronaut |
| launchSpacecraft | Spacecraft |
Step 2: Determine Resource Types
Section titled “Step 2: Determine Resource Types”Classify each resource. Think of it like a library:
| Type | Analogy | Example |
|---|---|---|
| Singleton | ONE specific book by title | /api/missions/apollo-11 |
| Collection | ALL books in a section | /api/missions |
| Sub-Collection | All chapters IN a book | /api/missions/apollo-11/crew |
GET /api/planets # Collection: all planetsGET /api/planets/mars # Singleton: one planetGET /api/planets/mars/moons # Sub-collection: moons of MarsFor detailed explanations of each resource type, see Resource-Oriented Design.
Step 3: Define Relationships
Section titled “Step 3: Define Relationships”Decide how resources connect to each other:
| Approach | When to Use | Example |
|---|---|---|
| Sub-resources | Child depends on or belongs to parent | /missions/apollo-11/crew |
| References | Resources exist independently | "mission_id": "apollo-11" with _links |
Quick decision: If deleting the parent should delete the child, use sub-resources. If not, use references.
# Sub-resource: crew only exists within a missionGET /api/missions/apollo-11/crew
# Reference: astronauts exist independently, linked via IDGET /api/astronauts/neil-armstrong# Response includes: { "current_mission": "apollo-11", "_links": { ... } }For more on relationship types, see Resource-Oriented Design.
Step 4: Design URL Structure
Section titled “Step 4: Design URL Structure”Good URLs should read almost like a sentence.
Naming Conventions
Section titled “Naming Conventions”- Plural nouns for collections:
/planets,/missions - Lowercase with hyphens:
/space-stations, not/spaceStations - No verbs in URLs:
/missions, not/getMissions - Identifiers for singletons:
/missions/apollo-11
URL Hierarchy
Section titled “URL Hierarchy”/api/missions # Collection/api/missions/{id} # Singleton/api/missions/{id}/crew # Sub-collection/api/missions/{id}/crew/{astronaut} # Singleton in sub-collectionKeep It Shallow
Section titled “Keep It Shallow”# Good: Max 2 levels deepGET /api/missions/apollo-11/crew
# Avoid: Too deep, hard to useGET /api/missions/apollo-11/crew/neil/training/physical/cardioIf you need deep data, provide it as a direct resource:
GET /api/astronauts/neil/trainingStep 5: Map HTTP Operations
Section titled “Step 5: Map HTTP Operations”Map each resource to the HTTP methods it supports:
| Resource | GET | POST | PUT/PATCH | DELETE |
|---|---|---|---|---|
/missions | List all | Create new | — | — |
/missions/{id} | Get one | — | Update | Delete |
/missions/{id}/crew | List crew | Add member | — | — |
/missions/{id}/crew/{id} | Get member | — | Update role | Remove |
For detailed HTTP method semantics, see HTTP Verbs. For status codes, see HTTP Status Codes.
Step 6: Design Response Format
Section titled “Step 6: Design Response Format”Keep Responses Concise
Section titled “Keep Responses Concise”{ "id": "apollo-11", "name": "Apollo 11", "status": "completed", "launch_date": "1969-07-16", "crew_size": 3, "_links": { "self": "/api/missions/apollo-11", "crew": "/api/missions/apollo-11/crew" }}Collection Response with Pagination
Section titled “Collection Response with Pagination”{ "page": 1, "limit": 10, "total_count": 156, "missions": [ { "id": "apollo-11", "name": "Apollo 11", "status": "completed" }, { "id": "artemis-3", "name": "Artemis 3", "status": "planned" } ], "_links": { "self": "/api/missions?page=1", "next": "/api/missions?page=2" }}Response Guidelines
Section titled “Response Guidelines”- Include only essential fields
- Add _links for navigation (HATEOAS)
- Use pagination for collections
- Keep consistent structure across resources
Quick Reference Checklist
Section titled “Quick Reference Checklist”Use this checklist when designing your API:
| Step | Check |
|---|---|
| 1. Resources | Identified all nouns in your domain? |
| 2. Types | Singleton, Collection, or Sub-collection? |
| 3. Relationships | Dependencies mapped? Sub-resources vs references decided? |
| 4. URLs | Plural nouns? Lowercase with hyphens? Shallow hierarchy? |
| 5. Operations | HTTP methods mapped correctly? Status codes defined? |
| 6. Responses | Concise? Links included? Pagination for collections? |
Example: Complete API Design
Section titled “Example: Complete API Design”Domain: Space Mission Management
Resources:├── /api/missions # All missions│ └── /{id} # Single mission│ ├── /crew # Mission crew (sub-collection)│ └── /data # Mission data (sub-collection)├── /api/astronauts # All astronauts (independent)│ └── /{id}│ └── /missions # Astronaut's mission history├── /api/planets # All planets│ └── /{id}│ └── /moons # Planet's moons (sub-collection)└── /api/spacecraft # All spacecraft (independent)