Isaac.

REST API Design Best Practices

Build RESTful APIs that are intuitive, scalable, and maintainable.

By EMEPublished: February 20, 2025
restapidesignbest-practiceshttpconventions

A Simple Analogy

A well-designed REST API is like a well-organized library. Books (resources) are organized logically, labeled clearly, and there's a standard system to find and retrieve them. Clients know exactly how to locate what they need without guidance.


What Makes a Good REST API?

A good REST API is intuitive, consistent, scalable, and predictable. Clients can understand and use it without extensive documentation because it follows conventions.


Core REST Principles

| Principle | Meaning | |-----------|---------| | Resources | Everything is a resource (users, orders, products) | | HTTP Methods | Use GET, POST, PUT, DELETE appropriately | | Status Codes | Communicate success/failure clearly | | Stateless | Each request is independent | | Representations | Resources returned as JSON/XML |


Resource Design

Good:
GET    /api/users              # List users
POST   /api/users              # Create user
GET    /api/users/:id          # Get specific user
PUT    /api/users/:id          # Update user
DELETE /api/users/:id          # Delete user

Bad:
GET    /api/getUsers
POST   /api/createUser
GET    /api/getUserById
POST   /api/updateUser
POST   /api/deleteUser

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 input
401 Unauthorized    // Authentication required
403 Forbidden       // Authenticated but not allowed
404 Not Found       // Resource doesn't exist
409 Conflict        // Request conflicts (duplicate)

// Server Errors
500 Internal Error  // Server error
503 Service Unavailable  // Server temporarily down

Practical Example

[ApiController]
[Route("api/[controller]")]
public class OrdersController : ControllerBase
{
    [HttpGet("{id}")]
    public async Task<ActionResult<OrderDto>> GetOrder(int id)
    {
        var order = await _orderService.GetOrderAsync(id);
        if (order == null)
            return NotFound();  // 404
        return Ok(order);       // 200
    }
    
    [HttpPost]
    public async Task<ActionResult<OrderDto>> CreateOrder(CreateOrderDto dto)
    {
        var order = await _orderService.CreateAsync(dto);
        return CreatedAtAction(nameof(GetOrder), new { id = order.Id }, order);  // 201
    }
    
    [HttpPut("{id}")]
    public async Task<IActionResult> UpdateOrder(int id, UpdateOrderDto dto)
    {
        var success = await _orderService.UpdateAsync(id, dto);
        if (!success)
            return NotFound();  // 404
        return NoContent();     // 204
    }
}

Best Practices

  1. Use nouns, not verbs: /orders not /getOrders
  2. Consistent naming: Plurals, lowercase, hyphens: /users, /product-categories
  3. Pagination: GET /users?page=1&limit=10
  4. Filtering: GET /orders?status=pending&date=2025-02-20
  5. Versioning: GET /api/v1/users or header-based
  6. Documentation: Clear error messages and swagger
  7. Error responses: Consistent format
    {
      "error": "Invalid input",
      "code": 400,
      "details": "Email is required"
    }
    

Real-World Example

User Orders API

GET    /api/v1/users/:userId/orders
       Returns: [{ id, date, status, total }]

POST   /api/v1/users/:userId/orders
       Body: { items: [...], shippingAddress: {...} }
       Returns: 201 + { id, orderNumber, ... }

GET    /api/v1/orders/:orderId
       Returns: { id, items, status, total, dates }

PUT    /api/v1/orders/:orderId
       Body: { status: "shipped", trackingNumber: "..." }
       Returns: 204

Related Concepts to Explore

  • GraphQL (alternative to REST)
  • API versioning strategies
  • Rate limiting and throttling
  • HATEOAS (Hypermedia)
  • OpenAPI/Swagger documentation

Summary

Good REST API design follows HTTP conventions, uses intuitive resource naming, and clear status codes. This makes APIs discoverable, maintainable, and a pleasure to use.