A practical REST API models meaningful resources, uses HTTP methods consistently, validates every write, returns documented representations, and treats errors, authorization, pagination, retries, and change management as part of the contract. REST is one useful style, not a universal answer. Product workflows sometimes fit commands, events, GraphQL, or purpose-built endpoints better.
Who this is for: Backend and full-stack developers designing an HTTP API that multiple clients must use and maintain over time.
- Choose resource boundaries from domain behavior instead of mirroring database tables mechanically.
- Make method, status, retry, validation, and authorization behavior predictable for every endpoint.
- Evolve contracts additively when possible and measure real client use before removing fields.
Model resources around client intent
Resource names should represent concepts clients recognize, such as orders, invoices, or memberships. A database join table is not automatically a public resource, and one large business operation does not need to be forced into a sequence of fragile table-like writes. Start from use cases, ownership, lifecycle, and invariants.
Use stable identifiers and noun-oriented paths where they improve understanding. Nested paths can express ownership, but deep nesting couples navigation to one hierarchy. A command resource such as refund-requests can honestly represent a workflow with validation and review. Purity matters less than a coherent contract that preserves business rules.
Give HTTP semantics real meaning
GET should not cause an intended state change, while PUT and DELETE should support safe repetition according to their semantics. POST is appropriate for creation or processing that is not naturally idempotent. PATCH needs a documented patch format and conflict behavior. Clients should not have to guess whether repeating a timed-out request duplicates work.
Return statuses that describe the outcome, then add an application error code for precise handling. A successful creation can return 201 and a location. Invalid input can return a client error with field details. Authentication failure, insufficient authority, absence, conflict, throttling, and unexpected failure should remain distinguishable without exposing internal stack traces.
Design collections and writes for production
Large collections need bounded pagination with a stable ordering. Offset pagination is understandable but can skip or repeat records as data changes. Cursor pagination better follows a stable sort key but is less convenient for arbitrary page jumps. Document filters, sort fields, maximum page size, empty results, and cursor expiration.
For writes, validate syntax, domain rules, authorization, and current state on the server. Use transactions where several changes form one invariant. Conditional requests or explicit version fields can prevent lost updates. Idempotency keys can protect selected creates. Rate limits and body limits should fail with documented behavior rather than surprise clients at a proxy.
Plan compatibility and operations
Prefer additive evolution: new optional fields and new endpoints are generally easier than changing meaning. Even additions can break clients that reject unknown fields, so test known integrations. When a breaking change is necessary, define migration instructions, observability, deprecation dates, and an overlap period based on actual client constraints.
An API is also an operated system. Track latency, error rates, throttling, dependency failures, and endpoint use without recording secrets. Publish examples that demonstrate authentication safely. Generate or validate documentation from the contract where useful, but review whether the contract describes real runtime behavior. Version claims must come from current deployed evidence.
Design order cancellation
A commerce team needs customers to request cancellation while fulfillment may be advancing concurrently.
- Define cancellation-request as a workflow resource because cancellation can be accepted, rejected, or held for review.
- Accept a POST with an idempotency key, authenticated customer identity, order identifier, and allowed reason code.
- In one transaction, lock or conditionally update the order, verify ownership and cancellable state, and create the request outcome.
- Return a documented representation with status, safe reason, and next action, using conflict when current state prevents cancellation.
- Measure duplicate attempts and conflicts, and publish retry behavior for clients that lose the first response.
Endpoint contract worksheet
Complete this worksheet for each operation before implementation review.
- Intent and resource: user goal, resource lifecycle, owner, identifier, path, and method.
- Input: authentication, authorization, headers, body schema, limits, validation, and sensitive fields.
- Outcome: statuses, response schema, error codes, transaction boundary, and conflict behavior.
- Reliability: idempotency, retry rules, ordering, pagination, timeout, rate limit, and dependency failure.
- Evolution: consumers, compatibility promise, observability, deprecation process, and rollback plan.
Common mistakes
- Exposing every database table directly and leaking storage decisions into the permanent public contract.
- Using POST for every operation while leaving retries, conflicts, and statuses undocumented.
- Breaking old clients by changing a field's meaning while keeping the same name and endpoint.
Try one
Design the contract for adding a member to a private project when duplicate invitations and concurrent acceptance are possible.
A strong answer identifies invitation or membership as a resource, requires authenticated authority, validates the invitee without revealing private accounts, and defines duplicate behavior. It uses a transaction or uniqueness constraint for concurrency, explains whether a repeated request returns the existing result, distinguishes conflict from invalid input, and includes expiration, revocation, audit, and safe notification behavior.
Sources
- GitHub REST API documentationGitHub's primary documentation for REST API requests, resources, and versioning.
- MDN HTTP request methodsMDN's reference for HTTP method semantics, safety, and idempotency.
- MDN HTTP response status codesMDN's reference for standard HTTP response status codes.