API Design Patterns
Comprehensive guide to REST API design patterns commonly used in GISE methodology. These patterns ensure consistency, scalability, and maintainability across all API implementations.
Core Design Principles
1. Resource-Oriented Design
Design APIs around business resources rather than actions:
# Good: Resource-oriented
GET /users # List users
POST /users # Create user
GET /users/{id} # Get specific user
PUT /users/{id} # Update user
DELETE /users/{id} # Delete user
# Bad: Action-oriented
POST /createUser # Avoid action-based URLs
POST /getUserById # Avoid RPC-style endpoints
POST /updateUserName # Too specific operations
2. Consistent URL Structure
# Collection patterns
GET /projects # List all projects
POST /projects # Create new project
# Resource patterns
GET /projects/{id} # Get specific project
PUT /projects/{id} # Replace entire project
PATCH /projects/{id} # Partial update
DELETE /projects/{id} # Delete project
# Nested resource patterns
GET /projects/{id}/tasks # List project tasks
POST /projects/{id}/tasks # Create task in project
GET /projects/{id}/tasks/{taskId} # Get specific task
3. HTTP Method Usage
| Method | Purpose | Idempotent | Safe |
|---|---|---|---|
| GET | Retrieve data | ✅ | ✅ |
| POST | Create resource | ❌ | ❌ |
| PUT | Replace resource | ✅ | ❌ |
| PATCH | Partial update | ❌ | ❌ |
| DELETE | Remove resource | ✅ | ❌ |
Request/Response Patterns
1. Standard Response Envelope
{
"data": {
"id": "user-123",
"name": "John Doe",
"email": "john@example.com"
},
"meta": {
"timestamp": "2024-01-15T10:30:00Z",
"requestId": "req-abc123",
"version": "1.0"
}
}
2. Error Response Format
{
"error": {
"code": "VALIDATION_ERROR",
"message": "The request data is invalid",
"details": [
{
"field": "email",
"message": "Email address is required",
"code": "REQUIRED"
},
{
"field": "password",
"message": "Password must be at least 8 characters",
"code": "MIN_LENGTH"
}
],
"requestId": "req-abc123",
"timestamp": "2024-01-15T10:30:00Z"
}
}
3. Pagination Patterns
Offset-based Pagination
// Request
GET /users?page=2&limit=20
// Response
{
"data": [...],
"pagination": {
"page": 2,
"limit": 20,
"total": 157,
"totalPages": 8,
"hasNext": true,
"hasPrevious": true
}
}
Cursor-based Pagination
// Request
GET /users?cursor=eyJpZCI6MTIzfQ&limit=20
// Response
{
"data": [...],
"pagination": {
"limit": 20,
"hasNext": true,
"nextCursor": "eyJpZCI6MTQzfQ",
"prevCursor": "eyJpZCI6MTAzfQ"
}
}
Authentication Patterns
1. JWT Bearer Token
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
POST /api/auth/login
Content-Type: application/json
{
"email": "user@example.com",
"password": "securepassword"
}
// Response
{
"data": {
"accessToken": "eyJhbGciOiJIUzI1NiIs...",
"refreshToken": "def50200e54b3b...",
"expiresIn": 900,
"tokenType": "Bearer"
}
}
2. API Key Authentication
X-API-Key: your-api-key-here
# or
Authorization: ApiKey your-api-key-here
Filtering and Querying
1. Query Parameters
# Simple filtering
GET /tasks?status=completed&priority=high
# Date range filtering
GET /orders?createdAfter=2024-01-01&createdBefore=2024-01-31
# Multiple values (array format)
GET /products?category=electronics,books&tags=featured,sale
# Search
GET /users?search=john&searchFields=name,email
2. Advanced Filtering
# Comparison operators
GET /products?price[gte]=10&price[lte]=100
# Logical operators
GET /tasks?filter=status:completed AND priority:high
# Field selection (sparse fieldsets)
GET /users?fields=id,name,email
# Including related data
GET /orders?include=items,customer,shipping
Sorting Patterns
# Single field sorting
GET /users?sort=createdAt
GET /users?sort=-createdAt # Descending (with minus prefix)
# Multiple field sorting
GET /users?sort=lastName,firstName
GET /users?sort=-priority,createdAt
# Alternative syntax
GET /users?sort=createdAt&order=desc
Versioning Strategies
1. URL Path Versioning
GET /v1/users
GET /v2/users
2. Header Versioning
Accept: application/vnd.api+json;version=1
API-Version: 1.0
3. Query Parameter Versioning
GET /users?version=1.0
Status Code Patterns
Success Codes
| Code | Usage | Example |
|---|---|---|
| 200 | Successful GET, PUT, PATCH | Updated user successfully |
| 201 | Successful POST (created) | User created successfully |
| 202 | Accepted (async processing) | File upload queued |
| 204 | Successful DELETE | User deleted (no content) |
Error Codes
| Code | Usage | Example |
|---|---|---|
| 400 | Bad Request | Invalid JSON or missing fields |
| 401 | Unauthorized | Missing or invalid authentication |
| 403 | Forbidden | Insufficient permissions |
| 404 | Not Found | Resource doesn't exist |
| 409 | Conflict | Duplicate email address |
| 422 | Unprocessable Entity | Validation errors |
| 429 | Too Many Requests | Rate limit exceeded |
| 500 | Internal Server Error | Unexpected server error |
Content Negotiation
Request Headers
Content-Type: application/json
Accept: application/json
Accept-Language: en-US,en;q=0.9
Accept-Encoding: gzip, deflate
Response Headers
Content-Type: application/json; charset=utf-8
Content-Length: 1234
Cache-Control: public, max-age=3600
ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"
Last-Modified: Wed, 15 Jan 2024 10:30:00 GMT
Caching Strategies
1. HTTP Caching Headers
# Response headers
Cache-Control: public, max-age=3600, s-maxage=7200
ETag: "version-123"
Last-Modified: Wed, 15 Jan 2024 10:30:00 GMT
# Conditional requests
If-None-Match: "version-123"
If-Modified-Since: Wed, 15 Jan 2024 10:30:00 GMT
2. Cache Patterns
# Static data (rarely changes)
Cache-Control: public, max-age=86400 # 24 hours
# Dynamic data (changes frequently)
Cache-Control: private, max-age=300 # 5 minutes
# No caching for sensitive data
Cache-Control: no-cache, no-store, must-revalidate
Rate Limiting
Headers
X-RateLimit-Limit: 1000 # Requests per window
X-RateLimit-Remaining: 500 # Remaining in current window
X-RateLimit-Reset: 1642680000 # Reset time (Unix timestamp)
X-RateLimit-Window: 3600 # Window duration in seconds
Response for Rate Limit Exceeded
HTTP/1.1 429 Too Many Requests
Retry-After: 3600
{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded. Try again in 1 hour.",
"retryAfter": 3600
}
}
Webhook Patterns
1. Webhook Registration
POST /webhooks
{
"url": "https://your-app.com/webhooks/orders",
"events": ["order.created", "order.updated"],
"secret": "your-webhook-secret",
"active": true
}
2. Webhook Payload
POST https://your-app.com/webhooks/orders
X-Webhook-Signature: sha256=hash
Content-Type: application/json
{
"event": "order.created",
"timestamp": "2024-01-15T10:30:00Z",
"data": {
"id": "order-123",
"amount": 99.99,
"status": "pending"
}
}
Bulk Operations
Batch Processing
POST /users/batch
{
"operations": [
{
"method": "POST",
"path": "/users",
"body": {"name": "John", "email": "john@example.com"}
},
{
"method": "PUT",
"path": "/users/123",
"body": {"name": "Jane Doe"}
}
]
}
Bulk Updates
PATCH /users/bulk
{
"filter": {"status": "inactive"},
"update": {"status": "archived"}
}
File Upload Patterns
1. Direct Upload
POST /files
Content-Type: multipart/form-data
file=@document.pdf
metadata={"title": "Important Document"}
2. Presigned URL Upload
# Step 1: Get upload URL
POST /files/upload-url
{
"filename": "document.pdf",
"contentType": "application/pdf"
}
# Response
{
"uploadUrl": "https://storage.example.com/upload/...",
"fileId": "file-123"
}
# Step 2: Upload directly to storage
PUT https://storage.example.com/upload/...
Content-Type: application/pdf
[file content]
# Step 3: Confirm upload
POST /files/file-123/confirm
Integration with GISE Phases
Design Phase Usage
- Define API contracts before implementation
- Establish consistent patterns across services
- Plan authentication and authorization flows
- Design error handling strategies
Development Phase Application
- Use patterns to guide implementation
- Implement standardized middleware
- Create reusable validation schemas
- Build consistent error handling
Testing Integration
- Generate test cases from API patterns
- Validate implementations against standards
- Create automated contract testing
- Monitor API performance and usage
Common Anti-Patterns to Avoid
1. Inconsistent Naming
# Bad: Mixed conventions
GET /users # plural
GET /user/profile # singular
GET /getUserTasks # camelCase with verb
# Good: Consistent plural nouns
GET /users
GET /users/profile
GET /users/tasks
2. Overly Nested URLs
# Bad: Too deeply nested
GET /companies/123/departments/456/teams/789/members
# Good: Shallow nesting with query params
GET /members?teamId=789
3. Exposing Internal IDs
# Bad: Database-specific details
{
"user_id": 12345,
"internal_db_id": "tbl_users_12345"
}
# Good: Clean, external identifiers
{
"id": "user-abc123",
"userId": "user-abc123"
}
These patterns provide a foundation for building consistent, maintainable APIs that integrate seamlessly with the GISE methodology.