Live data from Hacker News

How to Design Better APIs

r.bluethl.net

121–130 of 238 posts

Re: How to Design Better APIs

#121
post #5

Why would one prefer ISO 8601 dates over POSIX timestamps?

* Human readable * Supports birthdays for people older than 52 * Reliable after 2038 * Supports leap seconds * HTML date/time spec is a subset * String collation order matches temporal order * Excel

> * Human readable

Computers are the main consumers of APIs, and ISO 8601 is far from machine-readable.

For example, in Elixir, DateTime.from_iso8601/1 won't recognize "2022-03-12T07:36:08" even though it's valid. I had to rewrite a chunk of Python's radidjson wrapper to 1-9 digit fractional seconds (1).

I'm willing to bet 99% of ISO8601 will fail to handle all aspects of the spec. So when you say "ISO8601" what you're really saying is "our [probably undocumented, and possibly different depending on what system you're hitting] version of the ISO-86001 spec."

(1) https://github.com/python-rapidjson/python-rapidjson/pull/13...

Re: How to Design Better APIs

#122
> 6. Accept API key authentication ... using a custom HTTP header (such as Api-Key).

Wouldn't a bearer token [1] make more sense? Defined for use by OAuth2, but I don't see why it couldn't be the general mechanism for... bearer tokens.

> 11. Return created resources upon POST

Especially important if your database+caching layers use eventual consistency.

[1] https://datatracker.ietf.org/doc/html/rfc6750

Re: How to Design Better APIs

#123
I agree with most things.

I really hate when APIs use different api-key headers depending on the role of the consumer.

It is very annoying when you get dates that are not in the ISO format. There are reasons to not use UTC everywhere. One should make that decision.

The reason why many APIs use POST instead of DELETE is that POST is said to be more secure.

Many APIs that I use do not have neither of PATCH, PUT or DELETE. An order for instance will have an order status resource that one just keeps adding status entities to. In general, well-designed systems minimize the need for changing data.

Re: How to Design Better APIs

#124

> 6. Accept API key authentication ... using a custom HTTP header (such as Api-Key). Wouldn't a bearer token [1] make more sense? Defined for use by OAuth2, but I don't see why it couldn't be the general mechanism for... bearer tokens. > 11. Return created resources upon POST Especially important if your database+caching layers use eventual consistency. [1] https://datatracker.ietf.org/doc/html/rfc6750

Authentication and Authorization are two subtly different things. In this case, you may want an API key (Authentication) to be required to ensure things like rate limiting is enforced, but then want proof that the call is operating on a user, or is a machine-to-machine interaction which OAuth2 Bearer tokens work nicely for (Authorization)

Re: How to Design Better APIs

#125
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.

Re: How to Design Better APIs

#126
post #46
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…

It might be to formal for your use-case, but there is a standard defined for error responses in RFC 7807: https://datatracker.ietf.org/doc/html/rfc7807

That is stupid. Most of our failed requests are logged and logs are only read by dashboards and alarms. Sure, you can have a friendly message too but formalizing the errors in a structured way simplifies things and also improves the performance when scanning through large amount of logs.

Re: How to Design Better APIs

#127

Do you guys use plural or singular terms in your API endpoints or both? /books /books/:id /book /book/:id It gets harder to keep consistent when there are a lot of nouns that have the same singular/plural form like "clothing"

We use the form that represents a collection of objects. For example books and clothing both refer to a collection of things so I take them as valid forms

Re: How to Design Better APIs

#128
The PUT vs PATCH is debatable in different levels. One simple issue is how to resolve complex merges in a PATCH. For example if we patch a key that contains a list, what will be the expected result?

Re: How to Design Better APIs

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

Such simple approach is limited only to errors without arguments.

For more complex use cases, where we would want an error message to indicate that field value was too long and in addition provide maximum field length, we would need to introduce new field in the error response.

While it is solvable by adding this information to client application side. It would create a situation where the logic is duplicated in two places (backend and client application)...

Also if we would want better UX, then we would need to display all errors at the same time in the form that is incorrectly filled. This would require changing error structure to return array of errors and it potentially create a breaking change in the API or would result in confusing structure that supports both, legacy and new format...

Some years ago, I wrote an article sharing the ideas on how REST API error structuring could be done depending on the complexity of application or service: https://link.medium.com/ObW78jhDkob

Re: How to Design Better APIs

#130

Earlier quoted context omitted.

Chrome, Safari, Firefox, Edge, and Opera are all third-party clients for the HATEOAS-based API known as the World-Wide Web.

What?

The web (HTTP + HTML + JS) intentionally fits the definition of a REST API. https://oleb.net/2018/rest/

In particular:

> The central idea behind HATEOAS is that RESTful servers and clients shouldn’t rely on a hardcoded interface (that they agreed upon through a separate channel). Instead, the server is supposed to send the set of URIs representing possible state transitions with each response, from which the client can select the one it wants to transition to. This is exactly how web browsers work

Post reply on HN