Live data from Hacker News

How to Design Better APIs

r.bluethl.net

191–200 of 238 posts

Re: How to Design Better APIs

#191
post #178

Earlier quoted context omitted.

Well I imagine this is why sages like uncle bob and sam newman will always be needed. > Validation errors are errors and network failures are errors, but they’re very different animals and should never be conflated. > I don’t want to check for a status code in metadata ever, when an HTTP status is provided. These seem like conflicting views. If the HTTP status is all you check you must be conflating application/opera…

I think I'm with Jack on this one, at least when it comes to REST interfaces. When I query GET /bar/123, I want an object with a Bar protocol/content-type. I don't want a Envelope[Bar]. What if it's any data type other than json-isomorphic, e.g. image or video? Is /videos/123.mp4 going to return a json object like {"data": , "status": "whatever"} Of course not! You already have an envelope, it's the HTTP protocol. Th…

We wrap the response body because it's important to give clients of an API endpoint, something that they will use to query/modify data, a clear indicator of the application response status. We do this in the response body because http status codes aren't good enough, and people tend to miss headers. It's hard to miss it when it's part of the body.

And no, we don't do that for static content for a simple reason: static content isn't served from our API servers.

Re: How to Design Better APIs

#192
post #170
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'm not saying you should do it this way, this is just how our startup (still very much in the "move fast and discover product fit" stage) does it. We have separate API models (pydantic and fastapi) and DB models (sqlalchemy). Basically everything not in the original db schema ends up nullable when we first add a field. The API model handles validation. Then if we absolutely do need a field non-null in the db, we run…

That's what salesforce does. In our app we're on version 47.0 of their API

https://test.salesforce.com/services/Soap/c/47.0

And in the latest version of the API docs they have details regarding old versions. Example:

https://developer.salesforce.com/docs/atlas.en-us.api.meta/a...

Type reference Properties Create, Filter, Group, Nillable, Sort Description The ID of the parent object record that relates to this action plan.

For API version 48 and later, supported parent objects are Account, AssetsAndLiabilities, BusinessMilestone, Campaign, Card, Case, Claim, Contact, Contract, Financial Account, Financial Goal, Financial Holding, InsurancePolicy, InsurancePolicyCoverage, Lead, Opportunity, PersonLifeEvent, ResidentialLoanApplication, and Visit as well as custom objects with activities enabled.

For API version 47 and later, supported parent objects are Account, BusinessMilestone, Campaign, Case, Claim, Contact, Contract, InsurancePolicy, InsurancePolicyCoverage, Lead, Opportunity, PersonLifeEvent, and Visit as well as custom objects with activities enabled.

For API version 46 and later, supported parent objects are Account, Campaign, Case, Contact, Contract, Lead, and Opportunity as well as custom objects with activities enabled.

For API version 45 and earlier: the only supported parent object is Account.

Re: How to Design Better APIs

#193
post #155

ISO 8601 is bad, use RFC 3339. A lot of implementation are actually based on an ISO draft which changed in final release. But most dev do not have access to the spec. For example, timezone can only be specified as offset in the standard, while implementations accept name. Globally avoid ISO for software, it is non free crap. Also, do not use those standard for dates with timezone in the future. Use wall time/date and…

My own experience is that (unix) timestamps are much less error-prone than textual representations like ISO 8601 and such. A field like `update_time_seconds` is clear and easy to convert into any representation. This is what the Google API Improvement Proposals recommends in most cases, though civil timestamps are also described. https://google.aip.dev/142 Of course, when preparing queries against the API, you may ne…

I agree, for timestamp, I often use ms or sec offsets. But I do not dare say it because I pass for an old fool.

Re: How to Design Better APIs

#194

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?

Even beyond PUT vs PATCH I found this statement to be rather naive:

"From my experience, there barely exist any use cases in practice where a full update on a resource would make sense"

Just in finance I can think of *dozens* of use cases around invoicing and purchasing *alone*. A lot of times thousands of resources may need just one field "corrected", but hundreds others "reset" to ensure the proper retriggering of routing, workflows, and allocations. That the resources need to exist as originals is incredibly important for these kinds of things.

Re: How to Design Better APIs

#195
post #175
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…

Agreed. But rather than reinvent, let’s just use JSON API standard? https://jsonapi.org/format/ (Scroll to the very bottom)

The article is about REST API design, not JSON APIs! It’s a whole different ballpark.

Re: How to Design Better APIs

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

Interesting! Do you find that returning an array of errors works in practice?

Most validation I’ve seen looks like:

    raise error if foo
    raise other_error if bar
This pattern turns into one exception per response, and some foresight in architecting exceptions would be needed

Re: How to Design Better APIs

#197

Something I wonder is how to design search/list endpoints where the query can be long (a list of IDs, ex: /users?ids=123e4567-e89b-12d3-a456-426614174000,123e4567-e89b-12d3-a456-426614174001,123e4567-e89b-12d3-a456-426614174002,...), so long that it can exceed the url max length (2048), after 50 UUIDs, you can quickly exceed that length, so GET is not ideal, so which method, SEARCH with a body? POST with a body?

If QUERY is too new, I was always a fan of base62 for URLs, but base64 and straight binary encoding could do well for compacting UUID lists, they are essentially just giant verbosely written integers.

Re: How to Design Better APIs

#198
post #8

Earlier quoted context omitted.

Dear PAM69, this is great advice if you want to end up with a slow-to-load, low-performing web application that your customers complain about and hate using. But at least it'll adhere to a specific notion of architectural "purity", right? /s Anytime clients need to make 15 async calls before the UI can be displayed, you're headed up the creek. Generally speaking, this is an anti-pattern. There are exceptions, but the…

I think this is an unnecessarily harsh and sarcastic tone to take here. The comment you're replying to set out specific reasons why they disagree with expanding/bundling sub-resources. It obviously depends on your use case - and in fact they say use GraphQL, which I heartily agree with - but the point is that you don't always know how the API is going to evolve over time, and keeping things unbundled tends to be a "n…

I agree.

One thing to add, is that there's nothing preventing you to invent a new noun for a particular rest resource that returns bundles of content. eg. /user/:id/dashboard - it makes it so this endpoint is not tied to eg. user/:id .. making that endpoint harder to change in the future, but also solves the issue mentioned by the rude comment above re: needing to perform a lot of separate rest calls.

Re: How to Design Better APIs

#199
post #55

Earlier quoted context omitted.

Sort of, but is it any better if the GraphQL layer still has to make 15 requests in order to serve a single useful response?

But those 15 requests are then all occurring over a local network (in the data center), not over the Internet. The true power with GraphQL is that it might not even make all 15 calls because it will entirely depend on what you are querying for. E.g. if you query for a User but not the Orders for that User, then the request to retrieve the orders is simply skipped by GraphQL.

Great point.

I have only used Apollo for GraphQL, and I found a few things about it offputting (e.g. I need a 3rd-party library to figure out what fields the client actually requested). What GraphQL server do you use? Or is Apollo + Express generally a good "default" option for basic setups?

Re: How to Design Better APIs

#200
> 5xx for internal errors (these should be avoided at all costs)

An anti pattern I’ve often seen has devs avoiding 5xx errors in bizarre ways. I would change the above to make to have monitoring in place to address 5xx errors. By all means, let your code throw a 500 if things go off the rails.

Post reply on HN