Free tools Windows power users keep installed
One-click scans. No signup required.
The useful lesson behind a headline like this is not “serve everything from one GET.” It is that the URLs in an API should follow the resources clients work with, and the HTTP method should carry the meaning of the action. When an API accumulates many GET endpoints for one thing, the usual cause is that each endpoint was named after a question or a field instead of a resource. This article covers that design principle, not a particular codebase.
What GET actually promises
The HTTP semantics standard, RFC 9110 from the Internet Engineering Task Force (June 2022), defines GET in Section 9.2.1: “The GET method requests transfer of a current selected representation for the target resource.” Two properties matter for design. GET is safe, meaning the client is not asking the server to perform a state-changing action. GET is also idempotent, meaning that repeating the request is intended to have the same effect as sending it once.
As an Amazon Associate I earn from qualifying purchases.
Two clarifications prevent common misreadings. “Safe” describes what the client is asking for, not whether the server does literally nothing; incidental server work such as logging is not ruled out. “Idempotent” describes the intended effect of repeating a request, not byte-identical responses. Two GET calls a minute apart can return different data because the resource changed in between, and that is consistent with the standard.
Why GET endpoints multiply
Several GET URLs are normal. A collection and each of its items need their own addresses, and different resources have different URLs. The problem appears when the number of GET endpoints grows faster than the number of resources. Typical signs are:
#1 Best Overall
- Endpoints named after a single attribute of an object, such as one URL for an object’s name, another for its status, and another for its count.
- Endpoints named after a verb, such as a GET route that performs an action. For example,
GET /rents/42/cancelchanges state, which breaks the meaning that clients, caches, and retry logic rely on. - Several parallel URLs that expose the same resource in slightly different shapes, when one representation with optional fields would serve every caller.
- Client code that has to make a long chain of GET calls to assemble a single screen, which usually means the resource boundaries were drawn around database tables or internal functions rather than around what users actually work with.
Model the resource first, then choose the method
Ximenes and Juvenal’s O’Reilly walkthrough of designing a bike-rental API (published December 21, 2017) gives a practical sequence for avoiding ad hoc endpoints. Its example is illustrative, so treat it as a method rather than a universal template:
- Describe what users need to do in their own words, before naming any endpoint.
- Separate the nouns, which become resources such as a station or a rental, from the verbs, which usually become method choices applied to those resources.
- Give each resource a collection URL and an item URL.
- Choose the method by effect: read with GET, create with POST, replace or update with PUT, and remove or cancel with DELETE.
The article captures the principle in one sentence: “The correct way to rent something via HTTP is to POST a Rent.” The point is not that rentals must always use POST, but that “rent” is modeled as a thing that gets created rather than as a new verb invented for the API.
Rank #2
The bike-rental example, mapped
| Request | Target | Effect |
|---|---|---|
GET /stations/ |
Station collection | Returns the stations, including the available-bike quantity for each |
POST /rents/ |
Rental collection | Creates a rental |
GET /rents/ |
Rental collection | Returns rental history |
PUT /rents/{id}/ |
One rental | Updates its destination |
DELETE /rents/{id}/ |
One rental | Cancels the active rental |
The example has two GET URLs, and that is the lesson in miniature: it has two collections to read, not one endpoint per question. There is no /getAvailableBikes, no /cancelRent, and no /changeRentDestination. Each action lands on a method attached to a resource. The same article recommends Mike Amundsen’s RESTful Web Clients as further reading on RESTful architecture.
Recommended Free Tools
Should related fields share one representation?
This is the judgment call that most often produces a long list of GET endpoints, and it has no single right answer. Each choice has a cost:
Rank #3
| Choice | Benefit | Cost |
|---|---|---|
| One representation with related fields included | Fewer requests; a client can render a screen from one response | Larger payloads that some clients do not need; changes to one field can ripple into every consumer |
| Separate resources for each related piece | Each piece can be requested, cached, and versioned on its own | More round trips; clients must assemble the pieces themselves |
The bike-rental example includes availability in the station collection because the client’s use case, choosing a station, needs it. A field that only an administrative screen reads would not belong in that representation. Use the client’s use case to decide, then check the design against five questions:
- Does each URL identify a resource, or an ad hoc operation?
- Does the representation answer the client’s use case without excessive payload?
- Does each method’s effect match read or state-changing behavior?
- Are cache and retry behavior clear to a client that has never seen the code?
- Can the API change without forcing clients to depend on the database’s internal structure?
Does idempotent mean a GET always returns the same data?
No. Idempotence is a statement about the intended effect of a request, so a GET for a station’s bike count can legitimately return a different number each time. Caching is a separate matter. Whether a GET response may be stored and reused depends on its response headers and the HTTP caching rules, such as the Cache-Control directives. Do not assume every GET response is cached, and do not assume a cached response is current without checking those headers.
Rank #4
Retries carry the most practical risk. Because GET is defined as safe and idempotent, clients, proxies, and link prefetchers often repeat or speculatively issue GET requests. A GET route that cancels a rental will cancel it again on every retry or prefetch. In that case the fault is the route design, not the protocol, and the fix is to move the cancellation to DELETE on the rental resource.
Where the lesson applies, and where it does not
The principle is not a rule against multiple GET methods. It is a rule against GET endpoints whose names describe questions, fields, or actions instead of resources. An API with a dozen GET URLs can be well designed if each URL names a real resource and each action uses the method that matches its effect. An API with two GET URLs can be badly designed if one of them changes data.
The O’Reilly example is one walkthrough of this process, and it is deliberately small. Larger systems will have more resources, and the same questions still apply to each one.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




