1

I have an endpoint like so:

GET /api/customer/primary

If a primary customer exists, I return something like

{
  name: "customerName"
}

But what if I send a GET and a primary customer doesn't exist?

Is it better to send a 200 OK with an empty JSON {}

Or is better to only send a 204 No Content?

T Percival
  • 8,526
  • 3
  • 43
  • 43
RonApple1996
  • 269
  • 3
  • 13
  • 3
    You probably should return 404 since entity cannot be found. – tsolakp Oct 24 '18 at 22:52
  • I don't want the client to think something wrong happened. In my case, it's perfectly ok if a primary customer doesn't exist. – RonApple1996 Oct 24 '18 at 22:54
  • 8
    404 does not mean that something wrong has happened. It just indicates that the requested resource does not exist. Otherwise how does client know that it got no resource vs resource exists but it has no representation. – tsolakp Oct 24 '18 at 22:56
  • 1
    This seems to be a matter of opinion. See https://stackoverflow.com/q/34312023/217324, there are arguments for both sides. – Nathan Hughes Oct 24 '18 at 23:06
  • 1
    @NathanHughes in that question the different situation is discussed namely when the list of entities is accessed and it is empty. – Roman-Stop RU aggression in UA Oct 24 '18 at 23:16
  • I tend to differentiate on the purpose of the API call. If you are searching for something that might not be there a 200 with no search results and potentially a short message is just fine. After all, the search was executed properly but no results were found. If you are doing some form of lookup with a specific ID and expecting a (specific) result which should be there I would go with the 404. but thats just my two cents. – ophychius Oct 25 '18 at 06:09
  • Fwiw, I agree with all the above comments. There's a difference between 'resource doesn't exist', and 'resource is a collection with 0 items in it'. – Evert Oct 26 '18 at 03:58

3 Answers3

2

404 is the appropriate status code for this. You're trying to represent a 'primary customer' as a resource, but in some cases this relationship doesn't exists. This situation is pretty clear, it should be a 404 for GET requests.

This is a perfectly acceptable way to communicate this. A 404 might signal a client that the resource doesn't exist yet, and perhaps that it can be created with PUT.

204 No Content has a specific meaning, and doesn't make that much sense for your case. 204 is not just meant to signal there's not going to be response body (Content-Length: 0 can do that), but it has a more specific application for hypermedia applications. Specifically, it signals that when a user performs an action that results in the 204, the view shouldn't refresh. This makes sense for for example an "Update" operation where a user can occasionally save their progress while working on a document. Contrast to 205 Reset Content, which signals that the 'view' should reset so (perhaps) a new document can be created from scratch.

Most applications don't go this far. Frankly, I haven't seen a single one. Given that, returning 200 with Content-Length: 0 or 204 No Content is an almost completely irrelevant discussion. The HTTP specification certainly doesn't forbid 200 OK with Content-Length: 0.

That was a bit of a tangent. To conclude, 404 signals this 'thing' doesn't exist, and that's appropriate here. There's no multiple interpretations. There's the people who wrote the specifications, those who read them well and on the other side of the discussion the people who are wrong.

Evert
  • 93,428
  • 18
  • 118
  • 189
0

But what if I send a GET and a primary customer doesn't exist?

Is it better to send a 200 OK with an empty JSON {}

Or is better to only send a 204 No Content?

If I'm interpreting your question correctly, you aren't really asking about status codes, but rather what kind of schema should you be using to manage the different cases in your API.

For cases like REST, where the two ends of the conversation are not necessarily controlled by the same organization and same release cycle, you may need to consider that one side of the conversation is using a more recent schema version than the other.

So how is that going to be possible? The best treatments I have seen focus on designing schema for extension - new fields are optional, and have documented semantics for how they should be understood if a field is absent.

From that perspective

{}

Doesn't look like a representation of a missing object - it looks like a representation of an object with default values for all of the optional fields.

It might be that what you want is something like Maybe or Option - where instead of promising to send back an object or not, you are promising to send back a collection of zero or one object. Collections I would normally expected to be represented in JSON as a array, rather than an object.

[]

Now, with that idea in pocket, I think it's reasonable to decide that you are returning a representation of a Maybe, where the representation of None is zero bytes long, and the representation of Some(object) is the JSON representation of the object.

So in that design 204 when returning None makes a lot of sense, and you can promise that if a successful response returns a body, that there is really something there.

There's a trade off here - the list form allows consumers to always parse the data, but they have to do that even when a None is sent. On the other hand, using the empty representation for None saves a parse, but requires that the consumer be paying attention to the content length.

So, looking back to your two proposals, I would expect that using 204 is going to be the more successful long term approach.

Another possibility would be to return the null primitive type when you want to express that there is no object available. This would go with a 200 response, because the content length would be four bytes long.

null
Community
  • 1
  • 1
VoiceOfUnreason
  • 52,766
  • 5
  • 49
  • 91
-1

HTTP 404 status's text ("Not Found") is the closest to the situation, But:

The first digit of the Status-Code defines the class of response. The last two digits do not have any categorization role. There are 5 values for the first digit:

  • 1xx: Informational - Request received, continuing process
  • 2xx: Success - The action was successfully received, understood, and accepted
  • 3xx: Redirection - Further action must be taken in order to complete the request
  • 4xx: Client Error - The request contains bad syntax or cannot be fulfilled
  • 5xx: Server Error - The server failed to fulfill an apparently valid request

(reference)

  • In practice, 4xx recognized as an error and it is likely some alerts will rise from network / security / logging infrastructure
  • 204 semantic indicate that the server has successfully fulfilled a request and there is no additional content to send - not exactly what happening.
  • A common use case is to return 204 as a result of a PUT request, updating the resource.

Therefore I would recommend using either:

HTTP 200 with an empty object / array

like you suggested.

HTTP 200 returning a null object, e.g.:

"none" (valid JSON)

or

  {
    "name": "NO_PRIMARY_CUSTOMER"
  }

(implementation of such a null object depends on your specific system behavior with the returned data)

Custom HTTP 2xx code with an empty result

Less common, but still workable alternative is to return a custom HTTP code within the 2xx range (e.g. HTTP 230) with an empty result.

This option should be used with extra caution or even avoided if the API is exposed to a wide audience that may use unknown tools to access / monitor the API.

Community
  • 1
  • 1
Lior Bar-On
  • 10,784
  • 5
  • 34
  • 46