Skip to main content
โšก Calmops

API Design Best Practices Complete Guide 2026

Introduction

Well-designed APIs are crucial for developer experience and system maintainability. This guide covers API design best practices.

REST API Design

URL Structure

RESTful URL Patterns:
โ”œโ”€โ”€ Resources (nouns, plural)
โ”‚   โ”œโ”€โ”€ /users
โ”‚   โ”œโ”€โ”€ /orders
โ”‚   โ””โ”€โ”€ /products
โ”‚
โ”œโ”€โ”€ Nested Resources
โ”‚   โ”œโ”€โ”€ /users/{id}/orders
โ”‚   โ””โ”€โ”€ /orders/{id}/items
โ”‚
โ”œโ”€โ”€ Actions
โ”‚   โ”œโ”€โ”€ POST /users/{id}/activate
โ”‚   โ””โ”€โ”€ POST /orders/{id}/cancel
โ”‚
โ””โ”€โ”€ Filtering
    โ”œโ”€โ”€ /users?status=active
    โ”œโ”€โ”€ /products?category=electronics&price<100
    โ””โ”€โ”€ /orders?date_from=2026-01-01

HTTP Methods

HTTP Method Usage:
โ”œโ”€โ”€ GET - Retrieve resources
โ”‚   โ””โ”€โ”€ GET /users - List users
โ”‚   โ””โ”€โ”€ GET /users/123 - Get user
โ”‚
โ”œโ”€โ”€ POST - Create new resources
โ”‚   โ””โ”€โ”€ POST /users - Create user
โ”‚
โ”œโ”€โ”€ PUT - Replace entire resource
โ”‚   โ””โ”€โ”€ PUT /users/123 - Replace user
โ”‚
โ”œโ”€โ”€ PATCH - Partial update
โ”‚   โ””โ”€โ”€ PATCH /users/123 - Update user fields
โ”‚
โ””โ”€โ”€ DELETE - Remove resources
    โ””โ”€โ”€ DELETE /users/123 - Delete user

Response Format

// Success Response
{
  "data": {
    "id": "123",
    "type": "user",
    "attributes": {
      "name": "John Doe",
      "email": "[email protected]"
    }
  },
  "meta": {
    "request_id": "abc-123"
  }
}

// Error Response
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid email format",
    "details": [
      {
        "field": "email",
        "message": "Must be a valid email"
      }
    ]
  }
}

Authentication

API Keys

# API Key authentication
class APIKeyAuth:
    def __init__(self, header_name='X-API-Key'):
        self.header_name = header_name
    
    def authenticate(self, request):
        api_key = request.headers.get(self.header_name)
        if not api_key:
            return None
        
        user = self.validate_key(api_key)
        return user
    
    def validate_key(self, key):
        # Look up key in database
        return api_key_db.get(key)

JWT Tokens

import jwt
from datetime import datetime, timedelta

def create_access_token(user_id):
    """Create JWT access token"""
    payload = {
        'sub': user_id,
        'exp': datetime.utcnow() + timedelta(hours=1),
        'iat': datetime.utcnow()
    }
    return jwt.encode(payload, SECRET_KEY, algorithm='HS256')

def verify_token(token):
    """Verify JWT token"""
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=['HS256'])
        return payload['sub']
    except jwt.ExpiredSignatureError:
        return None

Versioning

URL Versioning

API Versioning Strategies:
โ”œโ”€โ”€ URL Path (Recommended)
โ”‚   โ”œโ”€โ”€ /v1/users
โ”‚   โ””โ”€โ”€ /v2/users
โ”‚
โ”œโ”€โ”€ Header
โ”‚   โ”œโ”€โ”€ Accept: application/vnd.api+json;version=2
โ”‚   โ””โ”€โ”€ X-API-Version: 2
โ”‚
โ””โ”€โ”€ Query Parameter
    โ”œโ”€โ”€ /users?version=2
    โ””โ”€โ”€ Not recommended

Rate Limiting

# Rate limiting with Redis
class RateLimiter:
    def __init__(self, redis_client):
        self.redis = redis_client
    
    def is_allowed(self, identifier, limit, window):
        """Check if request is allowed"""
        key = f"rate_limit:{identifier}"
        
        current = self.redis.get(key)
        if current is None:
            self.redis.setex(key, window, 1)
            return True
        
        if int(current) >= limit:
            return False
        
        self.redis.incr(key)
        return True

Documentation

OpenAPI/Swagger

OpenAPI Specification:
openapi: 3.0.0
info:
  title: User API
  version: 1.0.0
paths:
  /users:
    get:
      summary: List users
      parameters:
        - name: limit
          in: query
          schema:
            type: integer
            default: 20
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/User'

Conclusion

Good API design improves developer experience and system maintainability. Follow these practices consistently.

Comments