Live data from Hacker News

How to (and how not to) design REST APIs

github.com

41–50 of 153 posts

Re: How to (and how not to) design REST APIs

#43

Some 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…

I prefer to consider 404 as protocol error and missing thing as business error. That way 404 signals wrong endpoint and 200 + error message + empty result set signals wrong id.

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

#44

Rule #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

An API is not an essay, in OOP you write Array and not Array and yet you understand the type is about an array of students. Getting hung up on grammar in an API is probably the dumbest problem to have.

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

#45

I 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…

Second this. Reading this while working at google made me better design. Some that stand out to me are.

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
post #38

“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…

Agree. But I pick REST (or “json over http”) any day of the week instead of graphql, soap, grpc, etc.

Re: How to (and how not to) design REST APIs

#47

I’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…

I very much agree with your first and third point, from experience. As for the second one — if consuming dynamic data structures is hard in typed languages, maybe they are not the right tool for that particular job?

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

#48
There are a bunch of bad rules here...

Rule 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

#49

Rule #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…

It gets even more unpredictable for everyone involved when it's a non-native speaker who writes the API schema.

Re: How to (and how not to) design REST APIs

#50

Rule #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

While I do agree with this in almost all cases, I have found scenarios where there are actions that don't map easily to a HTTP verb and need something more explicit.

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.

Post reply on HN