Live data from Hacker News

Everything I know about good API design

seangoedecke.com

51–60 of 168 posts

Re: Everything I know about good API design

#52
post #38
post #31

Earlier quoted context omitted.

I don't see any harm in adding versioning later. Let's say your api is /api/posts, then the next version is simply /api/v2/posts.

It's a problem downstream. Integrators weren't forced to include a version number for v1, so the rework overhead to use v2 will be higher than if it was present in your scheme to begin.

This here, it's way easier to grep a file for /v1/ and show all the api endpoints then ensure you haven't missed something.

Re: Everything I know about good API design

#53
post #20

Anyone else old enough to remember when "API" also meant something that had nothing to do with sending and receiving JSON over HTTP? In some cases, you could even make something that your users would install locally, and use without needing an Internet connection.

[deleted]

Re: Everything I know about good API design

#54

Earlier quoted context omitted.

There are other options that allow long-lived access with naturally rotating keys without OAuth and only a tiny amount of complexity increase that can be managed by a bash script. The refresh token/bearer token combo is pretty powerful and has MUCH stronger security properties than a bare API key.

Refresh tokens are only really required if a client is accessing an API on behalf of a user. The refresh token tracks the specific user grant, and there needs to be one refresh token per user of the client. If a client is accessing an API on behalf of itself (which is a more natural fit for an API Key replacement) then we can use client_credentials with either client secret authentication or JWT bearer authentication…

That is a very specific form of refresh token but not the only model. You can just easily have your "API key" be that refresh token. You submit it to an authentication endpoint, get back a new refresh token and a bearer token, and invalidate the previous bearer token if it was still valid. The bearer token will naturally expire and if you're still using it, just use the refresh immediately, if its days or weeks later you can use it then.

There doesn't need to be any OIDC or third party involved to get all the benefits of them. The keys can't be used by multiple simultaneous clients, they naturally expire and rotate over time, and you can easily audit their use (primarily due to the last two principles).

Re: Everything I know about good API design

#55
post #13
post #4

While the author doesn't seem to like version based APIs very much, I always recommend baking them in from the very start of your application. You cannot predict the future and chances are there will be some breaking change forced upon you by someone or something out of your control.

If there is a breaking change forced upon in the future, can’t we use a different name for the function?

Discoverability.

/v1/downloadFile

/v2/downloadFile

Is much easier to check for a v3 then

/api/downloadFile

/api/downloadFileOver2gb

/api/downloadSignedFile

Etc. Etc.

Re: Everything I know about good API design

#56
post #13
post #4

While the author doesn't seem to like version based APIs very much, I always recommend baking them in from the very start of your application. You cannot predict the future and chances are there will be some breaking change forced upon you by someone or something out of your control.

If there is a breaking change forced upon in the future, can’t we use a different name for the function?

If you only break one or two functions, it seems ok. But, some change in a core data type could break everything, so adding a prefix "/v2/" would probably be cleaner.

Re: Everything I know about good API design

#57
post #46

Earlier quoted context omitted.

otoh staticly-linked executables are incredibly stable - it's nice to have that option.

From what I understand, statically linking in GNU's libc.a without releasing source code is a violation of LGPL. Which would break maybe 95% of companies out there running proprietary software on Linux. musl libc has a more permissive licence, but I hear it performs worse than GNU libc. One can hope for LLVM libc[1] so the entire toolchain would become Clang/LLVM, from the compiler driver to the C/C++ standard librar…

AFAIK, it's technically legal under the LGPL to statically link glibc as long as you also include a copy of the application's object code, along with instructions for how users can re-link against a different glibc if they wish. You don't need to include the source for those .o files.

But I don't think I've ever seen anybody actually do this.

Re: Everything I know about good API design

#58
post #4

While the author doesn't seem to like version based APIs very much, I always recommend baking them in from the very start of your application. You cannot predict the future and chances are there will be some breaking change forced upon you by someone or something out of your control.

I have to agree with the author about not adding "v1" since it's rarely useful. What actually happens as the API grows- First, the team extends the existing endpoints as much as possible, adding new fields/options without breaking compatibility. Then, once they need to have backwards-incompatible operations, it's more likely that they will also want to revisit the endpoint naming too, so they'll just create new endpo…

> So in the end, it's really rare that any endpoints ever have "/v2" in the name.

This is an interesting empirical question - take the 100 most used HTTP APIs and see what they do for backward-incompatible changes and see what versions are available. Maybe an LLM could figure this out.

I've been just using the Dropbox API and it is, sure enough, on "v2". (although they save you a character in the URL by prefixing "/2/").

Interesting to see some of the choices in v1->v2,

https://www.dropbox.com/developers/reference/migration-guide

They use a spec language they developed called stone (https://github.com/dropbox/stone).

Re: Everything I know about good API design

#59
post #20

Anyone else old enough to remember when "API" also meant something that had nothing to do with sending and receiving JSON over HTTP? In some cases, you could even make something that your users would install locally, and use without needing an Internet connection.

> sending and receiving JSON over HTTP

In my circles this is usually (perhaps incorrectly) called REST API.

Re: Everything I know about good API design

#60
> How should you store the key? I’ve seen people store it in some durable, resource-specific way (e.g. as a column on the comments table), but I don’t think that’s strictly necessary. The easiest way is to put them in Redis or some similar key/value store (with the idempotency key as the key).

I'm not sure how would storing a key in Redis achieve idempotency in all failure cases. What's the algorithm? Imagine a server handling the request is doing a conditional write (like SET key 1 NX), and sees that the key is already stored. What then, skip creating a comment? Can't assume that the comment had been created before, since the process could have been killed in-between storing the key in Redis and actually creating the comment in the database.

An attempt to store idempotency key needs to be atomically committed (and rolled back in case it's unsuccessful) together with the operation payload, i.e. it always has to be a resource-specific id. For all intents and purposes, the idempotency key is the ID of the operation (request) being executed, be it "comment creation" or "comment update".

Post reply on HN