
Designing a REST API: From Concept to Endpoints
Learn to design a REST API from scratch. Walk through requirements analysis, resource identification, endpoint mapping, and response structure for a real application.
Designing a REST API: From Concept to Endpoints
Understanding how APIs are designed makes you a better API consumer. In this lesson, we will design a complete REST API from scratch for a task management application — the kind you might actually build or work with in your career.
1. The Design Process
graph TD
A["1. Understand Requirements"] --> B["2. Identify Resources"]
B --> C["3. Define Relationships"]
C --> D["4. Map CRUD to Endpoints"]
D --> E["5. Design Request/Response"]
E --> F["6. Add Auth and Validation"]
F --> G["7. Document the API"]
style A fill:#4f46e5,color:#fff
style D fill:#0891b2,color:#fff
style G fill:#059669,color:#fff
2. Step 1: Requirements
Application: TaskFlow — a task management app for teams.
Features:
- Users can register and log in
- Users create projects
- Projects contain task lists
- Task lists contain tasks
- Tasks can be assigned to team members
- Tasks have due dates, priorities, and statuses
- Users can comment on tasks
- Users can label tasks with tags
3. Step 2: Identify Resources
Extract the nouns from requirements:
| Resource | Description |
|---|---|
| Users | People using the app |
| Projects | Top-level containers |
| Task Lists | Groups of tasks within a project |
| Tasks | Individual work items |
| Comments | Discussion on tasks |
| Tags | Labels for organizing tasks |
4. Step 3: Define Relationships
graph TD
U[User] -->|creates| P[Project]
U -->|assigned to| T[Task]
P -->|contains| TL[Task List]
TL -->|contains| T
T -->|has many| C[Comments]
T -->|has many| Tag[Tags]
U -->|writes| C
style U fill:#4f46e5,color:#fff
style P fill:#0891b2,color:#fff
style T fill:#059669,color:#fff
5. Step 4: Map Endpoints
Authentication
| Method | Endpoint | Description |
|---|---|---|
| POST | /auth/register | Create account |
| POST | /auth/login | Get access token |
| POST | /auth/refresh | Refresh expired token |
Users
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| GET | /users/me | Get current user | Required |
| PATCH | /users/me | Update profile | Required |
| GET | /users/:id | Get user by ID | Required |
Projects
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| GET | /projects | List my projects | Required |
| POST | /projects | Create a project | Required |
| GET | /projects/:id | Get project details | Required |
| PATCH | /projects/:id | Update project | Owner |
| DELETE | /projects/:id | Delete project | Owner |
Tasks
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| GET | /projects/:id/tasks | List tasks in project | Member |
| POST | /projects/:id/tasks | Create a task | Member |
| GET | /tasks/:id | Get task details | Member |
| PATCH | /tasks/:id | Update a task | Member |
| DELETE | /tasks/:id | Delete a task | Owner |
| POST | /tasks/:id/assign | Assign to user | Member |
Comments
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| GET | /tasks/:id/comments | List comments | Member |
| POST | /tasks/:id/comments | Add comment | Member |
| DELETE | /comments/:id | Delete comment | Author |
6. Step 5: Design Request/Response
Create Project (POST /projects)
Request:
{
"name": "Website Redesign",
"description": "Complete overhaul of company website",
"color": "#4f46e5"
}
Response (201 Created):
{
"id": "proj_abc123",
"name": "Website Redesign",
"description": "Complete overhaul of company website",
"color": "#4f46e5",
"ownerId": 42,
"memberCount": 1,
"taskCount": 0,
"createdAt": "2026-02-22T14:00:00Z"
}
Create Task (POST /projects/:id/tasks)
Request:
{
"title": "Design homepage mockup",
"description": "Create wireframes and hi-fi mockups for the new homepage",
"priority": "high",
"dueDate": "2026-03-01",
"assigneeId": 15,
"tags": ["design", "homepage"]
}
Response (201 Created):
{
"id": "task_xyz789",
"title": "Design homepage mockup",
"description": "Create wireframes and hi-fi mockups for the new homepage",
"status": "todo",
"priority": "high",
"dueDate": "2026-03-01",
"assignee": {
"id": 15,
"name": "Sarah Chen",
"avatar": "https://example.com/avatars/sarah.jpg"
},
"tags": ["design", "homepage"],
"commentCount": 0,
"projectId": "proj_abc123",
"createdBy": 42,
"createdAt": "2026-02-22T14:30:00Z"
}
List Tasks with Filtering
# All tasks in project, filtered and sorted
GET /projects/proj_abc123/tasks?status=in-progress&priority=high&sort=dueDate&order=asc&page=1&limit=20
Response:
{
"data": [
{
"id": "task_xyz789",
"title": "Design homepage mockup",
"status": "in-progress",
"priority": "high",
"dueDate": "2026-03-01",
"assignee": {"id": 15, "name": "Sarah Chen"}
}
],
"pagination": {
"page": 1,
"limit": 20,
"total": 1,
"totalPages": 1
}
}
7. Step 6: Error Responses
Every endpoint should have clear error responses:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Task creation failed",
"details": [
{"field": "title", "message": "Title is required"},
{"field": "priority", "message": "Must be one of: low, medium, high, urgent"}
]
}
}
Summary and Key Takeaways
- Design before building — identify resources, relationships, and endpoints.
- Each resource gets a standard set of CRUD endpoints.
- Use nested URLs for parent-child relationships:
/projects/:id/tasks. - Design consistent response formats across all endpoints.
- Include pagination for all collection endpoints.
- Plan error responses as carefully as success responses.
Lesson Review Quiz
?Knowledge Check
In our TaskFlow API design, how would you get all tasks in a specific project?
?Knowledge Check
Which endpoint would assign a task to a team member?
?Knowledge Check
What should the response look like when creating a task with invalid data?