By the design of HTTP (RFCs 7230-7235), each endpoint represents a thing that the server is keeping track of, usually called a Resource
. Sometimes that Resource is just one thing (like a single widget), and sometimes it's a group of things (or widgets). The URI is intended to be a unique specifier for a widget or group of widgets.
Most APIs use human-readable names and ids to identify these things in URIs. Some security-minded services do not do this, because it exposes information to end users that the service does not want them to have. Among human-readable APIs, the convention has become to use plural nouns to indicate collections, a plural noun followed by a unique identifier to indicate an individual item in a collection. These can nest - an individual item might itself have either a collection or individual item you want to expose directly. So:
/widgets > all the widgets the user can see
/widgets/12 > a specific widget
/widgets/12/texture > a widget has zero or one textures
/widgets/12/colors > a widget has zero or more colors
/widgets/12/colors/5 > color #5 of widget #12
The above approach is typically called RESTful
, even though REST
is really a lot more than just that. The other common approach is called Remote Procedure Calls
, or RPC
for short. In RPC, endpoints represent instructions to the server, such as /writeEndOfYearCsv
. If a client were to call that URL with a POST, the response might stream a CSV file with the end-of-year report. RPC is waning in popularity because it's believed to be harder to maintain over time. Properly written RPC will only use POST and GET calls.
Query parameters, defined in RFC 3986, are used to narrow down the details of a response to a URI. They are used most often with "collection resources", such as /widgets?shape=round
, to narrow down the contents of the collection. In general, they are used to provide information to the server about how to build the response.
For instance, /widgets/12?expand=texture
might return a widget resource with the texture information embedded in it, while /widgets/12
would only return the direct properties of the widget. A client who doesn't care about the texture doesn't have to get it, and a client who does care can save a server hit by getting the information embedded rather than just a link.
In RPC
, you would use query parameters for about the same thing: POST /writeEndOfYearCsv?format=csv
would give you a CSV report, while POST /writeEndOfYearCsv?format=xslx
would give you an Excel report.
The body of a request typically contains the resource being created/modified (if you're using a REST
ish approach), or instructions on how to process the request (if you're using an RPC
approach). So when creating or updating a widget, the request would contain all the information about what makes up a widget (colors, texture, name, etc). When asking for an end-of-year report, the request might contain the year the request is for, the clients to include in the report, etc.
It is still possible to use RPC-style requests in a REST
ish system. You just need to think of the request itself as a resource. So POST /reports/end-of-year
with a body containing instructions would create a new report, and you could later GET /reports/end-of-year/9
to view that report.
If it seems like RPC-style requests blur the lines heavily in terms of where things "belong", that's because they do. Since HTTP was designed around a "URL-as-resource" paradigm and RPC was squeezed in on top of that, it's often up to individual developers to figure out where the right place is for a specific instruction. If you use RPC (and in general, you should try not to), figure out a general rule and be consistent within your service as to what goes where.
The body of a request or response typically depends on the type of request. In REST, the body and the response are always resource representations, but sometimes that resource is really an instruction. You would