Good API design is invisible. Bad API design causes endless support tickets. Here's what I've learned designing APIs at Google.
URL Structure
// Good: nouns, not verbs
GET /api/v1/users // List users
GET /api/v1/users/123 // Get user
POST /api/v1/users // Create user
PUT /api/v1/users/123 // Replace user
PATCH /api/v1/users/123 // Partial update
DELETE /api/v1/users/123 // Delete user
// Bad
GET /api/getUsers
POST /api/createUser
POST /api/deleteUser/123Response Format
// Success
{
"data": { "id": "123", "name": "Rahul" },
"meta": { "requestId": "abc-123" }
}
// Error
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Email is required",
"details": [
{ "field": "email", "message": "Must be a valid email address" }
]
},
"meta": { "requestId": "abc-124" }
}
// List with pagination
{
"data": [...],
"pagination": {
"page": 1,
"pageSize": 20,
"totalCount": 150,
"totalPages": 8
}
}Pagination Strategies
| Strategy | Pros | Cons |
|---|---|---|
| Offset/Limit | Simple, random access | Inconsistent with inserts/deletes |
| Cursor-based | Consistent, performant | No random page access |
| Keyset | Very fast, consistent | Requires sortable unique column |
Versioning
// URL versioning (most common)
/api/v1/users
/api/v2/users
// Header versioning
Accept: application/vnd.myapi.v2+json
// Query parameter
/api/users?version=2Rate Limiting Headers
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1699000000
Retry-After: 60Golden Rules
- Be consistent (naming, casing, error format)
- Use HTTP status codes correctly (don't return 200 for errors)
- Include request IDs for debugging
- Document everything (OpenAPI/Swagger)
- Version from day one