Overview#
Resource-oriented APIs typically expose a small set of standard methods that cover the majority of interactions: get, list, create, update (PATCH), replace (PUT), and delete. These methods come with expectations about behavior (e.g., idempotence, lack of side effects, and consistency) that make APIs predictable for consumers.
“Whenever you rely on standards rather than entirely custom-designed tooling, you give up some flexibility.”
GET
— standard get method#
Purpose: return the resource record stored for a specific identifier (key-value lookup).
“The goal of the standard get method is very straightforward: the service has a resource record stored somewhere and this method returns the data stored in that record.”
Key properties
- Accepts only the resource identifier as input.
- Should be idempotent and have no noticeable side effects.
- Intended as a pure read: repeated calls (absent concurrent changes) return the same result.
LIST
— standard list method#
Purpose: browse a collection and return all resources that belong to it.
“In a list method, you provide a specific collection that you need to browse through and the result is a listing of all the resources belonging to that collection.”
Important considerations
Targeting: listing a top-level collection (e.g.,
/chatRooms
) vs. a subcollection (e.g.,/chatRooms/{id}/messages
).Access control: responses must include only resources the requester can access — different requesters can legitimately receive different views.
“The response should only include the resources the requester has access to.”
Result counts, sorting, and filtering
Result counts: generally discouraged because exact counts are expensive in large/distributed systems. If required, prefer an estimate and name it as such (e.g.,
resultCountEstimate
).“In short, it’s generally a bad idea to include item counts in the responses to a standard list method.”
Sorting: also discouraged for similar reasons — global sorting across multiple storage backends is costly and hard to scale.
“This tiny little feature tends to add a significant amount of complexity in the future for relatively little value to the API consumer.”
Filtering: encouraged — server-side filtering saves bandwidth and CPU. Prefer conveying filters as strings (parsed by the server) rather than a rigid typed schema, because string filters evolve more flexibly.
“…the best choice of data type for conveying the filter itself is a string, which can then be parsed by the server…”
CREATE
— standard create method#
Purpose: introduce a new resource so it can be retrieved by its identifier or discovered via list
.
“The goal of the standard create method is simple: given some information about a resource, create that new resource in the API such that it can be retrieved by its identifier or discovered by listing resources.”
Identifiers
Prefer server-generated IDs in most cases.
“it’s usually best to rely on server-generated identifiers for newly created resources.”
Client-chosen IDs are acceptable when needed (e.g., offline clients that must sync local and remote resources), but follow strict guidelines if allowed.
If clients supply IDs in
create
, put the ID in the resource body (e.g.,POST /chatRooms { id: 1234, ... }
).
Consistency
Standard methods expect strong consistency: once
create
returns success, the resource should be visible toget
,list
,update
, anddelete
.“One of the most important aspects of an API is its transactional behavior, and one of the key aspects of that is strong consistency.”
If your storage cannot provide strong consistency (e.g., eventually consistent distributed stores), consider using custom methods (e.g.,
ImportLogEntries
) or long-running operations rather than breaking the standardcreate
expectations.
UPDATE
— standard update method (PATCH)#
Purpose: partially modify an existing resource; update only the fields the client explicitly requests.
“The recommended way to update a resource relies on the HTTP PATCH method… One key aspect of the PATCH method is that it does partial modification of a resource rather than a full replacement.”
Notes
- Use PATCH to change specific fields; be careful about intent (e.g., distinguishing “don’t touch this field” vs. “set this field to blank”).
- Some changes (especially state transitions) may be better modeled as custom methods (e.g.,
ArchiveChatRoom()
), not as field updates.
REPLACE
— semi-standard replace method (PUT)#
Purpose: fully replace the resource with exactly the request payload.
“The semi-standard replace method’s goal is exactly that: replace an entire resource with exactly the information provided in this request.”
When to use
Use PUT/replace when a client wants the remote copy to exactly match the supplied representation — unknown or extra fields on the server side are removed if not provided in the request.
Replace can also be used to create a resource at a client-provided ID, but this should not replace the standard
create
method because clients sometimes need atomic guarantees like “create only if not exists” or “update only if exists.”“…there are cases where API consumers may want to create a resource if (and only if) the resource doesn’t already exist.”
DELETE
— standard delete method#
Purpose: remove a resource so it no longer exists.
“…the successful result of a standard delete method is to have the resource disappear entirely.”
Idempotence discussion
There are two perspectives:
Declarative/result-focused: deleting an already-deleted resource can be considered a success (idempotent).
“…deleting a resource that has already been deleted should be considered a success… therefore making the method idempotent.”
Imperative/action-focused: attempting to delete a non-existent resource is a failed action (non-idempotent); second call may return 404.
“…resource-oriented APIs are generally imperative in nature. As a result, the standard delete method should behave in the non-idempotent manner.”
The text advocates the imperative interpretation for resource-oriented APIs: deleting a non-existent resource should fail.
Cross-cutting principles#
- Idempotence: standard reads should be idempotent; behavior for delete depends on whether you treat the method as declarative or imperative.
- Minimize side effects: standard methods should avoid noticeable side effects (e.g., contacting third-party services). Small internal logging is typically okay if it does not alter the response or cause failures.
- Strong consistency expectation: standard methods carry an expectation that once an operation succeeds, the resource is immediately available to other standard operations.
- Use custom methods when semantics differ: if storage or domain semantics prevent meeting standard expectations (consistency, idempotence, etc.), prefer custom RPC-style methods with explicit names that document their behavior.
Trade-offs#
Using standard methods buys discoverability, predictability, and broad reusability at the cost of some flexibility. They’ll satisfy the majority of scenarios (“90% of the way there”), while custom methods handle the special cases.
“Standard methods should (and likely will) get an API 90% of the way there. And for the rest of the scenarios, you have custom methods to explore…”