DevToolBoxFREE
Blog

REST API Design Best Practices: The Complete Guide

12 min readby DevToolBox

Designing a great REST API is about more than just returning JSON. A well-designed API is predictable, consistent, secure, and easy to consume. This comprehensive guide covers the most important REST API design best practices with real-world examples, common mistakes, and battle-tested patterns used by companies like Stripe, GitHub, and Twilio.

1. Use Nouns for Resource URIs

REST APIs model resources, not actions. URIs should represent things (nouns), not operations (verbs). The HTTP method (GET, POST, PUT, DELETE) already describes the action.

# Good - nouns representing resources
GET    /api/v1/users          # list users
GET    /api/v1/users/123      # get user 123
POST   /api/v1/users          # create a user
PUT    /api/v1/users/123      # replace user 123
PATCH  /api/v1/users/123      # partially update user 123
DELETE /api/v1/users/123      # delete user 123

# Bad - verbs describing actions
GET    /api/v1/getUsers
POST   /api/v1/createUser
POST   /api/v1/deleteUser/123
GET    /api/v1/getUserById?id=123
# Nested resources (one level deep)
GET    /api/v1/users/123/orders       # orders for user 123
GET    /api/v1/users/123/orders/456   # order 456 for user 123
POST   /api/v1/users/123/orders       # create order for user 123

# For actions that don't map to CRUD, use sub-resources
POST   /api/v1/users/123/activate     # activate user (action)
POST   /api/v1/orders/456/cancel      # cancel order (action)
POST   /api/v1/emails/789/resend      # resend email

2. Use Proper HTTP Methods

Each HTTP method has a specific semantic meaning. Using the correct method makes your API predictable and enables caching, idempotency, and browser integration.

MethodPurposeIdempotentRequest Body
GETRead a resourceYesNo
POSTCreate a resourceNoYes
PUTFull replacementYesYes
PATCHPartial updateNo*Yes
DELETERemove a resourceYesNo

3. Use Plural Resource Names

Always use plural nouns for collections. This keeps URIs consistent whether you are accessing a collection or a single resource within it.

# Good - consistent plural nouns
/api/v1/users
/api/v1/users/123
/api/v1/products
/api/v1/products/456/reviews

# Bad - mixing singular and plural
/api/v1/user          # singular
/api/v1/user/123
/api/v1/productList   # avoid "list" suffix

4. Use HTTP Status Codes Correctly

Status codes tell clients what happened without parsing the response body. The three most important ranges are 2xx (success), 4xx (client error), and 5xx (server error).

CodeWhen to Use
200 OKSuccessful GET, PUT, PATCH, or DELETE
201 CreatedSuccessful POST that creates a resource
204 No ContentSuccessful DELETE with no response body
400 Bad RequestMalformed request syntax or invalid data
401 UnauthorizedMissing or invalid authentication
403 ForbiddenAuthenticated but not authorized
404 Not FoundResource does not exist
409 ConflictConflicting state (e.g., duplicate email)
422 UnprocessableValidation errors in request body
429 Too Many RequestsRate limit exceeded
500 Internal ErrorUnexpected server error

5. Version Your API

API versioning protects existing consumers when you make breaking changes. There are three common strategies, each with trade-offs.

# Strategy 1: URI versioning (most common)
GET /api/v1/users
GET /api/v2/users

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

# Strategy 3: Query parameter versioning
GET /api/users?version=2
StrategyProsCons
URI pathSimple, visible, cacheableURI pollution
HeaderClean URIsHarder to test, less visible
Query paramEasy to addCache-unfriendly, easy to forget

6. Pagination, Filtering, and Sorting

Any endpoint that returns a collection should support pagination. Without it, responses grow unbounded and performance degrades for both server and client.

# Offset-based pagination (simplest)
GET /api/v1/users?page=2&limit=25
GET /api/v1/users?offset=25&limit=25

# Cursor-based pagination (better for large datasets)
GET /api/v1/users?cursor=eyJpZCI6MTAwfQ&limit=25

# Response with pagination metadata
{
  "data": [...],
  "pagination": {
    "total": 1250,
    "page": 2,
    "limit": 25,
    "totalPages": 50,
    "hasNext": true,
    "hasPrev": true
  }
}

# Filtering and sorting
GET /api/v1/products?category=electronics&minPrice=100&maxPrice=500
GET /api/v1/products?sort=price&order=asc
GET /api/v1/products?sort=-created_at  # prefix with - for descending
GET /api/v1/users?fields=id,name,email  # sparse fieldsets

7. Error Response Format

A consistent error response format across your entire API helps clients handle errors programmatically. Include an error code, a human-readable message, and optionally field-level details for validation errors.

// Consistent error response format
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Request validation failed",
    "details": [
      {
        "field": "email",
        "message": "Must be a valid email address",
        "value": "not-an-email"
      },
      {
        "field": "age",
        "message": "Must be at least 18",
        "value": 15
      }
    ],
    "requestId": "req_abc123",
    "timestamp": "2026-01-15T10:30:00Z",
    "docs": "https://api.example.com/docs/errors#VALIDATION_ERROR"
  }
}

// Simple error (non-validation)
{
  "error": {
    "code": "RESOURCE_NOT_FOUND",
    "message": "User with id 999 not found",
    "requestId": "req_def456"
  }
}

8. Authentication and Security

API security is non-negotiable. Here are the essential security practices every API should implement from day one.

# Bearer token authentication (JWT)
GET /api/v1/users
Authorization: Bearer eyJhbGciOiJSUzI1NiIs...

# API key authentication
GET /api/v1/users
X-API-Key: sk_live_abc123def456

# OAuth 2.0 token request
POST /oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials
&client_id=YOUR_CLIENT_ID
&client_secret=YOUR_CLIENT_SECRET
&scope=read:users write:users
  • Always use HTTPS in production
  • Never put secrets in query parameters (they appear in server logs)
  • Use short-lived access tokens (15-60 min) with refresh tokens
  • Implement CORS properly for browser-based clients
  • Validate and sanitize all input to prevent injection attacks
  • Use rate limiting to prevent brute-force attacks

9. Rate Limiting

Rate limiting protects your API from abuse and ensures fair usage across clients. Always communicate limits via standard HTTP headers.

# Rate limit response headers (standard)
HTTP/1.1 200 OK
X-RateLimit-Limit: 1000        # max requests per window
X-RateLimit-Remaining: 742     # requests remaining
X-RateLimit-Reset: 1706810400  # Unix timestamp when limit resets
Retry-After: 60                # seconds until next request (on 429)

# Rate limit exceeded response
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
Retry-After: 60

{
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Too many requests. Limit: 1000/hour",
    "retryAfter": 60
  }
}

10. HATEOAS and Linking

Hypermedia As The Engine Of Application State (HATEOAS) adds discoverability to your API by including links in responses that tell clients what actions are available next.

// HATEOAS response example
{
  "id": 123,
  "name": "John Doe",
  "email": "john@example.com",
  "status": "active",
  "_links": {
    "self": { "href": "/api/v1/users/123" },
    "orders": { "href": "/api/v1/users/123/orders" },
    "deactivate": {
      "href": "/api/v1/users/123/deactivate",
      "method": "POST"
    }
  }
}

// Paginated collection with HATEOAS links
{
  "data": [...],
  "_links": {
    "self": { "href": "/api/v1/users?page=2&limit=25" },
    "first": { "href": "/api/v1/users?page=1&limit=25" },
    "prev": { "href": "/api/v1/users?page=1&limit=25" },
    "next": { "href": "/api/v1/users?page=3&limit=25" },
    "last": { "href": "/api/v1/users?page=50&limit=25" }
  }
}

Frequently Asked Questions

Should I use PUT or PATCH for updates?

Use PUT when the client sends the complete updated resource (full replacement). Use PATCH when the client sends only the fields to change (partial update). PATCH is more bandwidth-efficient and reduces merge conflicts, but requires careful handling of null vs absent fields. Most modern APIs prefer PATCH for updates.

Should REST API URIs be lowercase?

Yes, URIs should be lowercase with hyphens as separators (kebab-case): /api/v1/user-profiles instead of /api/v1/userProfiles. RFC 3986 defines URIs as case-sensitive, so mixing cases leads to confusion and potential 404 errors. JSON property names in request/response bodies should use camelCase.

How should I handle nested resources?

Limit nesting to one level: /users/123/orders is fine, but /users/123/orders/456/items/789 is too deep. For deeply nested resources, promote them to top-level endpoints with query parameters: /order-items?orderId=456. This keeps URIs short and avoids coupling.

What is the best authentication method for REST APIs?

For server-to-server communication, use API keys or OAuth 2.0 client credentials. For user-facing apps, use OAuth 2.0 with PKCE for SPAs or Authorization Code flow for server-side apps. JWT bearer tokens are the most common token format. Always use HTTPS and never send credentials in query parameters.

Should I use GraphQL instead of REST?

REST and GraphQL solve different problems. REST is simpler, has better caching (HTTP-level), and works well for CRUD-heavy APIs with predictable access patterns. GraphQL excels when clients need flexible queries across many related resources, or when you need to reduce over-fetching. Many teams use both: REST for simple CRUD, GraphQL for complex data requirements.

TL;DR

  • Use nouns (not verbs) for resource URIs
  • Use the correct HTTP method for each operation
  • Always use plural resource names
  • Return appropriate HTTP status codes
  • Version your API from day one (URI path is simplest)
  • Support pagination, filtering, and sorting for collections
  • Use a consistent error response format
  • Always use HTTPS and proper authentication
  • Implement rate limiting with standard headers
  • Consider HATEOAS for API discoverability

Following these best practices from the start saves countless hours of refactoring and breaking changes later. For testing and validating your API responses, try our tools below.

𝕏 Twitterin LinkedIn
Was this helpful?

Stay Updated

Get weekly dev tips and new tool announcements.

No spam. Unsubscribe anytime.

Try These Related Tools

{ }JSON Formatter4xxHTTP Status Code ReferenceJWTJWT Decoder

Related Articles

REST API Best Practices: The Complete Guide for 2026

Learn REST API design best practices including naming conventions, error handling, authentication, pagination, versioning, and security headers.

HTTP Status Codes: Complete Reference Guide for Developers

Complete HTTP status codes reference: 1xx to 5xx with practical explanations, API best practices, and common debugging tips.

API Authentication: OAuth 2.0 vs JWT vs API Key

Compare API authentication methods: OAuth 2.0, JWT Bearer tokens, and API keys. Learn when to use each method, security trade-offs, and implementation patterns.