API Fundamentals

API Design Guide

Build APIs that developers love to use. A comprehensive guide to API design covering REST principles, naming conventions, versioning strategies, error handling, and authentication patterns.

15 min readAll LevelsLast updated: March 2026

Why Design-First Wins

The design-first approach means writing your API specification before a single line of server code. Teams that adopt design-first ship faster, produce more consistent APIs, and create better developer experiences. Here is why.

Benefits of Design-First Development

  • Catch breaking changes before they reach production
  • Enable parallel frontend and backend development
  • Auto-generate SDKs, documentation, and mock servers
  • Validate requests and responses against a contract
  • Create a single source of truth for your API
  • Improve developer experience with interactive docs

Specway Makes Design-First Easy

Import your OpenAPI spec and instantly generate beautiful, interactive documentation. Make changes to your spec and watch your docs update automatically. No manual synchronization needed.

8 Core API Design Principles

Follow these principles to build APIs that are consistent, predictable, and a joy to integrate with.

Design-First Approach

Start with your API specification before writing any code. Define your endpoints, data models, and error responses upfront. This catches design issues early, enables parallel frontend and backend development, and produces better documentation from day one.

# Design-first: Write your OpenAPI spec first
openapi: 3.0.3
info:
  title: Users API
  version: 1.0.0
paths:
  /users:
    get:
      summary: List all users
      parameters:
        - name: page
          in: query
          schema:
            type: integer
            default: 1
        - name: limit
          in: query
          schema:
            type: integer
            default: 20
            maximum: 100

Use Nouns, Not Verbs

REST endpoints should represent resources (nouns), not actions (verbs). The HTTP method conveys the action. Use plural nouns for collections and keep URLs predictable and hierarchical.

# GOOD - Resource-oriented URLs
GET    /users          # List users
POST   /users          # Create a user
GET    /users/123      # Get a specific user
PUT    /users/123      # Update a user
DELETE /users/123      # Delete a user

# BAD - Verb-oriented URLs
GET /getUsers
POST /createUser
POST /deleteUser/123

Consistent Naming Conventions

Pick a naming convention and apply it everywhere. Most REST APIs use snake_case for JSON fields, kebab-case for URL paths, and camelCase for query parameters. The key is consistency across your entire API surface.

// Consistent snake_case in response bodies
{
  "user_id": "usr_abc123",
  "first_name": "Jane",
  "last_name": "Smith",
  "created_at": "2025-01-15T10:30:00Z",
  "is_active": true,
  "email_verified": true
}

// Consistent kebab-case in URL paths
GET /api/v1/user-profiles/usr_abc123/access-tokens

Versioning Strategy

Version your API from the start. URL-based versioning (/v1/, /v2/) is the most common and easiest to understand. Header-based versioning is more RESTful but harder to test. Whichever you choose, plan for backwards compatibility.

# URL-based versioning (most common)
GET /api/v1/users
GET /api/v2/users

# Header-based versioning
GET /api/users
Accept: application/vnd.myapi.v2+json

# Query parameter versioning
GET /api/users?version=2

Meaningful Error Responses

Return structured error responses with an error code, a human-readable message, and a link to documentation. Use appropriate HTTP status codes: 400 for bad input, 401 for unauthenticated, 403 for forbidden, 404 for not found, and 429 for rate limiting.

// Structured error response
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "The request body contains invalid fields.",
    "details": [
      {
        "field": "email",
        "message": "Must be a valid email address."
      },
      {
        "field": "age",
        "message": "Must be a positive integer."
      }
    ],
    "doc_url": "https://api.example.com/docs/errors#validation"
  }
}

Pagination, Filtering & Sorting

Every list endpoint needs pagination. Cursor-based pagination is more reliable than offset-based for large datasets. Support filtering with query parameters and sorting with a sort parameter that accepts field names with a direction prefix.

# Cursor-based pagination
GET /api/v1/users?limit=20&cursor=eyJpZCI6MTAwfQ

# Response with pagination metadata
{
  "data": [...],
  "pagination": {
    "next_cursor": "eyJpZCI6MTIwfQ",
    "has_more": true,
    "total_count": 1583
  }
}

# Filtering and sorting
GET /api/v1/users?status=active&role=admin&sort=-created_at

Rate Limiting

Protect your API with rate limits and communicate them clearly through response headers. Return 429 Too Many Requests when limits are exceeded, with a Retry-After header indicating when the client can try again.

# Rate limit headers in every response
HTTP/1.1 200 OK
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 994
X-RateLimit-Reset: 1704067200

# When rate limited
HTTP/1.1 429 Too Many Requests
Retry-After: 30
{
  "error": {
    "code": "RATE_LIMITED",
    "message": "Too many requests. Try again in 30 seconds."
  }
}

Authentication Patterns

Choose the right auth mechanism for your use case. API keys work for server-to-server calls. OAuth 2.0 is best for user-delegated access. JWT tokens enable stateless authentication. Always transmit credentials over HTTPS.

# API Key (header)
GET /api/v1/users
Authorization: Bearer sk_live_abc123def456

# OAuth 2.0 (Bearer token)
GET /api/v1/users
Authorization: Bearer eyJhbGciOiJSUzI1NiIs...

# API Key (query parameter - less secure)
GET /api/v1/users?api_key=sk_live_abc123def456

Frequently Asked Questions

Common questions about API design.

Design APIs the Right Way

Import your OpenAPI spec into Specway and publish beautiful, interactive API documentation in minutes.