Skip to main content

REST API Design Challenge

Design and implement a complete REST API - putting your API knowledge into practice.

Difficulty

⭐⭐⭐ Advanced

Problem Description

Design and implement a REST API for a Task Management System. This challenge combines your knowledge of REST principles, Spring Boot, and API best practices to build a real-world application.

Requirements

Build a REST API that allows users to:

  • Create, read, update, and delete tasks
  • Filter tasks by status
  • Assign tasks to users
  • Mark tasks as complete

API Specification

Design endpoints following REST best practices:

Task Endpoints

MethodEndpointDescription
GET/api/tasksList all tasks
GET/api/tasks/{id}Get a specific task
POST/api/tasksCreate a new task
PUT/api/tasks/{id}Update a task
DELETE/api/tasks/{id}Delete a task
PATCH/api/tasks/{id}/completeMark task as complete

Query Parameters

ParameterTypeDescription
statusStringFilter by status (PENDING, IN_PROGRESS, COMPLETED)
assigneeStringFilter by assigned user
priorityStringFilter by priority (LOW, MEDIUM, HIGH)

Skills Practised

  • REST API design principles
  • Spring Boot development
  • HTTP methods and status codes
  • Request/Response handling
  • Input validation
  • Error handling
  • API documentation

Data Model

Task

public class Task {
private Long id;
private String title;
private String description;
private TaskStatus status; // PENDING, IN_PROGRESS, COMPLETED
private Priority priority; // LOW, MEDIUM, HIGH
private String assignee;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
private LocalDateTime dueDate;
}

Example Requests and Responses

Create Task

Request:

POST /api/tasks
Content-Type: application/json

{
"title": "Implement login feature",
"description": "Add user authentication using JWT",
"priority": "HIGH",
"assignee": "john.doe",
"dueDate": "2024-02-15T17:00:00"
}

Response (201 Created):

{
"id": 1,
"title": "Implement login feature",
"description": "Add user authentication using JWT",
"status": "PENDING",
"priority": "HIGH",
"assignee": "john.doe",
"createdAt": "2024-01-20T10:30:00",
"updatedAt": "2024-01-20T10:30:00",
"dueDate": "2024-02-15T17:00:00"
}

List Tasks with Filters

Request:

GET /api/tasks?status=PENDING&priority=HIGH

Response (200 OK):

{
"content": [
{
"id": 1,
"title": "Implement login feature",
"status": "PENDING",
"priority": "HIGH",
"assignee": "john.doe"
}
],
"totalElements": 1,
"totalPages": 1,
"page": 0,
"size": 10
}

Error Response

Response (404 Not Found):

{
"timestamp": "2024-01-20T10:30:00",
"status": 404,
"error": "Not Found",
"message": "Task not found with id: 999",
"path": "/api/tasks/999"
}

Implementation Steps

Step 1: Create the Project

Create a Spring Boot project with these dependencies:

  • Spring Web
  • Spring Boot DevTools
  • Validation
  • SpringDoc OpenAPI (for documentation)

Step 2: Define the Model

public enum TaskStatus {
PENDING, IN_PROGRESS, COMPLETED
}

public enum Priority {
LOW, MEDIUM, HIGH
}

public class Task {
private Long id;

@NotBlank(message = "Title is required")
private String title;

private String description;

private TaskStatus status = TaskStatus.PENDING;

private Priority priority = Priority.MEDIUM;

private String assignee;

private LocalDateTime createdAt;
private LocalDateTime updatedAt;
private LocalDateTime dueDate;

// Constructors, getters, setters
}

Step 3: Implement the Controller

@RestController
@RequestMapping("/api/tasks")
public class TaskController {

@GetMapping
public ResponseEntity<List<Task>> getAllTasks(
@RequestParam(required = false) TaskStatus status,
@RequestParam(required = false) Priority priority,
@RequestParam(required = false) String assignee) {
// Implementation
}

@GetMapping("/{id}")
public ResponseEntity<Task> getTask(@PathVariable Long id) {
// Implementation
}

@PostMapping
public ResponseEntity<Task> createTask(@Valid @RequestBody Task task) {
// Implementation
}

@PutMapping("/{id}")
public ResponseEntity<Task> updateTask(
@PathVariable Long id,
@Valid @RequestBody Task task) {
// Implementation
}

@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteTask(@PathVariable Long id) {
// Implementation
}

@PatchMapping("/{id}/complete")
public ResponseEntity<Task> completeTask(@PathVariable Long id) {
// Implementation
}
}

Step 4: Add Error Handling

@RestControllerAdvice
public class GlobalExceptionHandler {

@ExceptionHandler(TaskNotFoundException.class)
public ResponseEntity<ErrorResponse> handleNotFound(TaskNotFoundException ex) {
ErrorResponse error = new ErrorResponse(
HttpStatus.NOT_FOUND.value(),
"Not Found",
ex.getMessage()
);
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(error);
}

@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ErrorResponse> handleValidation(MethodArgumentNotValidException ex) {
// Handle validation errors
}
}

Step 5: Add API Documentation

@Operation(summary = "Create a new task")
@ApiResponses({
@ApiResponse(responseCode = "201", description = "Task created"),
@ApiResponse(responseCode = "400", description = "Invalid input")
})
@PostMapping
public ResponseEntity<Task> createTask(@Valid @RequestBody Task task) {
// Implementation
}

Acceptance Criteria

Your API should:

Functional Requirements

  • Create tasks with title, description, priority, and due date
  • Retrieve all tasks with optional filtering
  • Retrieve a single task by ID
  • Update existing tasks
  • Delete tasks
  • Mark tasks as complete
  • Return appropriate HTTP status codes

Non-Functional Requirements

  • Validate input (title required, valid enum values)
  • Return meaningful error messages
  • Document API with OpenAPI/Swagger
  • Follow REST naming conventions
  • Handle edge cases gracefully

Testing Your API

Using cURL

# Create a task
curl -X POST http://localhost:8080/api/tasks \
-H "Content-Type: application/json" \
-d '{"title": "Test task", "priority": "HIGH"}'

# Get all tasks
curl http://localhost:8080/api/tasks

# Get tasks by status
curl "http://localhost:8080/api/tasks?status=PENDING"

# Update a task
curl -X PUT http://localhost:8080/api/tasks/1 \
-H "Content-Type: application/json" \
-d '{"title": "Updated task", "status": "IN_PROGRESS"}'

# Complete a task
curl -X PATCH http://localhost:8080/api/tasks/1/complete

# Delete a task
curl -X DELETE http://localhost:8080/api/tasks/1

Using REST Assured (Integration Tests)

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class TaskApiTest {

@LocalServerPort
private int port;

@BeforeEach
void setup() {
RestAssured.port = port;
}

@Test
void shouldCreateTask() {
given()
.contentType("application/json")
.body("""
{
"title": "New task",
"priority": "HIGH"
}
""")
.when()
.post("/api/tasks")
.then()
.statusCode(201)
.body("title", equalTo("New task"))
.body("status", equalTo("PENDING"))
.body("id", notNullValue());
}

@Test
void shouldReturn404ForNonExistentTask() {
when()
.get("/api/tasks/99999")
.then()
.statusCode(404)
.body("message", containsString("not found"));
}

@Test
void shouldValidateRequiredFields() {
given()
.contentType("application/json")
.body("{}")
.when()
.post("/api/tasks")
.then()
.statusCode(400);
}
}

Extension Challenges

1. Add Pagination

Implement pagination for the task list:

GET /api/tasks?page=0&size=10&sort=createdAt,desc

Search tasks by title or description:

GET /api/tasks/search?q=login

3. Add Subtasks

Allow tasks to have subtasks:

POST /api/tasks/1/subtasks
GET /api/tasks/1/subtasks

4. Add Comments

Allow users to comment on tasks:

POST /api/tasks/1/comments
GET /api/tasks/1/comments

5. Add Authentication

Secure the API with JWT authentication.

6. Add Database Persistence

Replace in-memory storage with a database using Spring Data JPA.

Evaluation Criteria

Your solution will be evaluated on:

CriteriaWeightDescription
Correctness30%Does the API work as specified?
REST Design25%Proper use of methods, status codes, URLs
Code Quality20%Clean, readable, maintainable code
Error Handling15%Graceful handling of errors
Documentation10%API is well-documented

What You've Learned

After completing this challenge, you should understand:

  • ✅ How to design RESTful APIs
  • ✅ Spring Boot controller development
  • ✅ Request validation and error handling
  • ✅ HTTP status codes and their meanings
  • ✅ API documentation with OpenAPI
  • ✅ Testing APIs with REST Assured

This challenge applies concepts from: