Skip to content

bakrsabeeh/api-design-guide

πŸš€ API Design Patterns & Best Practices

A comprehensive, production-ready guide to designing scalable, secure, and developer-friendly APIs. From REST fundamentals to GraphQL, webhooks, async patterns, and enterprise securityβ€”everything you need to build APIs that teams love.

API Design Last Updated License Contributions Welcome


πŸ“š What's Inside

1. REST API Design (Read Full Guide)

  • βœ… URL structure conventions (kebab-case, plural resources)
  • βœ… HTTP methods & status codes (comprehensive reference)
  • βœ… Response envelopes & error handling
  • βœ… Pagination strategies (offset, cursor, keyset)
  • βœ… Filtering, sorting & full-text search
  • βœ… Authentication & authorization patterns
# Quick example: RESTful resource design
GET    /api/v1/users           # List all users
POST   /api/v1/users           # Create new user
GET    /api/v1/users/:id       # Get specific user
PATCH  /api/v1/users/:id       # Update user
DELETE /api/v1/users/:id       # Delete user
GET    /api/v1/users/:id/orders # Get user's orders

2. GraphQL APIs (Read Full Guide)

  • βœ… Schema design best practices
  • βœ… Connection pattern for pagination
  • βœ… Error handling in GraphQL
  • βœ… Query complexity management
  • βœ… N+1 query prevention (DataLoader pattern)
  • βœ… Deprecation & versioning
query GetUser {
  user(id: "usr_123") {
    id
    email
    name
    orders(limit: 10, after: "cursor") {
      edges {
        node { id title }
        cursor
      }
      pageInfo { hasNextPage }
    }
  }
}

3. Webhook Integration (Read Full Guide)

  • βœ… Event design & structure
  • βœ… Idempotency & deduplication
  • βœ… Signature verification (HMAC-SHA256)
  • βœ… Retry logic with exponential backoff
  • βœ… Webhook management endpoints
  • βœ… Event catalog & versioning
// Secure webhook verification
const signature = req.headers["x-webhook-signature"];
const timestamp = req.headers["x-webhook-timestamp"];

const payload = `${timestamp}.${JSON.stringify(req.body)}`;
const expected = crypto
  .createHmac("sha256", WEBHOOK_SECRET)
  .update(payload)
  .digest("hex");

if (crypto.timingSafeEqual(signature, expected)) {
  // Process webhook
}

4. Async & Event-Driven APIs (Read Full Guide)

  • βœ… Long-running operations with status tracking
  • βœ… Server-Sent Events (SSE) for streaming
  • βœ… Message queue patterns
  • βœ… Job polling & progress updates
  • βœ… Eventual consistency handling
// Start async job
POST /api/v1/bulk-import/start
β†’ 202 Accepted { job_id: "job_123", status_url: "/jobs/job_123" }

// Poll for progress
GET /api/v1/bulk-import/job_123
β†’ { status: "processing", progress: 45% }

5. Security Patterns (Read Full Guide)

  • βœ… OAuth 2.0 & OpenID Connect
  • βœ… API Key management
  • βœ… JWT best practices
  • βœ… mTLS (mutual TLS)
  • βœ… Role-based access control (RBAC)
  • βœ… Attribute-based access control (ABAC)
  • βœ… Row-level security & multi-tenancy
  • βœ… Input validation & sanitization
  • βœ… Encryption at rest & in transit
  • βœ… Secrets management
// Secure authentication + authorization
app.get("/api/v1/orders/:id", authenticate, async (req, res) => {
  const order = await Order.findById(req.params.id);
  
  // Ownership check (resource-level authorization)
  if (order.customerId !== req.user.id && !req.user.isAdmin) {
    return res.status(403).json({ error: "forbidden" });
  }
  
  return res.json({ data: order });
});

6. Caching & Performance (Read Full Guide)

  • βœ… HTTP caching headers (Cache-Control, ETag, Last-Modified)
  • βœ… Cache-aside pattern
  • βœ… Cache invalidation strategies
  • βœ… Stale-while-revalidate
  • βœ… Redis implementation patterns
  • βœ… CDN integration
// Smart caching with ETag validation
app.get("/api/v1/products/:id", (req, res) => {
  const etag = generateETag(product);
  
  if (req.get("If-None-Match") === etag) {
    return res.status(304).send();  // Not Modified
  }
  
  res.setHeader("Cache-Control", "public, max-age=3600");
  res.setHeader("ETag", `"${etag}"`);
  res.json({ data: product });
});

7. Observability & Monitoring (Read Full Guide)

  • βœ… Structured logging
  • βœ… Prometheus metrics
  • βœ… Distributed tracing
  • βœ… Performance monitoring
  • βœ… Error tracking & alerting
  • βœ… Business metrics
// Structured logging with context
logger.info({
  timestamp: new Date().toISOString(),
  method: "POST",
  endpoint: "/api/v1/orders",
  status: 201,
  duration_ms: 145,
  user_id: "usr_123",
  order_id: "ord_456",
  amount_usd: 299.99,
});

8. Versioning & Deprecation (Read Full Guide)

  • βœ… URL path versioning
  • βœ… Header-based versioning
  • βœ… Deprecation timelines
  • βœ… Migration guides
  • βœ… Sunset headers
// Proper deprecation handling
app.get("/api/v1/users", (req, res) => {
  res.setHeader("Sunset", "Sat, 01 Jan 2026 00:00:00 GMT");
  res.setHeader("Deprecation", "true");
  res.setHeader(
    "Link",
    '</api/v2/users>; rel="successor-version"'
  );
  // Response...
});

🎯 Quick Start

1. For API Designers

# Clone the repository
git clone https://github.com/yourusername/api-design-guide.git
cd api-design-guide

# Read the main guide
cat GUIDE.md

# Check out specific domains
cat docs/rest-api-design.md
cat docs/security.md
cat docs/webhooks.md

2. Use as Template for Your Project

# Copy the checklist to your project
cp templates/api-design-checklist.md ./API-CHECKLIST.md

# Use the OpenAPI template
cp templates/openapi-template.yaml ./openapi.yaml

# Implement security patterns
cp patterns/security-patterns.ts ./src/middleware/

3. Reference Implementation Examples

# TypeScript/Express example
cat examples/typescript-express/api-server.ts

# Python/FastAPI example
cat examples/python-fastapi/main.py

# Go/Gin example
cat examples/go-gin/main.go

πŸ“ Repository Structure

api-design-guide/
β”œβ”€β”€ README.md                          # This file
β”œβ”€β”€ GUIDE.md                           # Complete comprehensive guide
β”‚
β”œβ”€β”€ docs/                              # Topic-specific guides
β”‚   β”œβ”€β”€ rest-api-design.md
β”‚   β”œβ”€β”€ graphql-design.md
β”‚   β”œβ”€β”€ webhooks.md
β”‚   β”œβ”€β”€ async-apis.md
β”‚   β”œβ”€β”€ security.md
β”‚   β”œβ”€β”€ caching.md
β”‚   β”œβ”€β”€ observability.md
β”‚   β”œβ”€β”€ versioning.md
β”‚   └── error-handling.md
β”‚
β”œβ”€β”€ templates/                         # Ready-to-use templates
β”‚   β”œβ”€β”€ api-design-checklist.md
β”‚   β”œβ”€β”€ openapi-template.yaml
β”‚   β”œβ”€β”€ error-response-schema.json
β”‚   β”œβ”€β”€ webhook-event-template.json
β”‚   └── security-headers-config.ts
β”‚
β”œβ”€β”€ patterns/                          # Code patterns & snippets
β”‚   β”œβ”€β”€ authentication/
β”‚   β”‚   β”œβ”€β”€ jwt-auth.ts
β”‚   β”‚   β”œβ”€β”€ oauth2-flow.ts
β”‚   β”‚   └── api-key-auth.ts
β”‚   β”œβ”€β”€ security/
β”‚   β”‚   β”œβ”€β”€ rate-limiting.ts
β”‚   β”‚   β”œβ”€β”€ input-validation.ts
β”‚   β”‚   └── encryption.ts
β”‚   β”œβ”€β”€ caching/
β”‚   β”‚   β”œβ”€β”€ redis-cache.ts
β”‚   β”‚   └── http-caching.ts
β”‚   └── pagination/
β”‚       β”œβ”€β”€ offset-pagination.ts
β”‚       β”œβ”€β”€ cursor-pagination.ts
β”‚       └── keyset-pagination.ts
β”‚
β”œβ”€β”€ examples/                          # Full working examples
β”‚   β”œβ”€β”€ typescript-express/
β”‚   β”‚   β”œβ”€β”€ package.json
β”‚   β”‚   β”œβ”€β”€ main.ts
β”‚   β”‚   β”œβ”€β”€ routes/
β”‚   β”‚   β”œβ”€β”€ middleware/
β”‚   β”‚   └── schemas/
β”‚   β”œβ”€β”€ python-fastapi/
β”‚   β”‚   β”œβ”€β”€ requirements.txt
β”‚   β”‚   β”œβ”€β”€ main.py
β”‚   β”‚   β”œβ”€β”€ models/
β”‚   β”‚   └── routes/
β”‚   └── go-gin/
β”‚       β”œβ”€β”€ go.mod
β”‚       β”œβ”€β”€ main.go
β”‚       β”œβ”€β”€ handlers/
β”‚       └── models/
β”‚
β”œβ”€β”€ tools/                             # Utilities & testing
β”‚   β”œβ”€β”€ api-validator.js
β”‚   β”œβ”€β”€ webhook-simulator.js
β”‚   β”œβ”€β”€ load-test.js
β”‚   └── security-scanner.js
β”‚
β”œβ”€β”€ checklists/                        # Before-launch checklists
β”‚   β”œβ”€β”€ design-checklist.md
β”‚   β”œβ”€β”€ security-checklist.md
β”‚   β”œβ”€β”€ testing-checklist.md
β”‚   └── deployment-checklist.md
β”‚
└── CONTRIBUTING.md                    # How to contribute

πŸ“š Topics Covered

REST APIs

  • Resource naming conventions
  • HTTP methods & semantics
  • Status codes reference (2xx, 3xx, 4xx, 5xx)
  • Request/response envelopes
  • Error handling & error codes
  • Pagination strategies
  • Filtering & sorting
  • Full-text search
  • Rate limiting
  • Versioning strategies

GraphQL

  • Schema design
  • Query optimization
  • Connection patterns
  • Error handling
  • Deprecation
  • Complexity management
  • DataLoader for N+1 prevention

Webhooks & Events

  • Event design
  • Idempotency & deduplication
  • Signature verification
  • Retry strategies
  • Event catalog
  • Dead letter queues

Security

  • OAuth 2.0 / OpenID Connect
  • API Keys
  • JWT (JSON Web Tokens)
  • mTLS (Mutual TLS)
  • RBAC (Role-Based Access Control)
  • ABAC (Attribute-Based Access Control)
  • Row-level security
  • Input validation & sanitization
  • Encryption (at rest & in transit)
  • Secrets management
  • CORS configuration
  • OWASP Top 10 for APIs

Performance & Caching

  • HTTP caching headers
  • ETag & Last-Modified
  • Cache-Control directives
  • Application-level caching
  • Redis patterns
  • Cache invalidation
  • Stale-while-revalidate

Observability

  • Structured logging
  • Metrics & monitoring
  • Distributed tracing
  • Error tracking
  • Performance monitoring
  • Business metrics

πŸ› οΈ Implementation Examples

TypeScript/Express (Recommended)

import express, { Router } from "express";
import { z } from "zod";

const router = Router();

const createUserSchema = z.object({
  email: z.string().email(),
  name: z.string().min(1).max(100),
});

router.post("/users", async (req, res) => {
  const result = createUserSchema.safeParse(req.body);
  
  if (!result.success) {
    return res.status(422).json({
      error: {
        code: "validation_error",
        message: "Validation failed",
        details: result.error.issues,
      },
    });
  }
  
  const user = await createUser(result.data);
  return res.status(201)
    .setHeader("Location", `/api/v1/users/${user.id}`)
    .json({ data: user });
});

export default router;

Python/FastAPI

from fastapi import FastAPI, HTTPException
from pydantic import BaseModel, EmailStr

app = FastAPI()

class CreateUserRequest(BaseModel):
    email: EmailStr
    name: str

@app.post("/users", status_code=201)
async def create_user(request: CreateUserRequest):
    user = await UserService.create(request.dict())
    return {"data": user}

Go/Gin

func CreateUser(c *gin.Context) {
  var req CreateUserRequest
  if err := c.ShouldBindJSON(&req); err != nil {
    c.JSON(400, gin.H{"error": err.Error()})
    return
  }
  
  user, _ := userService.Create(req)
  c.Header("Location", "/api/v1/users/"+user.ID)
  c.JSON(201, gin.H{"data": user})
}

πŸ”’ Security Checklist

Before deploying any API:

  • HTTPS/TLS enabled (HSTS header set)
  • Authentication implemented
  • Authorization checks in place
  • Input validation & sanitization
  • Rate limiting configured
  • CORS configured appropriately
  • Secrets managed securely (not in code)
  • SQL injection prevention (parameterized queries)
  • XSS prevention (output encoding)
  • CSRF protection
  • Sensitive data not in logs
  • Error messages don't leak implementation details
  • Request/response size limits
  • Dependency vulnerabilities scanned
  • API key rotation mechanism
  • Audit logging enabled
  • Monitoring & alerting in place

πŸ“Š Performance Best Practices

Optimize for Common Cases

βœ… Use pagination (cursor-based for scalability)
βœ… Implement caching (HTTP & app-level)
βœ… Use sparse fieldsets to reduce payloads
βœ… Compress responses (gzip, brotli)
βœ… Index frequently filtered/sorted fields
βœ… Use database query limits
βœ… Monitor slow queries
βœ… Load test before production

Metrics to Track

πŸ“ˆ Response time (p50, p95, p99)
πŸ“ˆ Error rate
πŸ“ˆ Cache hit rate
πŸ“ˆ Database query time
πŸ“ˆ Payload size
πŸ“ˆ Concurrent connections
πŸ“ˆ Rate limit violations
πŸ“ˆ Business metrics (orders/min, revenue/hour, etc.)

πŸ§ͺ Testing Checklist

Unit Tests

βœ… Schema validation (happy path + error cases)
βœ… Business logic
βœ… Authorization checks

Integration Tests

βœ… End-to-end API flow
βœ… Error cases (4xx, 5xx responses)
βœ… Rate limiting
βœ… Pagination
βœ… Filtering & sorting
βœ… Concurrent requests

Security Tests

βœ… Authentication bypass attempts
βœ… Authorization bypasses
βœ… SQL injection
βœ… XSS attacks
βœ… Rate limit evasion
βœ… Large payload handling

Load Tests

βœ… Concurrent users (1K, 10K, 100K)
βœ… Sustained load (24 hours)
βœ… Spike handling
βœ… Memory leaks

🀝 Contributing

We welcome contributions! Here's how:

  1. Fork the repository

    git clone https://github.com/yourusername/api-design-guide.git
  2. Create a branch

    git checkout -b feature/add-websocket-patterns
  3. Make your changes

    • Add patterns, examples, or improvements
    • Follow the existing structure
    • Add comprehensive documentation
  4. Submit a pull request

    • Reference any related issues
    • Describe your changes
    • Include examples if applicable

Contribution Ideas

  • Add more language examples (Rust, Java, C#)
  • Add more real-world case studies
  • Expand security patterns
  • Add monitoring/observability examples
  • Improve documentation
  • Fix typos/improve clarity
  • Add diagrams & visualizations

πŸ“– Learning Resources

Official Specifications

Security

Books

  • "REST API Design Rulebook" by Mark Masse
  • "Building Microservices" by Sam Newman
  • "API Security in Action" by Neil Madden
  • "Designing Data-Intensive Applications" by Martin Kleppmann

Articles


πŸ“ License

This guide is licensed under the MIT License. You're free to use it for any purpose, commercial or personal. See LICENSE for details.


πŸ’¬ Questions & Discussions


πŸ™Œ Acknowledgments

This guide is built on years of API design experience and best practices from:

  • IETF specifications (HTTP, OAuth, etc.)
  • OWASP security guidelines
  • Industry standards (GraphQL, REST Maturity Model)
  • Real-world implementations at scale
  • Community contributions & feedback

πŸ“ˆ Stats

  • Last Updated: January 15, 2025
  • Topics Covered: 8 major categories
  • Code Examples: 50+
  • Patterns & Templates: 40+
  • Contributors: Open to all
  • Stars: ⭐ Please consider starring if this helps you!

Built with ❀️ for developers who care about API quality

Made for developers, by developers.

⬆ Back to top

About

Comprehensive guide to designing scalable, secure APIs

Resources

License

Code of conduct

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors