REST APIs power the modern web, but most APIs are designed with subtle flaws that cause pain months later. This guide covers the conventions, patterns, and anti-patterns that separate production APIs from weekend projects.

1. Use Nouns, Not Verbs, for Resources

# Good
GET    /users
GET    /users/42
POST   /users
PUT    /users/42
DELETE /users/42

# Bad
GET    /getUsers
POST   /createUser
GET    /users/42/getProfile

2. Version Your API from Day One

Use URL prefix versioning (/v1/users) or header-based versioning (Accept: application/vnd.api.v2+json). URL versioning is simpler for public APIs. Choose one and stick with it everywhere โ€” mixing strategies is worse than either alone.

3. Consistent Naming Conventions

// JSON: camelCase for properties
{{"userId": 42, "createdAt": "2026-05-07"}}

// URL paths: kebab-case
GET /user-orders/42

// Query parameters: snake_case
GET /users?sort_by=name&page_size=20

4. Use Proper HTTP Status Codes

CodeWhen to Use
200 OKSuccessful GET, PUT, PATCH
201 CreatedSuccessful POST โ€” always include Location header
204 No ContentSuccessful DELETE (no body returned)
400 Bad RequestMalformed input, validation failure
401 UnauthorizedMissing or expired auth token
403 ForbiddenAuthenticated but not permitted
404 Not FoundResource doesn't exist
409 ConflictDuplicate or state conflict
422 UnprocessableValid syntax but semantic error
429 Too ManyRate limit exceeded โ€” include Retry-After header
500 Internal ErrorUnexpected server failure (never expose stack traces)

5. Error Response Format

Always return errors in a consistent structure:

{{
  "error": {{
    "code": "VALIDATION_ERROR",
    "message": "Email is required",
    "details": [
      {{"field": "email", "reason": "must not be empty"}},
      {{"field": "age", "reason": "must be positive"}}
    ],
    "requestId": "req_abc123"
  }}
}}

6. Pagination, Filtering, and Sorting

# Pagination with cursor (preferred for large datasets)
GET /users?cursor=eyJpZCI6NDJ9&limit=20
Response: {{"data": [...], "nextCursor": "eyJpZCI6NjJ9", "hasMore": true}}

# Or offset-based for simpler use cases
GET /users?offset=0&limit=20

# Filtering
GET /users?status=active&role=admin

# Sorting
GET /users?sort=-createdAt  # descending
GET /users?sort=+name       # ascending

7. Security Checklist

  • Always use HTTPS. No exceptions.
  • Set rate limits. At minimum: 60 req/min per IP for unauthenticated, 1000 req/min per user for authenticated.
  • Validate Content-Type. Reject requests with wrong Content-Type headers.
  • Set CORS explicitly. Never use Access-Control-Allow-Origin: * with credentials.
  • Use API keys or OAuth2. Never roll your own auth protocol.
  • Keep secrets out of responses. Password hashes, internal IDs, stack traces, server versions.

8. API Documentation

Use OpenAPI 3.1 (Swagger). It's the industry standard and generates interactive docs automatically. Tools like Stoplight, Redoc, and Swagger UI render beautiful docs from a single spec file. If your API doesn't have an OpenAPI spec, it's not ready for production.