When you ask AI to help design APIs, certain patterns emerge consistently. These aren't arbitrary preferences—they're patterns that have proven successful across thousands of APIs. Here's what AI recommends and why.
Pattern 1: Consistent Resource Naming#
What AI Recommends#
# Consistent, predictable resource paths
GET /users # List users
POST /users # Create user
GET /users/:id # Get user
PUT /users/:id # Update user
DELETE /users/:id # Delete user
GET /users/:id/orders # User's orders
GET /orders/:id # Specific order
Why It Works#
- Predictability: Developers can guess endpoints without documentation
- Tooling support: REST clients can generate methods automatically
- Mental model: Clear hierarchy aids understanding
- Discoverability: Logical structure reveals available operations
Anti-Pattern to Avoid#
# Inconsistent, confusing paths
GET /getUsers
POST /user/create
GET /fetchUser/:id
POST /users/:id/update
GET /user-orders/:userId
Pattern 2: Envelope Responses#
What AI Recommends#
1// Consistent response structure
2interface ApiResponse<T> {
3 data: T;
4 meta?: {
5 pagination?: PaginationInfo;
6 timestamp: string;
7 requestId: string;
8 };
9 errors?: ApiError[];
10}
11
12// Success response
13{
14 "data": {
15 "id": "123",
16 "name": "John"
17 },
18 "meta": {
19 "timestamp": "2024-01-15T10:30:00Z",
20 "requestId": "req_abc123"
21 }
22}
23
24// Error response
25{
26 "data": null,
27 "errors": [
28 {
29 "code": "VALIDATION_ERROR",
30 "message": "Email is invalid",
31 "field": "email"
32 }
33 ],
34 "meta": {
35 "timestamp": "2024-01-15T10:30:00Z",
36 "requestId": "req_abc123"
37 }
38}Why It Works#
- Consistency: Same structure for all responses
- Extension: Add metadata without breaking clients
- Debugging: Request IDs enable tracing
- Error handling: Structured errors enable programmatic handling
Pattern 3: Meaningful HTTP Status Codes#
What AI Recommends#
200 OK - Successful GET, PUT, PATCH, or DELETE
201 Created - Successful POST creating a resource
204 No Content - Successful DELETE with no response body
400 Bad Request - Invalid request syntax or parameters
401 Unauthorized - Missing or invalid authentication
403 Forbidden - Valid auth but insufficient permissions
404 Not Found - Resource doesn't exist
409 Conflict - Resource conflict (duplicate, version mismatch)
422 Unprocessable - Valid syntax but semantic errors
429 Too Many - Rate limit exceeded
500 Server Error - Unexpected server failure
503 Unavailable - Temporary unavailability
Why It Works#
- HTTP semantics: Works with proxies, caches, monitoring
- Quick triage: Status code indicates issue category
- Client handling: Different status codes trigger different handlers
Anti-Pattern to Avoid#
// Everything returns 200
{
"status": 200,
"success": false,
"error": "User not found"
}
Pattern 4: Pagination with Cursors#
What AI Recommends#
1// Cursor-based pagination
2GET /orders?cursor=eyJpZCI6MTIzfQ&limit=20
3
4{
5 "data": [...],
6 "meta": {
7 "pagination": {
8 "cursor": "eyJpZCI6MTQzfQ",
9 "hasMore": true,
10 "limit": 20
11 }
12 }
13}Why It Works#
- Stable: No issues with inserts/deletes during pagination
- Performant: Cursor lookups are O(1), not O(n) like offset
- Scalable: Works with millions of records
- Simple: No counting total rows (expensive operation)
When Offset Is Acceptable#
- Small, stable datasets
- UI requires "go to page 5" functionality
- Sorting by user-controlled fields
Pattern 5: Versioning Strategy#
What AI Recommends#
# URL versioning for major changes
GET /v1/users
GET /v2/users
# Headers for minor variations
Accept: application/json; version=1.1
# Sunset headers for deprecation
Sunset: Sat, 31 Dec 2024 23:59:59 GMT
Deprecation: true
Why It Works#
- URL versioning: Clear, cacheable, easy to test
- Header versioning: Fine-grained control without URL clutter
- Sunset headers: Standard way to communicate deprecation
Pattern 6: Idempotency Keys#
What AI Recommends#
1// Client sends idempotency key
2POST /orders
3Idempotency-Key: order_12345_user_67890
4
5// Server handles duplicates gracefully
6async function createOrder(req) {
7 const key = req.headers['idempotency-key'];
8
9 // Check if already processed
10 const existing = await cache.get(`idempotency:${key}`);
11 if (existing) {
12 return existing; // Return cached response
13 }
14
15 // Process request
16 const result = await processOrder(req.body);
17
18 // Cache for future requests
19 await cache.set(`idempotency:${key}`, result, '24h');
20
21 return result;
22}Why It Works#
- Safe retries: Network failures don't cause duplicate orders
- Simple client: Retry without tracking state
- Debugging: Key links related requests
Pattern 7: Rate Limiting Headers#
What AI Recommends#
HTTP/1.1 200 OK
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1609459200
X-RateLimit-Policy: 100;w=3600
HTTP/1.1 429 Too Many Requests
Retry-After: 3600
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
Why It Works#
- Transparency: Clients know their limits
- Adaptive behavior: Clients can throttle before hitting limits
- Debugging: Clear information about rate limit state
Pattern 8: Filtering and Sorting#
What AI Recommends#
# Simple filtering
GET /products?category=electronics&inStock=true
# Comparison operators
GET /products?price[gte]=100&price[lte]=500
# Sorting
GET /products?sort=-createdAt,name
# Field selection
GET /products?fields=id,name,price
Why It Works#
- Intuitive: Familiar query parameter syntax
- Flexible: Supports complex queries without complexity
- Efficient: Field selection reduces payload size
- Cacheable: Consistent URL structure
Pattern 9: Bulk Operations#
What AI Recommends#
1// Batch request
2POST /batch
3{
4 "operations": [
5 { "method": "POST", "path": "/users", "body": {...} },
6 { "method": "PUT", "path": "/users/123", "body": {...} },
7 { "method": "DELETE", "path": "/users/456" }
8 ]
9}
10
11// Batch response
12{
13 "results": [
14 { "status": 201, "body": {...} },
15 { "status": 200, "body": {...} },
16 { "status": 204 }
17 ]
18}
19
20// Or: Bulk create
21POST /users/bulk
22{
23 "users": [{...}, {...}, {...}]
24}Why It Works#
- Efficiency: One request instead of many
- Atomicity: Can be made transactional
- Reduced latency: Fewer round trips
Pattern 10: Health and Status Endpoints#
What AI Recommends#
GET /health
{
"status": "healthy",
"version": "1.2.3",
"checks": {
"database": "healthy",
"cache": "healthy",
"externalApi": "degraded"
}
}
GET /ready
{
"ready": true
}
Why It Works#
- Operations: Clear signals for load balancers and monitoring
- Debugging: Quick status check
- Kubernetes: Separate liveness and readiness probes
Implementing These Patterns#
Ask AI for help implementing any of these patterns:
Implement cursor-based pagination for this Express endpoint:
[paste endpoint code]
Requirements:
- Use base64-encoded cursor
- Support 'limit' parameter (default 20, max 100)
- Return hasMore boolean
- Handle invalid cursors gracefully
Conclusion#
These patterns emerge consistently in AI recommendations because they solve real problems. They're not theoretical ideals—they're practical solutions refined through widespread use.
When designing your API, use these patterns as a foundation. They'll save you from common pitfalls and create an API that's pleasant to use, easy to maintain, and ready to scale.