Skip to main content

API Design Guidelines

RESTful Design Principles​

1. Resource Naming​

# Good Examples
/api/v1/users # List users
/api/v1/users/{id} # Single user
/api/v1/users/{id}/posts # User's posts
/api/v1/teams/{id}/members # Team members

# Bad Examples
/api/v1/getUsers # Uses verb
/api/v1/user_profiles # Inconsistent naming
/api/v1/teamMembers # Not hierarchical

2. HTTP Methods Usage​

MethodUsageExampleSuccess Code
GETRead/RetrieveGET /api/users200 OK
POSTCreatePOST /api/users201 Created
PUTUpdate/ReplacePUT /api/users/123200 OK
PATCHPartial UpdatePATCH /api/users/123200 OK
DELETEDeleteDELETE /api/users/123204 No Content

Request/Response Format​

1. Request Format​

// POST /api/v1/users
{
"name": "John Doe",
"email": "[email protected]",
"role": "user"
}

2. Success Response​

// 200 OK
{
"data": {
"id": "123",
"name": "John Doe",
"email": "[email protected]",
"role": "user",
"createdAt": "2025-02-04T00:00:00Z"
},
"meta": {
"timestamp": "2025-02-04T00:00:00Z"
}
}

3. Error Response​

// 400 Bad Request
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid request parameters",
"details": {
"email": "Must be a valid email address"
}
},
"meta": {
"timestamp": "2025-02-04T00:00:00Z"
}
}

4. Collection Response​

// GET /api/v1/users
{
"data": [
{
"id": "123",
"name": "John Doe",
"email": "[email protected]"
}
],
"meta": {
"pagination": {
"total": 100,
"page": 1,
"perPage": 10,
"totalPages": 10
},
"timestamp": "2025-02-04T00:00:00Z"
}
}

Status Codes​

Success Codes​

  • 200: OK (Success)
  • 201: Created (Resource created)
  • 204: No Content (Success, no response body)

Client Error Codes​

  • 400: Bad Request (Invalid input)
  • 401: Unauthorized (Not authenticated)
  • 403: Forbidden (Not authorized)
  • 404: Not Found (Resource not found)
  • 409: Conflict (Resource conflict)
  • 422: Unprocessable Entity (Validation failed)

Server Error Codes​

  • 500: Internal Server Error
  • 502: Bad Gateway
  • 503: Service Unavailable
  • 504: Gateway Timeout

Authentication & Authorization​

1. JWT Authentication​

interface JWTPayload {
sub: string; // Subject (user ID)
iat: number; // Issued at
exp: number; // Expiration time
scope: string[]; // Permissions
}

2. OAuth2 Flow​

  1. Client Registration
  2. Authorization Request
  3. User Consent
  4. Token Exchange
  5. Resource Access

3. API Keys​

// Request Header
Authorization: Bearer <api_key>

// Query Parameter (less secure)
/api/v1/users?api_key=<api_key>

Versioning​

1. URL Versioning​

/api/v1/users
/api/v2/users

2. Header Versioning​

Accept: application/vnd.company.api+json;version=1

3. Query Parameter​

/api/users?version=1

Rate Limiting​

1. Headers​

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1612345678

2. Response (429 Too Many Requests)​

{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded",
"details": {
"retryAfter": 3600
}
}
}

Documentation​

1. OpenAPI Specification​

openapi: 3.0.0
info:
title: API Documentation
version: 1.0.0
paths:
/users:
get:
summary: List users
parameters:
- name: page
in: query
schema:
type: integer
responses:
'200':
description: Success

2. API Documentation Example​

/**
* Create a new user
* @route POST /api/v1/users
* @param {Object} body.required - User data
* @param {string} body.name.required - User's full name
* @param {string} body.email.required - User's email
* @returns {Object} 201 - Created user object
* @returns {Error} 400 - Validation error
*/

Security​

1. Input Validation​

interface CreateUserRequest {
name: string;
email: string;
role: 'admin' | 'user';
}

function validateCreateUser(data: unknown): CreateUserRequest {
// Validation logic
}

2. Security Headers​

app.use(helmet());  // Adds security headers

// Custom headers
res.setHeader('Content-Security-Policy', "default-src 'self'");
res.setHeader('X-Content-Type-Options', 'nosniff');
res.setHeader('X-Frame-Options', 'DENY');

3. CORS Configuration​

app.use(cors({
origin: ['https://example.com'],
methods: ['GET', 'POST', 'PUT', 'DELETE'],
allowedHeaders: ['Content-Type', 'Authorization'],
credentials: true
}));