
Engineering Team
2026-07-07
10 mins
API Design Principles: Build Better REST APIs
Every integration built against an API is a long-term commitment to that API's design decisions. A poorly designed interface does not fail at launch, it accumulates support burden, workaround code, and consumer attrition over months and years until backward compatibility becomes more expensive to maintain than breaking it.
This article is for software engineers building or evaluating a web API, not readers who need to learn what one is. It addresses rest and restful web services alongside other architectural styles as a set of trade-offs for practitioners who have already decided to build and need to make defensible structural choices. To apply any api design principles, you first need a working definition of what "well-designed" actually means in production.
REST formalizes predictability through the uniform interface, which is one of six architectural constraints that define the style and the one most directly responsible for the consistent, easy-to-understand behavior that rest api best practices prescribe. When consumers can predict how resources are addressed and represented without consulting the implementation, the API fulfills this constraint's purpose.
Resource naming and URL structure are where all three qualities first become observable in a working API. How endpoints are organized sets the predictability contract before a single request is made.
Resource-oriented URI design is the most foundational of all REST api design principles: paths identify things, not actions. Treating URIs as action encoders rather than resource identifiers is the most pervasive structural mistake in REST API design, and the one that makes every downstream naming decision harder to keep consistent. URL structure's role is to establish where resources live, and the four conventions below define that contract consistently.
- Nouns, not verbs: Paths identify resources, not operations: /users retrieves a user collection, while /getUsers encodes the action in the URI rather than the HTTP method. An API using /getUsers, /createOrder, or /deleteProduct builds a parallel verb system that the HTTP method already provides.
- Plural nouns for collections: Collection endpoints use plural nouns (/orders, /products, /users) because a singular label forces an inconsistent pattern at the single-resource level. Postman's API design guidance identifies plural nouns as the foundational naming convention for this reason.
- One level of nesting for sub-resources: /users/{id}/orders is a clear, readable path for representing a relationship; nesting beyond one level starts encoding data-model coupling that breaks as schemas evolve. API design guidelines recommend stopping at one level for exactly this reason.
- Kebab-case for path formatting: Paths are lowercase and hyphen-separated when creating APIs, not camelCase or snake_case, for readability and consistent log parsing. The convention removes ambiguity from URLs that would otherwise vary by team or framework preference.
HTTP methods are the semantic contract that governs what each api request does to server state, and treating them as interchangeable labels is among the most consequential violations of REST api design principles. According to API design guidelines, GET retrieves a resource without mutation, POST creates a new one, PUT replaces the resource entirely, PATCH modifies a subset of fields, and DELETE removes it. Mixing these methods incorrectly, such as using POST where PUT belongs or GET for a mutating operation, produces an API that behaves unpredictably as it scales.
The safe and idempotent properties of these methods are a distinct concern that few teams address explicitly, despite their direct impact on retry logic, payment safety, and data integrity in distributed systems. Established REST API best practices define a safe method as one that does not change server state, whereas an idempotent method may change state but, when repeated, produces the same result. GET, PUT, and DELETE are idempotent, but POST is neither, meaning a duplicate request from a client retry or network timeout can create duplicate resources or charges.
Published API design guidance identifies the idempotency key as the standard remedy: a client-generated unique token sent as a request header alongside common headers such as Content-Type. Payment and order APIs should require one on any creation endpoint, which transforms duplicate requests from a data-integrity risk into a recoverable condition.
HTTP status codes communicate which tier of the system is responsible for a failure; collapsing them into 200 for every response or 500 for every error eliminates one of the most reliable diagnostic contracts in API design principles, where each range carries a distinct responsibility:
- 2xx: The request succeeded and the API fulfilled its contract.
- 4xx: The caller submitted an invalid, malformed, or incomplete request.
- 5xx: The API failed; the caller's request was valid and the problem lies in the service.
The 401 and 403 codes are the most frequently misused pair. 401 (Unauthorized) means the request lacks valid credentials; 403 (Forbidden) means credentials are valid but the caller lacks permission. Returning 403 for an unauthenticated request leaks security posture by confirming that a resource exists and is access-controlled.
Returning a correct status code is necessary but rarely sufficient. Most APIs get the code right and return an unusable error payload. Established REST API best practices recommend a structured error body with a consistent content type and three stable fields:
- error.code: A machine-readable identifier for client-side conditional logic.
- error.message: A human-readable description intended for developers and log output.
- error.details[]: A validation array for field-level failures, listing each invalid field and the reason.
Security in API design principles is a set of design-time decisions that must be made before the interface ships. Authentication and authorization are distinct concerns, each requiring its own mechanism. Three mechanisms address different access patterns:
- OAuth 2.0 for delegated access using scoped, revocable tokens;
- JSON web tokens (JWT) for stateless claims that downstream services verify without a central session store;
- API keys for service-to-service communication where user identity plays no role.
Mixing these mechanisms without clear boundaries creates authorization gaps that are difficult to detect through functional testing.
All API traffic must travel over TLS/HTTPS. Sensitive data must never appear in URL path segments or query parameters, where token values, PII, and session identifiers are routinely captured in server logs, browser history, and CDN access logs. Rate limiting protects the API against both intentional abuse and accidental flooding from misbehaving or misconfigured clients. A 429 Too Many Requests response paired with a Retry-After header gives rate-limited clients a defined recovery path and removes the need to poll until the limit resets.
Versioning without a deprecation plan leaves consumers on old versions indefinitely, and most coverage of api design principles focuses on introducing new versions rather than retiring old ones. A sound deprecation lifecycle begins with announcing the retirement date early and running both versions in parallel through the transition window. Old-version responses should carry a Deprecated header from the day the successor ships, and a Sunset header on each response communicates the exact removal date so consumer teams have a fixed migration deadline.
The access-pattern layer of api design principles determines how consumers filter and receive data; poor decisions here cause over-fetching and mobile performance problems that no later optimization fully resolves.
Pagination and partial responses improve performance in ways that query parameters alone cannot address:
- Offset pagination: This approach uses LIMIT and OFFSET to navigate a resource collection. Concurrent inserts shift row positions mid-fetch, producing duplicates or skipped items; cursor-based pagination is more reliable for real-time, high-volume collections.
- Partial responses: A ?fields= parameter, such as GET /users?fields=id,name,email, reduces payload size for mobile and bandwidth-constrained clients. Although some API design guidance covers this pattern, adoption remains low relative to the straightforward performance gains it delivers.
Access patterns consumers cannot discover will not be used, and the legibility of the data access layer is as important as its technical precision.
A complete endpoint document is the contract between an API team and its consumers; an undocumented endpoint forces developers to reverse-engineer decisions the team already made, discarding the design work entirely. Each endpoint document must cover the HTTP method, resource path, and all parameters with their names, types, required-or-optional status, and applicable constraints. It must also specify the request body schema, the response schema for every status code the endpoint can return, and at least one example request-and-response pair including an error case.
OpenAPI (formerly Swagger), recognized as the de facto machine-readable standard for API documentation, makes this tractable. A single OpenAPI specification drives auto-generated client SDKs, mock servers, and interactive consoles simultaneously, keeping all three synchronized with the implementation.
Interactive documentation, a runnable interface where developers test against a live or mocked API, is a design deliverable produced before the API ships publicly. API documentation that is easy to understand and executable reduces integration friction; a developer who can run a real request does not need to file a ticket.
Three architectural patterns dominate web API design, each suited to a distinct set of requirements.
- REST, the foundation of most RESTful web services on the public web, is the right default for externally consumed APIs. Universal HTTP tooling, native browser support, HTTP-layer caching, and the largest ecosystem of client libraries make it the lowest-friction choice for teams serving external consumers.
- GraphQL suits clients with complex, variable data requirements, particularly dashboards and mobile apps that need different fields per screen. This flexibility comes at the cost of caching complexity and a heavier server-side implementation than REST requires.
- gRPC suits internal microservice communication where performance constraints preclude REST's text-based payloads. Binary Protocol Buffer encoding, bidirectional streaming, and strongly-typed interface contracts deliver the performance improvements that REST's text-based approach cannot provide at high-throughput service boundaries.
The architecture matters less than the discipline applied within it; resource modeling, versioning, and documentation are REST API best practices that apply regardless of which protocol a team adopts.
The priority order for applying these API design principles to a newly designed API differs from the order appropriate for a legacy system.
- Greenfield APIs: Establish resource modeling and HTTP semantics first, since these decisions define the shape of every subsequent interface contract. Security and versioning should follow before the first public release, with documentation deferred until the API's surface area is stable.
- Legacy APIs: Begin with versioning and a deprecation plan, which creates room for structural change without breaking consumers already in production. Resource naming and error handling can then be addressed incrementally, in stages that downstream teams can absorb without coordinating a simultaneous migration.
