TL;DR - API developers should make it so consumers have the necessary information and tools to know what's happening. If you're just returning a 404 with no other info, you have a bad API.
There's basic error handling/reporting that seems to transcend technology and architecture, and a big part of that is that errors should have unique error codes. In the context of a web API, both "route not found" and "resource does not exist" should return a 404, but each should have a unique `code` in the body:
{"code": 0, "err": "route not found"}
{"code": 1, "err", "user not found"}
For HTTP, the status code is often for general application development, and the error code is for debugging, though there can be overlap and it's completely fine if a client wants to implement custom logic based on `body.code`.
A validation error should look like:
{"code": 2, err: "invalid", "data": {
"username": [{"code": 100, "err": "required"}],
"password": [{"code": 101, "err": "must be at least 6 characters", "data": {"min": 6}}]
}}
The `code` always indicates what other data, if any, exists. Above, a code of 2 means there'll be a `data` field of errors. A validation error of `101` means there'll be a `min` field in `data`. `err` is an user-safe (developer friendly) description of the message which can always be regenerated from `code` + `data`.
For errors that aren't known ahead of a time (e.g. a server error), that should also have a distinct code, say 500, and the "data" field should contain an `error_id` which can be used to look up the error.