I'd say that either a 200 or a 404 response code can be valid, depending on how you look at the situation.
The thing is that HTTP response codes are defined in the context of an server, which can deliver various resources based on their URL. In this context, the meanings of 200 OK
and 404 Not Found
are perfectly unambiguous: the former says "here's the resource you asked for", while the latter says "sorry, I don't have any resource like that".
However, in your situation, you have an additional application layer between the HTTP server and the actual resources (trees) that are being requested. The application occupies a sort of an intermediate space that is not well addressed in the HTTP spec.
From the webserver's viewpoint, the application looks kind of like a resource: it's typically a file on the server, identified by (a part of) the URL, just like other resources (e.g. static files) the server might serve. On the other hand, it's a weird kind of resource, since it consists of executable code that dynamically determines the content, and indeed potentially even the status code, of the response, making it behave in some ways more like a mini-server.
In particular, in your example case, the webserver can locate the application just fine, but the application then fails to locate the subresource (tree) that has been requested. Now, if you consider the application to be just an extension of the server, and the subitem (tree) to be the actual resource, then a 404 response is appropriate: the server has merely delegated the task of finding the actual resource to the application, which it turn has failed to do so.
On the other hand, if your viewpoint is that the application is the resource being requested, then obviously the webserver should return a 200 response; after all, the application was found and executed correctly. Obviously, in this case, the application should actually return a valid response body in the expected format, indicating (using whatever higher-level protocol that format encodes) that no actual data matching the query was found.
Both of these viewpoints can make sense. In most cases, at least for applications intended to be directly accessed over HTTP with an ordinary web browser, I would favor the former view: the user generally doesn't care about internal details like the difference between the server and the application, they just care about whether the data they wanted is there or not.
However, in the specific case of an application designed to communicate with other computer programs using a custom high-level API protocol, using HTTP only as a low-level transport layer, there's an argument to be made in favor of the latter view: for clients interfacing with such an application, all they really care about, at the HTTP level, is whether they managed to successfully contact the application or not. Everything else is, in such cases, often more naturally communicated using the higher-level protocol.
In any case, regardless of which of the above views you prefer, there are a few details you should keep in mind. One is that, in many cases, there may be a meaningful distinction between an (essentially) empty resource and a nonexistent one.
On the HTTP level, an empty resource would simply be indicated by a 200 response code and an empty response body, while a nonexistent resource would be indicated by a 404 response and a resource body explaining the absence of the resource. In a higher-level API protocol, one would typically indicate a nonexistent resource by an error response, containing a suitable protocol-specific error code/message, while an empty response would simply be a normal response structure with no data items.
(Note that a resource need not be literally zero bytes long to be "empty" in the sense I mean above. For example, a search result with no matching items would count as empty in the broad sense, as would an SQL query result with no rows or an XML document containing no actual data.)
Also, of course, if the application really does believe that the requested subresource should be there, but can't find it, then a third possible response code exists: 500 Internal Server Error
. Such a response makes sense if the existence of the resource is an assumed precondition for the application, such that its absence necessarily indicates an internal malfunction.
Finally, you should always keep in mind Postel's law:
"Be conservative in what you send, and liberal in what you receive."
Whether the server should respond in a particular situation with a 200 or a 404 response, that doesn't excuse you as the client implementor from handling either response appropriately and in the manner that maximizes robust interoperability. Of course, what "appropriate" handling means in different situations can be argued, but it certainly shouldn't normally include crashing or otherwise "falling apart".
/GoalTree/GetById?versionId=CompletelyInvalidID
return? Not success, as the resource named/GoalTree/GetById?versionId=CompletelyInvalidID
was literally not found.