How to (and how not to) design REST APIs
41–50 of 153 posts
Re: How to (and how not to) design REST APIs
#42Re: How to (and how not to) design REST APIs
#43Some good points - particularly about not returning arrays (I've made that mistake!) But I feel 410 instead of 404 is pretty controversial: > There are many layers of software that can return 404 to a request Anything in your stack can return any HTTP error code - I don't see why 404 is special. > When calling (say) GET /things/{thing_id} for a thing that doesn't exist, the response should indicate that 1) the server…
Or even more simple: Anything other than 200 means check infrastructure docs and if you don't like the 200 check the business requirements.
Re: How to (and how not to) design REST APIs
#44Rule #1 is terrible advice. Avoid plural nouns in English API endpoints because English is full of irregular plurals. For example: goose -> geese child -> children index -> indices vertex -> vertexes analysis -> analyses This makes English plurals unpredictable especially for for non-native speakers and hurts API consistency and discoverability. Also consider that for a CRUD interface you may need the singular form a…
You use plurals anyway to fetch collections: GET /students So you can't escape the problem unless you want `GET /child` to fetch multiple children. Also, you should avoid verbs in URLs (IMHO, of course). You're adding to the students collection, so post to students: # BAD POST /student/create # GOOD POST /students
If you think `GET /student` is confusing, or more importantly, structurally restrictive as an API, you can think about it as `GET /student/filter` where the "filter" may be a specific student id, or a range of ids, or other conditions such as `GET /student/top` or `GET /student/graduated` and then all students will be just the filter "all" or: `GET /student/all`.
As for `POST /student/create`... it doesn't matter. To use one of Fielding's own examples from his blog, how'd you turn a lamp on and off via REST? Would you be like `POST /lamp`? No. It's unclear WTF is happening.
Re: How to (and how not to) design REST APIs
#45I highly recommend anyone to read Google's [AIP]( https://google.aip.dev/ ). There's even a grpc schema linter for it. Put more focus on the resource data design than nitpicking on transport details. I would consider the best lessons to be: - Optional but supported user defined identifiers, it's so frustrating to work with API that passes you back an identifier. - String identifier (names) for resources, with some ki…
Resource Oriented Design: https://google.aip.dev/121
Declarative Friendly APIs: https://google.aip.dev/128
Declarative friendly makes writing scripts, pipelines so much better because of idempotency. It also pairs very naturally with resource Oriented design.
Long Running Operations: https://google.aip.dev/151
LROs are applicable to any request that runs longer than a second or a couple of seconds. Having a unified interface can be very powerful for implementing offline task workers and pipelines.
Filtering: https://google.aip.dev/160
This one is probably controversial as it's makes implementing basic filtering quite a bit harder. I haven't quite seen the issues it's supposed to solve play out in practice but it's interesting nonetheless.
Re: How to (and how not to) design REST APIs
#46“RESTful” API design is mostly bike-shedding. There’s no standard. Every REST API looks different. Clients have to refer to documentation anyway, so consistent URL patterns achieve nothing. People waste large amounts of time over totally inconsequential minutiae like whether to use singular or plural words in URLs. Separating idempotent calls from non-idempotent calls is useful, but REST overcomplicates this. All tha…
Re: How to (and how not to) design REST APIs
#47I’d add: * If you’re going to forbid people changing a parameter with a PUT or PATCH request, then the schema for these shouldn’t list them as parameters. This seems to creep in to APIs constantly as people are lazy and will use the same serializer method as for POST with an additional check somewhere in the code that changes the response. Just don’t do it! * Don’t change the response format based on query parameters…
What I have seen is endpoints trying to corral their responses into one-size-fits-all schemas in the situation you're describing, with predictable outcomes. Lots of overhead in most situations, tricky documentation, lots of optionals.
Under that premise, I have to say that at least for generic APIs with many differing clients, the idiosyncrasies of typed-language clients would not rank too highly on my list of design considerations — not when they are in the way of simpler, easier to understand responses.
Re: How to (and how not to) design REST APIs
#48Rule 1 - "DO use plural nouns for collections" - is an entirely arbitrary opinion.
Rule 2 - "DON'T add unnecessary path segments" - I agree with the rule, but the examples are bad because, e.g., "/listings/{listing_id} " and "/shop/{shop_id}/listings/{listing_id}" mean two different things (or at least they should). Now, "/shop/{shop_id}/listings/{listing_id}" is a complex path, so if your API doesn't need it, then I agree, don't include it. But if it does, then it would be bad to not include it.
Rule 3 - "DON'T add .json or other extensions to the url" I mostly agree with the rule, but on the grounds of keeping things simple. Here, keeping to the standard (which means using Accept). But things like supporting a ".json" suffix are nice for cases where you want to give people (not programs) access to the different representations (should be in addition to Accept).
This justification for rule 3: "URLs are resource identifiers..." is simply not true, at least for any reasonably useful definition of identifier. A URL points at a resource, that's it.
Rule 4 is good. ("Rule #4: DON'T return arrays as top level responses") You want to keep the door open to adding metadata in the response body that will be very easy for clients to accept in a backwards-compatible manner.
Rule 5 "DON'T return map structures" doesn't really make sense. Now, you shouldn't do it just to provide a lookup index -- the id should really be the inherent id of the data -- but it's a logically valid way to structure data and your API should strive to match the logical structure of the data. Also, the arguments here are not great.. e.g., "Converting an array of objects to a map is a one-liner in most languages"... that's true, but so is the converse. The openapi example doesn't make sense either. openapi v4 could have simply added a "name" property to the object in the v3 structure, right next to the "post" property -- just like the hypothetical list-based API. I would assume openapi has other reasons for the restructure, because the map-based API doesn't force it.
Well, I'll stop there. It's not all bad, but just don't take these rules to the bank.
Wait one more: Rule 8 "DON'T use 404 to indicate not found"
Come on now, why even write something like that?
The rule is more like, don't use 404 poorly. DELETE should be idempotent (that's a good rule), which means an attempt to DELETE something that could exist but doesn't happen to exist right now, isn't an error, and should return a 2xx code. 404 response for an attempt to delete on a route that doesn't exists makes sense (well, I guess unless your API is so dynamic that routes can be created and deleted on the fly, in which case even there you'd return a success code).
Re: How to (and how not to) design REST APIs
#49Rule #1 is terrible advice. Avoid plural nouns in English API endpoints because English is full of irregular plurals. For example: goose -> geese child -> children index -> indices vertex -> vertexes analysis -> analyses This makes English plurals unpredictable especially for for non-native speakers and hurts API consistency and discoverability. Also consider that for a CRUD interface you may need the singular form a…
Re: How to (and how not to) design REST APIs
#50Rule #1 is terrible advice. Avoid plural nouns in English API endpoints because English is full of irregular plurals. For example: goose -> geese child -> children index -> indices vertex -> vertexes analysis -> analyses This makes English plurals unpredictable especially for for non-native speakers and hurts API consistency and discoverability. Also consider that for a CRUD interface you may need the singular form a…
You use plurals anyway to fetch collections: GET /students So you can't escape the problem unless you want `GET /child` to fetch multiple children. Also, you should avoid verbs in URLs (IMHO, of course). You're adding to the students collection, so post to students: # BAD POST /student/create # GOOD POST /students
What I've generally done in these cases is pretty similar to https://cloud.google.com/apis/design/custom_methods which also explains the problem better than I can.
I'd be interested as to how you'd solve some of these problems without an explicit verb in the path.