HACKER Q&A
📣 julianlam

In API design; minimal responses or kitchen sink responses?


I'm currently refactoring my app away from websockets to a more traditional RESTful API (especially for things that should've been RESTful in the first place), and I wanted to know peoples' thoughts on whether response bodies should return just what you need (e.g. a need-to-know response), or return components that are common across different responses.

For example, given a hypothetical API, `GET /widgets/:id` would return a generic set of properties for the widget... the id, location, parts, etc.

Whereas `POST /widgets` could return all of that, but in a scenario where it doesn't matter (that is, all the other values are null or defaults), then returning just `{ id }` would be sufficient.

Especially in the case of large response payloads, it may save some data from going over the wire, but we may be waltzing into premature optimization territory here.

If you use reusable components in OpenAPI, then it indirectly pushes you towards having your API return common schemas across different routes. So both `POST /widgets` and `GET /widgets/:id` would return the same kind of response (in terms of properties present, etc.)

I can also see the argument that for developer friendliness, it makes more sense to return the kitchen sink, so additional calls need not be made to retrieve additional information.

In the real world, Stripe's API always returns a common object that you can rely on... creating an invoice returns an "Invoice" object, listing invoices returns an array of "Invoice" objects, updating an invoice returns an "Invoice" object, etc.

I ask this because I can see in the existing code that a lot of the calls were fairly minimalist in nature. For example, deleting a widget wouldn't even _need_ a response body. A 200 would just mean I could remove the element from the DOM, but from a dev friendliness POV, it could be advantageous to return the output of `GET /widgets` when you call `DELETE /widgets/:id` (or maybe the output of `GET /widgets/:id` with the deleted flag set)


  👤 dexwiz Accepted Answer ✓
Like all things, the answer is it depends. Returning consistent API responses will usually be better for future API consumers. If you are deciding between sending back 1 field or 5 fields, it’s going to about the same since the overall request overhead will outweigh payload size. But if your widget has 500 fields, or deeply nested fields, it may be useful for the API to provide parameters that a consumer can use to specify which fields to return to avoid sending extra bytes.

The area I find dangerous for response sizes are load everything endpoints. Say it takes 5 API calls to build a page, you may have the great idea to create one Uber endpoint that returns the data for all 5 in a single call. These usually work initially but scale very poorly if your response body has any sort of list.

For delete it’s pretty common to not return much beyond the status code. If the object is successfully deleted, then it no longer has data, so what are you returning it for? If you need to store a snapshot before deletion, then send a GET first.