Live data from Hacker News

How to Design Better APIs

r.bluethl.net

131–140 of 238 posts

Re: How to Design Better APIs

#131

Earlier quoted context omitted.

What is the reason?

I don’t know what OP thinks is the reason, but the actual reason is CORS. Web Devs (such as me) have asked for e.g. DELETE as an acceptable formmethod (e.g. https://github.com/whatwg/html/issues/3577 ) however WHATWG always pushes back citing security concerns such as CORS. I suspect this is not what OP had in mind since it is trivial to send a DELETE request with a simple JavaScript: Delete

Right.

If CORS can be weakened in any simple way with that HTRP-DELETE method, then your database could simply disappeared via HTTP-DELETE method.

Besides, webmasters’ HTTP DELETE method is a different domain scoping issue than the web developers’ HTML/JavaScript FORM deleteThis row-entry approach.

I marvel at designers trying to flatten the scoping/nesting of abstractions without factoring apart the disparate error and protocol handling.

Re: How to Design Better APIs

#132

Earlier quoted context omitted.

Cursor-based pagination doesn't solve your state issue, it forces the server to create a copy of state for the cursor request. This is complex to implement correctly - for example, if the user does not actually paginate through all the entries, when do you dump the unused cursor? If the user issues the same request over and over, do you return a cached cursor or re-copy the state into a new cursor? If you re-copy the…

You appear to be referring to a database cursor. It is quite simple to implement pagination in the application layer using a unique record identifier (primary key or ULID or ...) as an anchor for the navigation. From that unique ID, we can then fetch the previous `n` or the next `n` records, depending on the direction of the navigation. This way, the server remains stateless, since the anchor (possibly sent as an enc…

What if that particular unique ID is deleted right before the client requests the next page?

Re: How to Design Better APIs

#133
post #2

The error messages could be better yet. The example uses a different code per issue, for instance: "user/email_required". Most integrators will build their UI to highlight the input fields that contain an error. Making them parse the `code` field (or special-case each possible code) is pretty toilsome. // from blog post { "code": "user/email_required", "message": "The parameter [email] is required." } Make it parseab…

Localization has entered the chat. You need codes because the field isn't going to be 'email' for much longer than it takes for your management to realize that people outside of the US also have wallets.

No doubt they exist, but I’ve never seen an api that localised identifiers.

Re: How to Design Better APIs

#134
post #70

Can someone share how they handle versioning in their API when it comes to data model changes? For example `POST /users` now takes a required field `avatar_url` but it was not part of `v1`. Since this field is validated in the DB, merely having `v1` `v2` distinction at the API layer is not sufficient. So I was thinking we will have to either 1) disable DB validations and rely on app validations or 2) run two separate…

I really like this way of versioning https://medium.com/@XenoSnowFox/youre-thinking-about-api-ver... It uses Accept and Content-Type to version resources: application/vnd.company.article-v1+json

Interesting! Personally, if I had to go to the lengths of the article, I might as well use a schema registry like Avro.

Re: How to Design Better APIs

#135

Extra points: document the API / have an API technical writer in the team. Part of a good API design is documenting it. If you use an API specification format, such as OpenAPI, design and documentation overlap nicely.

Ah yes, the classic:

POST /document/:id?params

Creates a document with parameters

Re: How to Design Better APIs

#136

Sometimes, I feel that we ought to have a simple protocol, on top of HTTP, to simply do remote procedure calls and throw out all this HTTP verbs crap. Every request is a http POST, with or without any body and the data transfer is in binary. So that objects can be passed back and forth between client and server. Sure, there is gRPC, but it requires another API specification (the proto files). There I said it. HTTP Ve…

While I totally agree with the overkill that REST can be, I really do NOT agree with your statement:

> but it requires another API specification

This implies API-specs are part of the problem; and I think they are not.

Specs that have generators for client-libs (and sometimes even sever-stubs) are verrrrry important. They allow us to get some form of type-safety over the API barrier which greatly reduces bugs.

One big reason for me to go with REST is OpenAPIv3: it allows me to completely spec my API and generate clients-libs for sooo many languages, and server-stub for sooo many BE frameworks. This, to me, may weight up to the downsides of REST.

GraphQL is also picking up steam and has these generators.

JSON-RPC (while great in terms of less-overkill-than-REST) does not have so much of this.

Re: How to Design Better APIs

#137
post #44

Sometimes, I feel that we ought to have a simple protocol, on top of HTTP, to simply do remote procedure calls and throw out all this HTTP verbs crap. Every request is a http POST, with or without any body and the data transfer is in binary. So that objects can be passed back and forth between client and server. Sure, there is gRPC, but it requires another API specification (the proto files). There I said it. HTTP Ve…

I don't think I've ever come across any third party actually implementing HATEOAS ( https://en.wikipedia.org/wiki/HATEOAS )

I used some API recently that returns URLs in the response body. It's really useful because they maintain those URLs and we don't have to rewrite our URL building code whenever the server side rules change. Actually we don't even have to write that code. It saves time, bugs, money.

I don't remember which API was that, I'll update the comment if I do.

Re: How to Design Better APIs

#138
post #132

Earlier quoted context omitted.

You appear to be referring to a database cursor. It is quite simple to implement pagination in the application layer using a unique record identifier (primary key or ULID or ...) as an anchor for the navigation. From that unique ID, we can then fetch the previous `n` or the next `n` records, depending on the direction of the navigation. This way, the server remains stateless, since the anchor (possibly sent as an enc…

What if that particular unique ID is deleted right before the client requests the next page?

If the IDs are monotonous, it doesn't matter.

Re: How to Design Better APIs

#139
post #4

Some nice tips in here. However, tip 15, I strongly disagree with: > 15. Allow expanding resources I would suggest the opposite. A REST API should not return nested resources at all. Instead, and to stay with the example provided on the website, to obtain the "orders", the /users/:id/orders endpoint should be called. It might be tempting to return nested resources, because clients would only have to make a single cal…

I've consumed the kinds of APIs you're referencing and they are my least favorite. I would prefer a poorly documented API over one that returns me 15 IDs that I must look up in separate calls. I think there's a reason those APIs also tend to have rate limits that are way too low to be useful.

We're querying dozens, if not into hundreds, of GraphQL APIs for a couple of years now. Terrible DX, terrible performance, terrible uptimes. Everyone on the team, with no exception, hates them. Even a lot of those who produce them cobble together a bad REST implementation for parts of their own products.

Agreed even at rate limits comment - frequently, probably in moments of desperation, they rate limit according to Host header to keep their own products up and working.

Re: How to Design Better APIs

#140
post #82

Earlier quoted context omitted.

I upvoted because I'm curious to hear what others are doing. We typically make sure to only make such breaking changes where either the now-required value or a sane filler value could be used. If it's the same API for the same purpose, it's usually not a stretch to assume the values for a new field are derived from some combination of an old field or else are primitive components of an old field such that they can be…

Thanks. This is a fair point. I made up the example only to illustrate the idea. Since Stripe is considered some sort of benchmark here I was curious to see how they tackle all the learnings they will have over time...I feel it is very hard to think through all the future cases especially when you are just about starting out with your product. For example, in financial services and insurance, regs change and what dat…

Hey

We're working in this space at the moment, (eliminating the pain from breaking changes in APIs) and looking to get feedback on what we're building.

We're all from banking backgrounds, so understand the reg headaches you're talking about.

Can we chat?

Post reply on HN