Design
API Design
Best practices for designing robust, maintainable APIs
APIs (Application Programming Interfaces) are the contracts between software components. Good API design is crucial for maintainability, usability, and the long-term success of your software.
API Contract Components
Based on industry best practices, an API contract includes:
| Component | Purpose |
|---|---|
| Terms of Service | Legal usage terms |
| Privacy Policy | Data handling commitments |
| SLA / Service Accord | Quality and reliability expectations |
| Interface License | API usage rights |
| Data License | Data usage rights |
| Deprecation Policy | End-of-life procedures |
| Rate Limits | Usage constraints |
| Versioning | Change management |
REST API Design Principles
Resource-Based URLs
Good:
GET /users # List users
GET /users/123 # Get user 123
POST /users # Create user
PUT /users/123 # Update user 123
DELETE /users/123 # Delete user 123
GET /users/123/orders # Get orders for user 123
Bad:
GET /getUsers
POST /createUser
GET /getUserOrders?userId=123
POST /deleteUserHTTP Methods
| Method | Purpose | Idempotent | Safe |
|---|---|---|---|
GET | Retrieve resource | Yes | Yes |
POST | Create resource | No | No |
PUT | Replace resource | Yes | No |
PATCH | Partial update | No | No |
DELETE | Remove resource | Yes | No |
HTTP Status Codes
Success:
200 OK - Request succeeded
201 Created - Resource created
204 No Content - Success, no response body
Client Errors:
400 Bad Request - Invalid request syntax
401 Unauthorized - Authentication required
403 Forbidden - Access denied
404 Not Found - Resource doesn't exist
409 Conflict - Resource conflict
422 Unprocessable - Validation failed
429 Too Many Req - Rate limit exceeded
Server Errors:
500 Internal Error - Server error
502 Bad Gateway - Upstream error
503 Unavailable - Service unavailable
504 Gateway Timeout - Upstream timeoutRequest/Response Design
Request Format
// POST /api/v1/users
{
"email": "john@example.com",
"name": "John Doe",
"role": "user",
"preferences": {
"notifications": true,
"theme": "dark"
}
}Response Format
// Success Response
{
"data": {
"id": "user-123",
"email": "john@example.com",
"name": "John Doe",
"role": "user",
"createdAt": "2024-01-15T10:30:00Z",
"updatedAt": "2024-01-15T10:30:00Z"
},
"meta": {
"requestId": "req-abc-123"
}
}
// Error Response
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Request validation failed",
"details": [
{
"field": "email",
"message": "Invalid email format"
}
]
},
"meta": {
"requestId": "req-abc-124"
}
}Pagination
// Request
GET /api/v1/users?page=2&limit=20
// Response
{
"data": [...],
"pagination": {
"page": 2,
"limit": 20,
"total": 150,
"totalPages": 8,
"hasNext": true,
"hasPrev": true
},
"links": {
"self": "/api/v1/users?page=2&limit=20",
"first": "/api/v1/users?page=1&limit=20",
"prev": "/api/v1/users?page=1&limit=20",
"next": "/api/v1/users?page=3&limit=20",
"last": "/api/v1/users?page=8&limit=20"
}
}API Versioning
Strategies
| Strategy | Example | Pros | Cons |
|---|---|---|---|
| URL Path | /api/v1/users | Clear, easy to implement | URL changes |
| Query Param | /api/users?version=1 | Flexible | Easy to miss |
| Header | Accept: application/vnd.api.v1+json | Clean URLs | Less visible |
| Media Type | Content-Type: application/vnd.api.v1+json | Semantic | Complex |
Recommended: URL Path Versioning
/api/v1/users # Version 1
/api/v2/users # Version 2 (breaking changes)Deprecation Timeline
Timeline:
├── Announce deprecation (6 months before sunset)
├── Add deprecation header to responses
├── Provide migration guide
├── Monitor usage of deprecated version
├── Send reminders to active consumers
└── Sunset old version// Deprecation response header
HTTP/1.1 200 OK
Deprecation: Sun, 01 Jul 2025 00:00:00 GMT
Sunset: Sun, 01 Jan 2026 00:00:00 GMT
Link: </api/v2/users>; rel="successor-version"Authentication & Authorization
API Key Authentication
// Request Header
Authorization: ApiKey sk_live_abc123xyz
// Or Query Parameter (less secure)
GET /api/v1/users?api_key=sk_live_abc123xyzJWT (Bearer Token)
// Request Header
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
// Token structure
{
"header": {
"alg": "RS256",
"typ": "JWT"
},
"payload": {
"sub": "user-123",
"iat": 1705312200,
"exp": 1705315800,
"scope": "read:users write:users"
}
}OAuth 2.0 Flows
Rate Limiting
Headers
HTTP/1.1 200 OK
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 999
X-RateLimit-Reset: 1705316400Rate Limit Response
// 429 Too Many Requests
{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded. Try again in 60 seconds.",
"retryAfter": 60
}
}Strategies
| Strategy | Description | Use Case |
|---|---|---|
| Fixed Window | X requests per minute | Simple, predictable |
| Sliding Window | Rolling time window | Smoother limits |
| Token Bucket | Tokens replenish over time | Burst-friendly |
| Leaky Bucket | Constant output rate | Consistent load |
API Documentation
OpenAPI Specification
openapi: 3.0.3
info:
title: User Management API
version: 1.0.0
description: API for managing users
paths:
/users:
get:
summary: List all users
operationId: listUsers
parameters:
- name: page
in: query
schema:
type: integer
default: 1
- name: limit
in: query
schema:
type: integer
default: 20
maximum: 100
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/UserList'
components:
schemas:
User:
type: object
properties:
id:
type: string
email:
type: string
format: email
name:
type: string
required:
- id
- emailDocumentation Tools
| Tool | Type | Features |
|---|---|---|
| Swagger UI | Interactive | Try-it-out, code samples |
| Redoc | Reference | Clean layout, search |
| Stoplight | Platform | Design-first, mock servers |
| Postman | Collection | Testing, automation |
Error Handling
Error Response Structure
interface ApiError {
error: {
code: string; // Machine-readable code
message: string; // Human-readable message
details?: { // Specific error details
field?: string;
message: string;
value?: any;
}[];
documentation?: string; // Link to error docs
requestId: string; // For support reference
};
}Common Error Codes
| Code | HTTP Status | Description |
|---|---|---|
VALIDATION_ERROR | 400 | Invalid request data |
AUTHENTICATION_REQUIRED | 401 | Missing or invalid auth |
PERMISSION_DENIED | 403 | Insufficient permissions |
RESOURCE_NOT_FOUND | 404 | Resource doesn't exist |
RESOURCE_CONFLICT | 409 | Conflicting state |
RATE_LIMIT_EXCEEDED | 429 | Too many requests |
INTERNAL_ERROR | 500 | Server error |
Security Best Practices
Transport Security
- Always use HTTPS
- Enforce HSTS headers
- Use TLS 1.2 or higher
Input Validation
// Validate and sanitize all inputs
const schema = z.object({
email: z.string().email().max(255),
name: z.string().min(1).max(100),
role: z.enum(['user', 'admin']),
});
const validated = schema.parse(request.body);Output Security
// Security headers
res.setHeader('X-Content-Type-Options', 'nosniff');
res.setHeader('X-Frame-Options', 'DENY');
res.setHeader('Content-Security-Policy', "default-src 'self'");CORS Configuration
const corsOptions = {
origin: ['https://app.example.com'],
methods: ['GET', 'POST', 'PUT', 'DELETE'],
allowedHeaders: ['Content-Type', 'Authorization'],
credentials: true,
maxAge: 86400, // 24 hours
};API Design Checklist
Naming & Structure
- Resource names are nouns (not verbs)
- URLs are lowercase with hyphens
- Consistent plural/singular usage
- Logical resource hierarchy
Functionality
- Proper HTTP methods used
- Appropriate status codes returned
- Pagination for list endpoints
- Filtering and sorting supported
Security
- Authentication required for protected endpoints
- Authorization checked on every request
- Input validation on all endpoints
- Rate limiting implemented
- CORS configured correctly
Documentation
- OpenAPI specification complete
- Error codes documented
- Authentication explained
- Examples provided
Operations
- Versioning strategy defined
- Deprecation policy published
- Health check endpoint exists
- Monitoring in place
Related Resources
Compliance
This section fulfills ISO 13485 requirements for design outputs (7.3.4) and design inputs (7.3.3), and ISO 27001 requirements for secure architecture (A.8.27), application security requirements (A.8.26), and access control (A.5.15).
How is this guide?
Last updated on