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…
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…
How to Design Better APIs
31–40 of 238 posts
Re: How to Design Better APIs
#32A few things I see rarely discussed that I often do: - Always use a response envelope - HTTP status is not the same as your application status. I always include a "status" field in the response envelope (OP recommends standardizing errors but I think standardize all of it) - Always have an unique error code for every error your API can return (they should also be URL safe ("some-thing-went-wrong"), basically an enum…
Are you able to elaborate on what is a response envelope? Edit: Nevermind, see [0]. It's the simple and intuitive concept of encasing the payload in an consistently structured object which includes metadata, e.g. {"Error": null, Data: ...} [0] https://stackoverflow.com/questions/9989135/when-in-my-rest-... Makes intuitive sense, as it's then easier to develop a nice, generic REST client.
export enum ErrorCode {
InvalidEntity = 1,
NotSupported = 2,
UnexpectedServerError = 3,
InvalidRequest = 4,
Validation = 5,
// ...
}
export enum ResponseStatus {
Success = "success",
Error = "error",
}
export class ResponseEnvelope {
public readonly status: ResponseStatus = ResponseStatus.Success;
public readonly data: T | Pruned | null = null;
public readonly error?: {
code: ErrorCode,
message: string,
details: object | string,
status: ResponseStatus,
};
constructor(opts?: Partial>) {
if (opts) {
if (opts.status) { this.status = opts.status; }
if (opts.data) { this.data = opts.data; }
if (opts.error) { this.error = opts.error; }
}
if (!this.data) { return; }
// Prune if the thing is prunable
this.data = prune(this.data);
}
}Hopefully this isn't too hard to grok, it's Typescript.
BTW, If you're cringing at the number scheme for the ErrorCode enum, don't worry I am too. This is why I prefer to use strings rather than numbers, and it basically just ends up being stuff like "invalid-entity", etc.
Re: How to Design Better APIs
#33Earlier quoted context omitted.
Quoted post unavailable.
I would rather you not assigning hate to the entirety of autistic developers. There are plenty of autistic developers who are fully capable of designing great APIs with awesome usability. Being autistic has nothing to do with how APIs are developed.
Re: How to Design Better APIs
#34Mostly common-sense things, but I can't wait for the community to stop trying to use PUT, PATCH, DELETE and the like. There's a reason that in 2022 web forms only support GET and POST (and implicitly, HEAD).
What is the reason?
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
Re: How to Design Better APIs
#35Earlier 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…
Well they said use GraphQL, which is a solid way to avoid REST's clumsiness once and for all.
Re: How to Design Better APIs
#36I’m gonna say it: Many rest apis are lazy and developer friendly, not consumer friendly. If you have related resources, let’s say, product and product options as two distinct endpoints: - /api/product - /api/options Then, and I want to be clear here, it is impossible for a client to perform an atomic operation on multiple distinct objects types. Let’s say the client needs to add a product with a single option or fail…
Re: How to Design Better APIs
#37Sure, there is gRPC, but it requires another API specification (the proto files).
There I said it. HTTP Verbs constrained REST APIS are the worst thing ever. I hate them.
They introduce un-necessary complexity, un-necessary granularity and they almost always stray away from the "REST principles". To hell with "Hypermedia" stuff.
I find it such a joy to program in server rendered pages. No cognitive overhead of thinking in "REST".
But, of course, all this is only where the client and server are developed by the same person / company.
For publishing data and creating API for third party use, we have no serious, better alternative to REST.
Re: How to Design Better APIs
#38Sometimes, 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…
Re: How to Design Better APIs
#39Some 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…
That's not a rest-y API. You want GET /orders?user=Id Orders can be searched on many dimensions, not inherent to users
But then again, when it comes to API's, domain modelling is the hard part and it is therefore the reason why you don't want to return nested results/objects.
Re: How to Design Better APIs
#40Earlier quoted context omitted.
Huh? There’s full browser support for all of those verbs. What is the argument for not supporting them?
The HTTP request APIs pass through any method name you write. The HTML forms only support GET and POST. Try it.
The recommendation is perfectly good for any API using HTTP as the substrate. The wisdom of using HTTP as a protocol substrate is questionable, but having made that decision the verbs it supplies work perfectly well.
Incidentally, the HTML living standard supports three form methods, not two: get, post, and dialog. Which rather reinforces the point that HTML != HTTP.