Manikandan — Manikandan
System Design

8 REST API Design Laws

ManikandanManikandan
5 min read·Updated Sep 9, 2026
8 REST API Design Laws

A comprehensive guide to the 8 REST API design laws, focusing on designing around resources, predictable URLs, proper HTTP method usage, and consistent error handling.

Intro

Designing a REST API is more than just exposing endpoints to your database; it is about creating a predictable, maintainable, and intuitive interface for developers to interact with your system. A well-designed API reduces friction, minimizes the need to constantly consult documentation, and establishes a clear mental model.

In this article, we will explore the 8 REST API Design Laws that set the foundation for a cohesive API framework.

1. Design Around Resources, Not Actions

This is the first law of REST API design. It establishes that URLs should identify the resource being acted upon, while HTTP methods (verbs) describe the operation being performed.

Core Concept & Common Pitfalls

A common mistake in API design is putting the action directly into the URL path, resulting in endpoints like getUsers, createOrder, or deleteProduct. This design is redundant because HTTP was explicitly built to communicate actions through standard methods.

Instead, a clean RESTful design uses noun-based resources for the path (such as users, orders, or products) and lets the HTTP verb specify the action:

  • GET /orders: Retrieves orders.
  • POST /orders: Creates a new order.
  • DELETE /orders/{id}: Removes a specific order.

Key Benefits

  • Scalability: As the API expands, the same resource endpoint can support multiple operations without creating a separate URL for every action.
  • Simplicity & Predictability: Developers don’t have to guess or memorize custom endpoint URLs for every new feature.

2. Make URLs Predictable

Use consistent resource naming conventions. Developers should be able to guess the URL for a resource without looking at the documentation.

Best Practices

  • Use Plural Nouns: Collections should be named with plural nouns. For example, use /users instead of /user, and /orders instead of /order.
  • Standard Identifier Structures: When targeting a specific item in a collection, append the identifier to the path: /users/123.
  • Nested Resources: Represent relationships logically. If an order belongs to a user, a predictable path would be /users/123/orders.
// Good
GET /api/v1/products
GET /api/v1/products/42
GET /api/v1/products/42/reviews
// Bad
GET /api/v1/getAllProducts
GET /api/v1/product?id=42

3. Use HTTP Methods for Their Actual Purpose

Respect standard HTTP semantics and idempotency. HTTP provides verbs designed for specific operations.

  • GET: Retrieve a resource. Should be safe and idempotent (repeated calls don’t change state).
  • POST: Create a new resource or trigger processing. Not idempotent.
  • PUT: Update an existing resource completely, or create it if it doesn’t exist. Idempotent.
  • PATCH: Partially update an existing resource.
  • DELETE: Remove a resource. Idempotent.
[ApiController]
[Route("api/users")]
public class UsersController : ControllerBase
{
[HttpGet] // GET /api/users
public IActionResult GetAll() { /* ... */ return Ok(); }
[HttpPost] // POST /api/users
public IActionResult Create(UserDto user) { /* ... */ return CreatedAtAction(nameof(GetAll), new { id = 1 }, user); }
[HttpPut("{id}")] // PUT /api/users/123
public IActionResult Update(int id, UserDto user) { /* ... */ return NoContent(); }
}

4. Make Status Codes Useful

Communicate overall outcome categories with standard HTTP status codes rather than masking errors behind a 200 OK body. Using correct status codes helps clients handle responses automatically (like retrying on 500s or redirecting to login on 401s).

  • 200 OK: Request succeeded.
  • 201 Created: Resource successfully created (usually via POST).
  • 204 No Content: Request succeeded but no response body (common for DELETE).
  • 400 Bad Request: Client sent invalid data.
  • 401 Unauthorized: Authentication is required and has failed or has not yet been provided.
  • 403 Forbidden: Authenticated, but lacks permissions.
  • 404 Not Found: Resource does not exist.
  • 422 Unprocessable Entity: Validation errors in the payload.
  • 500 Internal Server Error: The server encountered an unexpected condition.

5. Keep Errors Consistent

Provide structured error bodies containing failure codes, clear messages, and specific field validation details. An API should have one unified error format.

In .NET Core, you can achieve this easily using the standard ProblemDetails format (RFC 7807).

{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"traceId": "00-84c1...-00",
"errors": {
"Email": [
"The Email field is not a valid e-mail address."
]
}
}

6. Don’t Put Everything into the URL Path

Use URL paths exclusively to identify resources, and rely on query parameters for filtering, sorting, or searching.

When clients need to narrow down a list, the URL path should not become a complex command.

// Bad: Action and filters in path
GET /users/active/sort/asc
// Good: Query parameters for filtering and sorting
GET /users?status=active&sort=createdAt:asc&limit=10

7. Treat API Changes Carefully

Manage API evolution thoughtfully through deliberate versioning strategies so updates do not break existing clients.

Always version your API from day one. You can use URL versioning, Header versioning, or Query string versioning. URL versioning is the most explicit and easiest to explore.

[ApiController]
[Route("api/v{version:apiVersion}/[controller]")]
[ApiVersion("1.0")]
public class ProductsController : ControllerBase
{
// Controller actions...
}

8. Keep Request and Response Formats Consistent

Enforce uniform conventions for JSON property casing, date formats, pagination structures, and error payloads across every endpoint.

  • Casing: Stick to one naming convention for JSON properties, typically camelCase.
  • Dates: Use ISO 8601 format (e.g., 2026-09-09T14:30:00Z).
  • Pagination: Standardize how paginated data is returned. Always include metadata like totalItems, totalPages, currentPage.
{
"data": [
{ "id": 1, "name": "Laptop" },
{ "id": 2, "name": "Mouse" }
],
"meta": {
"page": 1,
"pageSize": 10,
"totalItems": 45,
"totalPages": 5
}
}

Summary

By defining resource-centric URLs first, the API creates a clear mental model that makes applying the remaining laws—such as method semantics, parameter filtering, and error handling—far more straightforward and predictable. By adhering to these 8 REST API Design Laws, you will build systems that developers will actually enjoy consuming.

Interactive Architectural Roadmaps

Explore Complete Roadmaps & Pattern Checklists

Track your learning with interactive checklists for all 23 Gang of Four patterns and modern Microservice architecture patterns.

Share:
Back to Blog

Related Posts

View All Posts
HTTP QUERY Method in .NET 10 and Angular
API Design

HTTP QUERY Method in .NET 10 and Angular

A practical guide to the HTTP QUERY method (RFC 10008), with GET vs POST vs QUERY comparisons, performance implications, and .NET 10 plus Angular examples.

Manikandan
Manikandan·7 min read