REST API Design Principles
URL Structure
GET /api/v1/resources # List all GET /api/v1/resources/{id} # Get one POST /api/v1/resources # Create PUT /api/v1/resources/{id} # Replace PATCH /api/v1/resources/{id} # Partial update DELETE /api/v1/resources/{id} # Delete
Nested resources
GET /api/v1/parents/{id}/children POST /api/v1/parents/{id}/children
HTTP Status Codes
Code Meaning When to Use
200 OK Successful GET, PUT, PATCH
201 Created Successful POST (new resource)
204 No Content Successful DELETE
400 Bad Request Validation errors, malformed request
401 Unauthorized Missing or invalid authentication
403 Forbidden Valid auth but no permission
404 Not Found Resource doesn't exist
409 Conflict Duplicate, state conflict
422 Unprocessable Semantic errors
500 Server Error Unexpected errors
Request/Response Design
Collection Response
{ "data": [...], "pagination": { "page": 1, "pageSize": 20, "totalItems": 150, "totalPages": 8 } }
Single Resource Response
{ "id": "uuid", "name": "Resource Name", "createdAt": "2024-01-15T10:30:00Z", "updatedAt": "2024-01-15T11:00:00Z" }
Error Response
{ "error": { "code": "VALIDATION_ERROR", "message": "Name is required", "details": [ {"field": "name", "message": "must not be blank"} ] } }
Query Parameters
Filtering
GET /api/v1/resources?status=active&type=premium
Sorting
GET /api/v1/resources?sort=createdAt,desc
Pagination
GET /api/v1/resources?page=1&pageSize=20
Field selection
GET /api/v1/resources?fields=id,name,status
Search
GET /api/v1/resources?search=query
Idempotency
-
POST with unique identifiers should return existing resource (200) if duplicate
-
PUT/DELETE should be idempotent
-
Use Pair<Result, Boolean> pattern to indicate created vs existing
Versioning
-
Use URL path versioning: /api/v1/ , /api/v2/
-
Version when making breaking changes
-
Support old versions during migration period
Security Considerations
-
Always validate input at API boundary
-
Use parameterized queries (JOOQ handles this)
-
Check authorization in service layer
-
Never expose internal IDs or sensitive data
-
Rate limit public endpoints