| name | api-design-principles |
| description | Master REST API design principles to build intuitive, scalable, and maintainable APIs. Use when designing new APIs, reviewing API specifications, or establishing API design standards. |
| layer | 2 |
| tech_stack | agnostic |
| topics | rest-api, versioning, pagination, http-methods, status-codes, api-design |
| depends_on | |
| complements | technical-design-patterns, abp-api-implementation |
| keywords | REST, API, Endpoint, GET, POST, PUT, DELETE, OpenAPI, Swagger, HTTP |
API Design Principles
Master REST API design principles to build intuitive, scalable, and maintainable APIs. This skill focuses on design theory - for implementation patterns, see abp-api-implementation or abp-service-patterns.
When to Use This Skill
- Designing new REST API contracts
- Reviewing API specifications before implementation
- Establishing API design standards for your team
- Planning API versioning and evolution strategy
- Creating developer-friendly API documentation
Audience
- Backend Architects - API contract design
- Tech Leads - Standards and review
- Business Analysts - Understanding API capabilities
For Implementation: Use
abp-service-patternsfor AppService code,api-response-patternsfor response wrappers,fluentvalidation-patternsfor validation.
Core Principles
1. Resource-Oriented Design
APIs expose resources (nouns), not actions (verbs).
| Concept | Good | Bad |
|---|---|---|
| Resource naming | /patients, /appointments |
/getPatients, /createAppointment |
| Actions via HTTP methods | POST /patients |
POST /createPatient |
| Plural for collections | /patients |
/patient |
| Consistent casing | kebab-case or camelCase |
Mixed styles |
Resource Hierarchy:
/api/v1/patients # Collection
/api/v1/patients/{id} # Single resource
/api/v1/patients/{id}/appointments # Nested collection
/api/v1/appointments/{id} # Direct access to nested resource
Avoid Deep Nesting (max 2 levels):
# Good - Shallow
GET /api/v1/patients/{id}/appointments
GET /api/v1/appointments/{id}
# Bad - Too deep
GET /api/v1/clinics/{id}/doctors/{id}/patients/{id}/appointments/{id}
2. HTTP Methods Semantics
| Method | Purpose | Idempotent | Safe | Request Body |
|---|---|---|---|---|
GET |
Retrieve resource(s) | Yes | Yes | No |
POST |
Create resource | No | No | Yes |
PUT |
Replace entire resource | Yes | No | Yes |
PATCH |
Partial update | Yes* | No | Yes |
DELETE |
Remove resource | Yes | No | No |
Idempotent: Multiple identical requests produce same result. Safe: Does not modify server state.
3. HTTP Status Codes
Success (2xx):
| Code | Meaning | Use When |
|---|---|---|
200 OK |
Success | GET, PUT, PATCH succeeded |
201 Created |
Resource created | POST succeeded |
204 No Content |
Success, no body | DELETE succeeded |
Client Errors (4xx):
| Code | Meaning | Use When |
|---|---|---|
400 Bad Request |
Malformed request | Invalid JSON, missing required headers |
401 Unauthorized |
Not authenticated | Missing or invalid token |
403 Forbidden |
Not authorized | Valid token, insufficient permissions |
404 Not Found |
Resource doesn't exist | ID not found |
409 Conflict |
State conflict | Duplicate email, version mismatch |
422 Unprocessable Entity |
Validation failed | Business rule violations |
429 Too Many Requests |
Rate limited | Exceeded request quota |
Server Errors (5xx):
| Code | Meaning | Use When |
|---|---|---|
500 Internal Server Error |
Unexpected error | Unhandled exception |
503 Service Unavailable |
Temporarily down | Maintenance, overload |
Design Patterns
Pattern 1: Pagination
Always paginate collections - Never return unbounded lists.
Offset-Based (simple, good for small datasets):
GET /api/v1/patients?page=2&pageSize=20
Response:
{
"items": [...],
"totalCount": 150,
"pageNumber": 2,
"pageSize": 20,
"totalPages": 8
}
Cursor-Based (efficient for large datasets, real-time data):
GET /api/v1/patients?cursor=eyJpZCI6MTIzfQ&limit=20
Response:
{
"items": [...],
"nextCursor": "eyJpZCI6MTQzfQ",
"hasMore": true
}
| Approach | Pros | Cons | Best For |
|---|---|---|---|
| Offset | Simple, supports jumping to page | Slow on large datasets, inconsistent with real-time data | Admin panels, reports |
| Cursor | Fast, consistent | Can't jump to arbitrary page | Infinite scroll, feeds |
Pattern 2: Filtering and Sorting
Query Parameters for Filtering:
GET /api/v1/patients?status=active
GET /api/v1/patients?status=active&createdAfter=2025-01-01
GET /api/v1/patients?doctorId=abc-123
Sorting:
GET /api/v1/patients?sorting=name
GET /api/v1/patients?sorting=createdAt desc
GET /api/v1/patients?sorting=lastName,firstName
Searching:
GET /api/v1/patients?filter=john
GET /api/v1/patients?search=john doe
Design Decisions:
- Use
WhereIfpattern - only apply filter if parameter provided - Define allowed sort fields (security - don't expose internal fields)
- Set maximum page size (prevent abuse)
Pattern 3: Error Response Design
Consistent Structure:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "One or more validation errors occurred.",
"details": [
{
"field": "email",
"message": "Invalid email format."
},
{
"field": "dateOfBirth",
"message": "Date of birth cannot be in the future."
}
],
"traceId": "00-abc123-def456-00"
}
}
Error Codes (for client handling):
| Code | HTTP Status | Meaning |
|---|---|---|
VALIDATION_ERROR |
422 | Input validation failed |
NOT_FOUND |
404 | Resource doesn't exist |
UNAUTHORIZED |
401 | Authentication required |
FORBIDDEN |
403 | Permission denied |
CONFLICT |
409 | State conflict |
RATE_LIMITED |
429 | Too many requests |
Pattern 4: Versioning Strategy
URL Versioning (Recommended for ABP):
/api/v1/patients
/api/v2/patients
| Strategy | Example | Pros | Cons |
|---|---|---|---|
| URL Path | /api/v1/ |
Clear, easy routing | Multiple URLs |
| Header | Api-Version: 1 |
Clean URLs | Hidden, harder to test |
| Query Param | ?version=1 |
Easy testing | Can be forgotten |
Versioning Policy:
- Major version for breaking changes
- Support N-1 version minimum
- Deprecation notice 6+ months before removal
- Document migration path
Pattern 5: Resource Relationships
Embedding vs Linking:
// Embedded (fewer requests, larger payload)
{
"id": "patient-123",
"name": "John Doe",
"doctor": {
"id": "doctor-456",
"name": "Dr. Smith"
}
}
// Linked (smaller payload, more requests)
{
"id": "patient-123",
"name": "John Doe",
"doctorId": "doctor-456"
}
// Hybrid (with expand parameter)
GET /api/v1/patients/123?expand=doctor,appointments
Decision Criteria:
| Use Embedding | Use Linking |
|---|---|
| Related data always needed | Related data rarely needed |
| Few relationships | Many relationships |
| Related data is small | Related data is large |
API Contract Checklist
Resource Design
- Resources are nouns, not verbs
- Plural names for collections
- Consistent naming convention
- Max 2 levels of nesting
- All CRUD mapped to correct HTTP methods
Request/Response
- All collections paginated
- Default and max page size defined
- Filter parameters documented
- Sorting parameters documented
- Consistent error response format
Security
- Authentication method defined
- Authorization on all mutating endpoints
- Rate limiting configured
- Sensitive data not in URLs
- CORS configured
Documentation
- OpenAPI/Swagger spec
- All endpoints documented
- Request/response examples
- Error responses documented
Anti-Patterns to Avoid
| Anti-Pattern | Problem | Solution |
|---|---|---|
| Verb endpoints | POST /createPatient |
POST /patients |
| Ignoring HTTP methods | Using POST for everything | Use appropriate method |
| No pagination | Returning 10,000 items | Always paginate |
| Inconsistent errors | Different formats per endpoint | Standardize error structure |
| Exposing internals | Database columns in API | Design API contract separately |
| No versioning | Breaking changes break clients | Version from day one |
| Deep nesting | /a/{id}/b/{id}/c/{id}/d |
Flatten, max 2 levels |
Integration with Other Skills
| Need | Skill |
|---|---|
| AppService implementation | abp-service-patterns |
| Response wrappers | api-response-patterns |
| Input validation | fluentvalidation-patterns |
| Query optimization | linq-optimization-patterns |
| Technical design docs | technical-design-patterns |
References
references/rest-best-practices.md- Detailed REST patternsassets/api-design-checklist.md- Pre-implementation checklist