Skip to main content

Command Palette

Search for a command to run...

REST API Design Best Practices

Updated
4 min read
REST API Design Best Practices

Core Principles

  • Design APIs that are:

    1. Easy to read and work with

    2. Hard to misuse

    3. Complete and concise

Naming and URL Structure

Resource Naming

  • Use nouns to represent resources, not verbs

    • Good: /items, /employees

    • Bad: /createItems, /getEmployees

  • Use plural nouns for collections (e.g., /orders not /order)

  • Use hyphens for readability (e.g., inventory-management) instead of underscores

URL Structure

  • Implement logical grouping for nested resources

    • Example: /customers/{id}/orders
  • Avoid going deeper than collection/resource/collection

  • Don't mirror database structure in URLs to prevent exposing unnecessary information

Versioning

  • Always version your APIs to prevent breaking changes

  • Options:

    1. Path versioning: /v1/store, /v2/store (more common)

    2. Query parameter: ?version=2

Data Handling

Pagination

  • Implement pagination for large datasets

  • Use cursor based pagination (more efficient, similar to what stripe does)

    • Edit: Offset based is better for experiences where you want pages e.g. search in a booking system.
  • Example: /items?lastItemId=1000&limit=20

Filtering and Sorting

  • Allow filtering through query parameters

    • Example: /users?lastName=Smith&age=30
  • Support field selection to limit response data

    • Example: /products?fields=id,name,price

    • Can be faster since less data needs to be fetched from the database and serialised before sending over the network

  • Enable sorting with clear parameters

    • Example: /posts?sort=+author,-datePublished

API Operations

Idempotency

  • Ensure operations are idempotent where appropriate

  • Multiple identical requests should result in the same state

  • Particularly important for DELETE, PUT operations

  • For sensitive operations, consider using idempotency keys. Stripe does this for charge operations.

Async Operations

  • Use status code 202 for long-running operations, says the operation is accepted but not completed

  • Provide status endpoint for tracking progress e.g. GET /orders/123/status

  • Include status endpoint URL in Location header (e.g. Location: /orders/123/status), helps clients to know where to get the status of the operation. This follows the HATEOAS principle (Hypermedia as the Engine of Application State) which states that the API should tell the client what it can do next.

  • Consider supporting operation cancellation e.g. DELETE /orders/123/cancel

Partial Responses

Support partial content retrieval for large resources e.g. video files. This is useful for large files that you don't want to download all at once, think Netflix movies... They would be HUGE if you downloaded the whole thing at once.

  1. First, client can make a HEAD request to check resource size (very fast request, no body needed):
HEAD /files/big-video.mp4
Response headers:
Accept-Ranges: bytes
Content-Length: 100000000
Content-Type: video/mp4
  1. Then client can request specific chunks using Range header:
GET /files/big-video.mp4
Range: bytes=0-1048575  # Request first 1MB
  1. Server responds with partial content:
HTTP/1.1 206 Partial Content
Content-Range: bytes 0-1048575/100000000
Content-Length: 1048576
[... first 1MB of data ...]
  1. Client can request next chunk:
GET /files/big-video.mp4
Range: bytes=1048576-2097151  # Request second 1MB

Security

  • Implement SSL/TLS encryption -> Use HTTPS.

  • Use proper authentication and authorization -> OAuth, JWT, etc.

  • Apply rate limiting to prevent DoS attacks

  • Be careful with error messages to avoid information leakage -> Best to always craft a good error message: No inner details, clear what's wrong and what to do next.

Error Handling

  • Return appropriate HTTP status codes

  • Provide clear error messages

  • Include enough information for debugging without exposing sensitive details

  • Use 204 for successful empty responses

Documentation

  • Use OpenAPI (formerly Swagger) for API documentation

  • Document:

    • Endpoint structure

    • Request/response formats

    • Authentication requirements

    • Error codes and messages

HATEOAS (Hypermedia as the Engine of Application State)

  • Consider implementing HATEOAS for better API navigation

  • Include related resource links in responses, you can also include self links, they would describe other things you can do with the resource. If you created a post, they would include links to edit the post, delete the post, etc.

Example:

{
  "orderId": "12345",
  "status": "pending",
  "total": 99.99,
  "links": {
    "self": {
      "href": "/orders/12345",
      "method": "GET"
    },
    "update": {
      "href": "/orders/12345",
      "method": "PUT"
    },
    "cancel": {
      "href": "/orders/12345/cancel",
      "method": "POST"
    },
    "payment": {
      "href": "/orders/12345/payment",
      "method": "POST"
    },
    "customer": {
      "href": "/customers/789",
      "method": "GET"
    }
  }
}

For each method, you provide the type of operation PLUS href and method for each operation.

Each thing should be self documenting. For POST with body, you can include contentType and schema, example:

    "create": {
      "href": "/orders",
      "method": "POST",
      "contentType": "application/json",
      "schema": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array"
          }
        }
      }
    }