Build scalable, secure, and developer-friendly APIs with proven patterns and best practices
Design APIs with developer experience as the primary focus - intuitive naming, consistent patterns, and comprehensive documentation
Choose REST for simple, cacheable APIs; GraphQL for complex data relationships and mobile applications
Implement robust authentication (JWT for stateless, OAuth for third-party) and always use HTTPS
Plan for versioning from day one and use OpenAPI specifications for contract-first development
Poor API design costs developers 23% more integration time and reduces adoption by 40%
Well-designed APIs reduce server load by 35% and improve response times by up to 50%
Modern APIs must handle 10x more requests than 5 years ago while maintaining sub-200ms response times
Factor | REST | GraphQL |
---|---|---|
Query Flexibility | Fixed endpoints | Single endpoint, flexible queries |
Caching | HTTP caching built-in | Complex caching strategies needed |
Learning Curve | Familiar HTTP methods | New query language to learn |
Over-fetching | Common issue | Eliminated by design |
Real-time | WebSockets/SSE needed | Built-in subscriptions |
Best for | Simple APIs, caching-heavy | Complex data relationships |
Separation of concerns between user interface and data storage
Each request must contain all information needed to understand it
Responses should be cacheable to improve network efficiency
Consistent resource identification and manipulation methods
Stateless auth, microservices
Third-party integrations
Internal services
Pros
Clear, cacheable, easy to implement
Cons
URL proliferation, resource duplication
Pros
Clean URLs, flexible
Cons
Complex implementation, harder to test
Pros
RESTful, granular control
Cons
Developer confusion, complex
// pages/api/users.js
export default async function handler(req, res) {
if (req.method !== 'GET') {
return res.status(405).json({
error: 'Method not allowed',
message: 'Only GET requests are supported'
});
}
try {
const { page = 1, limit = 10 } = req.query;
const users = await getUsersPaginated({
page: parseInt(page),
limit: Math.min(parseInt(limit), 100) // Max 100 per page
});
res.status(200).json({
data: users.items,
pagination: {
page: users.page,
limit: users.limit,
total: users.total,
totalPages: Math.ceil(users.total / users.limit),
hasNext: users.page < Math.ceil(users.total / users.limit),
hasPrev: users.page > 1
},
meta: {
timestamp: new Date().toISOString(),
version: '1.0'
}
});
} catch (error) {
console.error('Users API Error:', error);
res.status(500).json({
error: 'Internal server error',
message: 'Unable to fetch users'
});
}
}
interface ApiResponse<T> {
data: T;
pagination?: {
page: number;
limit: number;
total: number;
totalPages: number;
hasNext: boolean;
hasPrev: boolean;
};
meta?: {
timestamp: string;
version: string;
};
error?: string;
}
class ApiClient {
private baseURL: string;
private token?: string;
constructor(baseURL: string, token?: string) {
this.baseURL = baseURL;
this.token = token;
}
private async request<T>(
endpoint: string,
options: RequestInit = {}
): Promise<ApiResponse<T>> {
const url = `${this.baseURL}${endpoint}`;
const response = await fetch(url, {
...options,
headers: {
'Content-Type': 'application/json',
...(this.token && { 'Authorization': `Bearer ${this.token}` }),
...options.headers
}
});
if (!response.ok) {
throw new Error(`API Error: ${response.status}`);
}
return response.json();
}
async getUsers(page = 1, limit = 10) {
return this.request<User[]>(`/users?page=${page}&limit=${limit}`);
}
async createUser(userData: CreateUserRequest) {
return this.request<User>('/users', {
method: 'POST',
body: JSON.stringify(userData)
});
}
}
openapi: 3.1.0
info:
title: User Management API
version: 1.0.0
description: Modern user management API with authentication
contact:
name: API Support
email: api@example.com
servers:
- url: https://api.example.com/v1
description: Production server
paths:
/users:
get:
summary: List users with pagination
parameters:
- name: page
in: query
schema:
type: integer
minimum: 1
default: 1
- name: limit
in: query
schema:
type: integer
minimum: 1
maximum: 100
default: 10
responses:
'200':
description: Successful response
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/User'
pagination:
$ref: '#/components/schemas/Pagination'
components:
schemas:
User:
type: object
required:
- id
- email
- name
properties:
id:
type: string
format: uuid
email:
type: string
format: email
name:
type: string
minLength: 1
maxLength: 100
createdAt:
type: string
format: date-time
Response Time
Throughput
Error Rate
Availability
200
OK - Request successful201
Created - Resource created204
No Content - Success, no data400
Bad Request - Invalid request401
Unauthorized - Authentication required404
Not Found - Resource missing429
Too Many Requests - Rate limited{
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid request parameters",
"details": [
{
"field": "email",
"message": "Must be a valid email address"
},
{
"field": "age",
"message": "Must be between 18 and 120"
}
],
"timestamp": "2025-08-05T10:30:00Z",
"requestId": "req_123456789"
}
}
Get our comprehensive API Design Checklist and start building better APIs today