This is a question I use when interviewing devs for writing REST API.
The answer is either way, and it depends on the tooling you are using. If you are relying on a client library that doesn't handle HTTP errors in the way you want, then you return a 200 - OK {"error": "bad request"}. If the client library does what you want, then returning a limited selection of 4xx errors is very useful for letting the client know what happened quickly and easily.
Personally, I default to using the HTTP error codes. But I know that some really large companies don't agree, and always return a 200 OK to any valid request.
4xx is when the client did something wrong:
(1) asked for a resource which does not exist - 404
(2) does not have permission to access the resource - 403
(3) is not authenticated - 401
(4) not correct / enough parameters provided - bad request 400.
(5) doing a post request where a put request was supposed to be made - 405
5xx is when the server is doing something wrong. Most common is whenever something unexpected has happened - 500 Internal Server ErrorThis isn't 'How do you use' but 'Do you use', isn't it? If you return 200 with `{"error": "not found"}`, you are not using status codes.
the layer in your stack determines the error...if your returning json, the HTTP worked fine...if you cannot return json, the HTTP might be at fault
this policy is essential when bug hunting: if you get a 404, you should be certain its an http issue, not a db one
When writing idiomatic REST APIs, It's important to send the correct status code where you can. If you search for a record and there is none, return a 404, try to never return a 200 status code on an error. Sometimes it's unavoidable to send a not perfect status code, like in the instance of SSE, but in that case, assuming they got past the basic error checking, send a 207 to indicate there are multiple status codes. I believe you should ALWAYS send the correct status code, it makes your API easier to use, internally or externally, someone doesnt have to skim through pages of documentation to find that when a record is not found it will return {"error": "not found"} instead of a 404.