Netspective Logo
Design

API Design

Best practices for designing robust, maintainable APIs

APIs (Application Programming Interfaces) are the contracts between software components. Good API design is crucial for maintainability, usability, and the long-term success of your software.

API Contract Components

Based on industry best practices, an API contract includes:

ComponentPurpose
Terms of ServiceLegal usage terms
Privacy PolicyData handling commitments
SLA / Service AccordQuality and reliability expectations
Interface LicenseAPI usage rights
Data LicenseData usage rights
Deprecation PolicyEnd-of-life procedures
Rate LimitsUsage constraints
VersioningChange management

REST API Design Principles

Resource-Based URLs

Good:
GET    /users                    # List users
GET    /users/123               # Get user 123
POST   /users                   # Create user
PUT    /users/123               # Update user 123
DELETE /users/123               # Delete user 123
GET    /users/123/orders        # Get orders for user 123

Bad:
GET    /getUsers
POST   /createUser
GET    /getUserOrders?userId=123
POST   /deleteUser

HTTP Methods

MethodPurposeIdempotentSafe
GETRetrieve resourceYesYes
POSTCreate resourceNoNo
PUTReplace resourceYesNo
PATCHPartial updateNoNo
DELETERemove resourceYesNo

HTTP Status Codes

Success:
200 OK              - Request succeeded
201 Created         - Resource created
204 No Content      - Success, no response body

Client Errors:
400 Bad Request     - Invalid request syntax
401 Unauthorized    - Authentication required
403 Forbidden       - Access denied
404 Not Found       - Resource doesn't exist
409 Conflict        - Resource conflict
422 Unprocessable   - Validation failed
429 Too Many Req    - Rate limit exceeded

Server Errors:
500 Internal Error  - Server error
502 Bad Gateway     - Upstream error
503 Unavailable     - Service unavailable
504 Gateway Timeout - Upstream timeout

Request/Response Design

Request Format

// POST /api/v1/users
{
  "email": "john@example.com",
  "name": "John Doe",
  "role": "user",
  "preferences": {
    "notifications": true,
    "theme": "dark"
  }
}

Response Format

// Success Response
{
  "data": {
    "id": "user-123",
    "email": "john@example.com",
    "name": "John Doe",
    "role": "user",
    "createdAt": "2024-01-15T10:30:00Z",
    "updatedAt": "2024-01-15T10:30:00Z"
  },
  "meta": {
    "requestId": "req-abc-123"
  }
}

// Error Response
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Request validation failed",
    "details": [
      {
        "field": "email",
        "message": "Invalid email format"
      }
    ]
  },
  "meta": {
    "requestId": "req-abc-124"
  }
}

Pagination

// Request
GET /api/v1/users?page=2&limit=20

// Response
{
  "data": [...],
  "pagination": {
    "page": 2,
    "limit": 20,
    "total": 150,
    "totalPages": 8,
    "hasNext": true,
    "hasPrev": true
  },
  "links": {
    "self": "/api/v1/users?page=2&limit=20",
    "first": "/api/v1/users?page=1&limit=20",
    "prev": "/api/v1/users?page=1&limit=20",
    "next": "/api/v1/users?page=3&limit=20",
    "last": "/api/v1/users?page=8&limit=20"
  }
}

API Versioning

Strategies

StrategyExampleProsCons
URL Path/api/v1/usersClear, easy to implementURL changes
Query Param/api/users?version=1FlexibleEasy to miss
HeaderAccept: application/vnd.api.v1+jsonClean URLsLess visible
Media TypeContent-Type: application/vnd.api.v1+jsonSemanticComplex
/api/v1/users    # Version 1
/api/v2/users    # Version 2 (breaking changes)

Deprecation Timeline

Timeline:
├── Announce deprecation (6 months before sunset)
├── Add deprecation header to responses
├── Provide migration guide
├── Monitor usage of deprecated version
├── Send reminders to active consumers
└── Sunset old version
// Deprecation response header
HTTP/1.1 200 OK
Deprecation: Sun, 01 Jul 2025 00:00:00 GMT
Sunset: Sun, 01 Jan 2026 00:00:00 GMT
Link: </api/v2/users>; rel="successor-version"

Authentication & Authorization

API Key Authentication

// Request Header
Authorization: ApiKey sk_live_abc123xyz

// Or Query Parameter (less secure)
GET /api/v1/users?api_key=sk_live_abc123xyz

JWT (Bearer Token)

// Request Header
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

// Token structure
{
  "header": {
    "alg": "RS256",
    "typ": "JWT"
  },
  "payload": {
    "sub": "user-123",
    "iat": 1705312200,
    "exp": 1705315800,
    "scope": "read:users write:users"
  }
}

OAuth 2.0 Flows

OAuth 2.0 Flow


Rate Limiting

Headers

HTTP/1.1 200 OK
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 999
X-RateLimit-Reset: 1705316400

Rate Limit Response

// 429 Too Many Requests
{
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Rate limit exceeded. Try again in 60 seconds.",
    "retryAfter": 60
  }
}

Strategies

StrategyDescriptionUse Case
Fixed WindowX requests per minuteSimple, predictable
Sliding WindowRolling time windowSmoother limits
Token BucketTokens replenish over timeBurst-friendly
Leaky BucketConstant output rateConsistent load

API Documentation

OpenAPI Specification

openapi: 3.0.3
info:
  title: User Management API
  version: 1.0.0
  description: API for managing users

paths:
  /users:
    get:
      summary: List all users
      operationId: listUsers
      parameters:
        - name: page
          in: query
          schema:
            type: integer
            default: 1
        - name: limit
          in: query
          schema:
            type: integer
            default: 20
            maximum: 100
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserList'

components:
  schemas:
    User:
      type: object
      properties:
        id:
          type: string
        email:
          type: string
          format: email
        name:
          type: string
      required:
        - id
        - email

Documentation Tools

ToolTypeFeatures
Swagger UIInteractiveTry-it-out, code samples
RedocReferenceClean layout, search
StoplightPlatformDesign-first, mock servers
PostmanCollectionTesting, automation

Error Handling

Error Response Structure

interface ApiError {
  error: {
    code: string;           // Machine-readable code
    message: string;        // Human-readable message
    details?: {             // Specific error details
      field?: string;
      message: string;
      value?: any;
    }[];
    documentation?: string; // Link to error docs
    requestId: string;      // For support reference
  };
}

Common Error Codes

CodeHTTP StatusDescription
VALIDATION_ERROR400Invalid request data
AUTHENTICATION_REQUIRED401Missing or invalid auth
PERMISSION_DENIED403Insufficient permissions
RESOURCE_NOT_FOUND404Resource doesn't exist
RESOURCE_CONFLICT409Conflicting state
RATE_LIMIT_EXCEEDED429Too many requests
INTERNAL_ERROR500Server error

Security Best Practices

Transport Security

  • Always use HTTPS
  • Enforce HSTS headers
  • Use TLS 1.2 or higher

Input Validation

// Validate and sanitize all inputs
const schema = z.object({
  email: z.string().email().max(255),
  name: z.string().min(1).max(100),
  role: z.enum(['user', 'admin']),
});

const validated = schema.parse(request.body);

Output Security

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

CORS Configuration

const corsOptions = {
  origin: ['https://app.example.com'],
  methods: ['GET', 'POST', 'PUT', 'DELETE'],
  allowedHeaders: ['Content-Type', 'Authorization'],
  credentials: true,
  maxAge: 86400, // 24 hours
};

API Design Checklist

Naming & Structure

  • Resource names are nouns (not verbs)
  • URLs are lowercase with hyphens
  • Consistent plural/singular usage
  • Logical resource hierarchy

Functionality

  • Proper HTTP methods used
  • Appropriate status codes returned
  • Pagination for list endpoints
  • Filtering and sorting supported

Security

  • Authentication required for protected endpoints
  • Authorization checked on every request
  • Input validation on all endpoints
  • Rate limiting implemented
  • CORS configured correctly

Documentation

  • OpenAPI specification complete
  • Error codes documented
  • Authentication explained
  • Examples provided

Operations

  • Versioning strategy defined
  • Deprecation policy published
  • Health check endpoint exists
  • Monitoring in place


Compliance

This section fulfills ISO 13485 requirements for design outputs (7.3.4) and design inputs (7.3.3), and ISO 27001 requirements for secure architecture (A.8.27), application security requirements (A.8.26), and access control (A.5.15).

View full compliance matrix

How is this guide?

Last updated on

On this page