Skip to main content

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

MethodPurposeIdempotentSafe
GETRetrieve data
POSTCreate resource
PUTReplace resource
PATCHPartial update
DELETERemove 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

CodeUsageExample
200Successful GET, PUT, PATCHUpdated user successfully
201Successful POST (created)User created successfully
202Accepted (async processing)File upload queued
204Successful DELETEUser deleted (no content)

Error Codes

CodeUsageExample
400Bad RequestInvalid JSON or missing fields
401UnauthorizedMissing or invalid authentication
403ForbiddenInsufficient permissions
404Not FoundResource doesn't exist
409ConflictDuplicate email address
422Unprocessable EntityValidation errors
429Too Many RequestsRate limit exceeded
500Internal Server ErrorUnexpected 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.