HTTP response retrieving a resource when only partial data is available - rest

I apologise if there is an answer for this already. I found related questions (e.g. HTTP status code for a partial successful request) but not exactly the same.
I'm building an API that returns data that is aggregated from multiple sources. Sometimes, some critical part of the data is unavailable and the client has to be made aware and error data is included in the response.
Other than the severity of the missing field(s), the rest of the resource is valid and useful and could be regarded as a partial update (e.g. if you only had permissions to see part of a resource).
So far, the options are
return 200, consider it a partial resource, handle the error data fields in the application as you would with any other data
return 207 to emphasise it's not fully successfully, but 207 is not strictly HTTP.
return 500 and handle the successfully returned data in the application as you would on a 200
I'm partial to option 1 but I'm not fully convinced. Is there a clear way of handling this? Perhaps defining a specific content-type?

You are missing the point here because a 500 is indicative of a failure of the system or the chain of communication, and since data is returned then it must be assumed that the resource exists and is found. What the OP has indicated is a partial result, implying composite data pertaining to the resource. This is necessarilly outside of the scope of http, which has done its job via a successful 200, unless you have elected a contract under which partial data is erroneous and thus a 40x.

Related

version number vs ETag for optimistic concurrency

I'm implementing my first Web API with JSON responses and got confused handling concurrency control for optimistic locking. Right now I develop the server with ASP.NET Core 6 and the client is developed with Angular. The data store is a SQL database. In the future we want to open the API to third parties.
I see two options for handling optimistic locking:
A) ETag in header
B) version number in the body
With option A) I see those two problems:
Since ETag is a header "Precondition Fails 412" needs to be send for failures. The error needs to be specified in the body, so the client can understand that it is a concurrency error.
For concurrency errors I would expect to send HTTP error code 409:
"...Conflicts are most likely to occur in response to a PUT request. For example, if versioning were being used and the entity being PUT included changes to a resource which conflict with those made by an earlier (third-party) request, the server might use the 409 response to indicate that it can't complete the request. In this case, the response entity would likely contain a list of the differences between the two versions in a format defined by the response Content-Type."
2) When a collection/list of representations (e.g. all due orders) is returned from the server there is no possibility to send multiple ETags. The ETag in the header applies to the whole collection/list, but each single resource in the list can be individually modified by different users and needs to have a version number for concurrency detection. I don't see any other option than to send an individual version number/ETag as a property with each representation in the body.
I find it confusing when collections are treated differently than single resources. Since the client needs to store the ETags for each single resource it is natural to include the ETag as a property in its object model anyway.
Option B) avoids the issues of A): I'm free to send a 409 on failure and single resources and collections of resources are treated the same way. The problem is the DELETE verb.
There is a discussion about using a body in a DELETE request at [1]: Is an entity body allowed for an HTTP DELETE request?
The current version of the RFC states:
"A client SHOULD NOT generate a body in a DELETE request. A payload received in a DELETE request has no defined semantics, cannot alter the meaning or target of the request, and might lead some implementations to reject the request."
What does "has no defined semantics" mean? What are the implications? I'm aware that some implementations are ignoring the body or have not implemented the option to send a body with DELETE. I still wonder if I could send a version number in the body. Generally, I don't understand the reasons a body should not be generated for DELETE? Why is it evil?
I understand that If-Match with ETag is the recommended solution to handle concurrency, but it can't handle basic collections. Why is there a 409 error code for concurrency issues, when the recommended solution ETag can't use it to be compliant? This is really confusing.
Keeping the version number in the body for concurrency detection would be consistent, but it does not work for DELETE.
Edited:
The above text was edited for clarification reflecting Everts comments.
I see the following options (even GET can be conditional I'm here only concerned about concurrency update issues):
A) Client requests use If-Match header. Server responses put ETag in header and in body
The ETag in the body gives the client a consistent way of handling single resources and collections. In case the collection needs to have a version on its own the ETag in the header is available and can also be used for conditional GET.
I have to give up sending 409 for concurrency errors.
B) Version number is sent in the body except for DELETE.
In the case of DELETE the version number must be either sent with a query parameter or with an If-Match header. It is not pleasant to have this exception, but a more clear 409 can be sent and single resources and collections are handled consistently.
I'm still unsure about what implementation to choose. Are there any clear criteria that can help with the decision? How has this problem been solved by others?
Do I misunderstand the usage of 409?
Update:
This German article https://www.seoagentur.de/seo-handbuch/lexikon/s/statuscode-412-precondition-failed/ explains the usage of 409 vs 412:
412 should only be used if the precondition (e.g. If-Match) caused the failure, while 409 should be used if the entity would cause a conflict. If a database with version id is used this id can be passed to the ETag and from the If-Match back to the version id. However, it is not forbidden to do it in the body of the entity itself. It just requires that the concept and how it works be explained, whereas the ETag solution just lets you refer to the HTTP specification. (comment: it still leaves the no body in DELETE problem)
The ETag with collections problem has more nuances:
a) If the returned collection is just data for a list view it normally doesn't hold all data of the displayed objects. If one item in the list is edited the client needs to first GET the full entity from a single resource URI and will get the required ETag with that request. It also provides are current version of the resource at the time of editing and not when the list was requested.
b) If the returned collection holds the full entity data and performance issues are relevant or many items independently need to be changed at once, than the ETags of each item can be passed to the client in the body.
Update 2:
The "Zalando RESTfull API and Event Guidelines" compare various options for optimisitc locking at [https://opensource.zalando.com/restful-api-guidelines/#optimistic-locking][2]
They favour sending the ETag in the body for server responses.
I currently think that this is the best option. The client than has the freedom to use that ETag or send a new Get on the single resource.
To me "Conflict 409" is the right response for a concurrency error, but the RFC states that a "Precondition Fails 412" needs to be send, which is not clear enough. Of course an error description in the body can clarify the cause of the error, but I would rather send 409.
Use the HTTP status codes as they are defined, not what you think they should mean based on the name.
When a collection (e.g. all due orders) is returned from the server there is no possibility to send multiple ETags. Each single resource can be individually modified. Therefore the only option is to send the ETag in the body as a property of each representation in the JSON response. It is confusing that collections are treated differently than single resources. Also the client needs to include a property for the ETag in its object model in any case.
HTTP doesn't really have a concept of collections, but you can give the collection itself its own ETag as well.
I don't understand all the implications of the specific wording. What does "has no defined semantics" mean? What is the reasons a body should not be generated?
A delete request should only delete the resource located at the URI. If it's successful, we can assume that the URI that was used in the DELETE request will return a 404 or 410 after the request was successful.
If you want to conditionally parameterize deletions, delete multiple resources at once or delete something other than the resource specified in the URI, the DELETE request is simply not appropriate for that use-case.
If you want to use ETags, just use an If-Match header.

REST Check if resource exists, how to handle on server side?

how to handle resource checking on server side?
For example, my api looks like:
/books/{id}
After googling i found, that i should use HEAD method to check, if resource exists.
https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
I know, that i can use GET endpoint and use HEAD method to fetch information about resource and server does not return body in this case.
But what should i do on server side?
I have two options.
One endpoint marked as GET. I this endpoint i can use GET method to fetch data and HEAD to check if resource is available.
Two endpoints. One marked as GET, second as HEAD.
Why i'm considering second solution?
Let's assume, that GET request fetch some data from database and process them in some way which takes some time, eg. 10 ms
But what i actually need is only to check if data exists in database. So i can run query like
select count(*) from BOOK where id = :id
and immediately return status 200 if result of query is equal to 1. In this case i don't need to process data so i get a faster response time.
But... resource in REST is a object which is transmitted via HTTP, so maybe i should do processing data but not return them when i use HEAD method?
Thanks in advance for your answer!
You could simply delegate the HEAD handler to the existing GET handler and return the status code and headers only (ignoring the response payload).
That's what some frameworks such as Spring MVC and JAX-RS do.
See the following quote from the Spring MVC documentation:
#GetMapping — and also #RequestMapping(method=HttpMethod.GET), are implicitly mapped to and also support HTTP HEAD. An HTTP HEAD request is processed as if it were HTTP GET except but instead of writing the body, the number of bytes are counted and the "
Content-Length header set.
[...]
#RequestMapping method can be explicitly mapped to HTTP HEAD and HTTP OPTIONS, but that is not necessary in the common case.
And see the following quote from the JAX-RS documentation:
HEAD and OPTIONS requests receive additional automated support. On receipt of a HEAD request an implementation MUST either:
Call a method annotated with a request method designator for HEAD or, if none present,
Call a method annotated with a request method designator for GET and discard any returned entity.
Note that option 2 may result in reduced performance where entity creation is significant.
Note: Don't use the old RFC 2616 as reference anymore. It was obsoleted by a new set of RFCs: 7230-7235. For the semantics of the HTTP protocol, refer to the RFC 7231.
Endpoint should be the same and server side script should make decision what to do based on method. If method is HEAD, then just return suitable HTTP code:
204 if content exists but server don't return it
404 if not exists
4xx or 5xx on other error
If method is GET, then process request and return content with HTTP code:
200 if content exists and server return it
404 if not exists
4xx or 5xx on other error
The important thing is that URL should be the same, just method should be different. If URL will be different then we talking about different resources in REST context.
Your reference for HTTP methods is out of date; you should be referencing RFC 7231, section 4.3.2
The HEAD method is identical to GET except that the server MUST NOT send a message body in the response (i.e., the response terminates at the end of the header section).
This method can be used for obtaining metadata about the selected representation without transferring the representation data and is often used for testing hypertext links for validity, accessibility, and recent modification.
You asked:
resource in REST is a object which is transmitted via HTTP, so maybe i should do processing data but not return them when i use HEAD method?
That's right - the primary difference between GET and HEAD is whether the server returns a message-body as part of the response.
But what i actually need is only to check if data exists in database.
My suggestion would be to use a new resource for that. "Resources" are about making your database look like a web site. It's perfectly normal in REST to have many URI that map to a queries that use the same predicate.
Jim Webber put it this way:
The web is not your domain, it's a document management system. All the HTTP verbs apply to the document management domain. URIs do NOT map onto domain objects - that violates encapsulation. Work (ex: issuing commands to the domain model) is a side effect of managing resources. In other words, the resources are part of the anti-corruption layer. You should expect to have many many more resources in your integration domain than you do business objects in your business domain.

what is the best Http code to identify idempotent operation conflict

i develop res service at which it take unique id parameter each call, but when the same id used more than once it should retrieve the same response was retrieved the first time and status code specify error, i am looking for the best status code for that , some post use "409 Conflict" and some "406 Not Acceptable", which to use ?
409 is better, because 406 is mostly used to represent header not acceptable.
406 Not Acceptable The requested resource is capable of generating
only content not acceptable according to the Accept headers sent in
the request.
409 (Conflict) means your request is duplicated.
409 Conflict Indicates that the request could not be processed because
of conflict in the request, such as an edit conflict between multiple
simultaneous updates.
I would like to put a different opinion on the table.
"Why should we return 409 always and bother client to handle these scenarios? Why should client be bothered about if item was created as part of current request or one of past tries?"
I feel for a simple scenarios like "POST on collection to create a resource instance" client could be simplified if server returns 201 even in the case of idempotent response.
However, we should also make sure that this simplification does not create confusion in some scenarios like:
Resource was created with initial version V1 by POST request from a client. This resource then get updated and moves to version V2. Now for some reason the initial client retries POST request with the same Idempotency token.
I believe the later one should be returned as 409, since this is a conflict.
POST is expected to create an initial version of the resource with the data present in request. Since this is duplicate request, we would rather fetch existing resource instance and return to client. That resource state may not have all fields as specified in the create request, and hence conflicting.

Cannot Delete Last Contact - What Http Status Code?

I'm currently building a Web API and have a specific scenario that I cannot determine which HTTP Status Code would be most appropriate to return.
The Scenario
I have a "client" resource which owns a collection of contact resources.
The invariant is that a client must always have at least one contact. Therefore, if a request is made to delete a contact and this contact is the last remaining contact for the given client, I need to return an appropriate HTTP response indicating that the request cannot be fulfilled as you "Cannot Delete the last contact".
My feeling is this should fall under the category of "4xx Client Error's"
I've considered the following Status Codes:
400 Bad Request - I've ruled this out as it's specifically regarding malformed request's in which the server is unable to understand.
405 Method Not Allowed - at first this seems suitable, but I think 405 indicates that this method should never be allowed, however the above scenario is only transient. Thoughts?
409 Conflict - I've been leaning towards this, however the common example given for this code is generally a concurrency exception/edit conflict.
Does anyone have any guidance as to how I should respond in this scenario?
The key is to look at the expectations on the client and caches when a particular status code is used.
Here's some chunks of RFC2616 that are useful to look at:
10.4.1. 400 Bad Request
The request could not be understood by the server due to malformed syntax. The client SHOULD NOT repeat the request without modifications.
This indicates that the request itself is completely wrong - either syntactically or by the protocol. Your specific case is really an application protocol error so this may indeed be appropriate.
10.4.6. 405 Method Not Allowed
The method specified in the Request-Line is not allowed for the resource identified by the Request-URI. The response MUST include an Allow header containing a list of valid methods for the requested resource.
This is a transient status code. If the DELETE refers specifically to the contact resources itself (e.g., DELETE /contacts/D9DF5176-EEE4-4C70-8DA7-BA57B82027A8) then this is probably the most appropriate status code. However, if the DELETE is on a different resource or a resource with a query (e.g., DELETE /contacts?index=12), then I would not return a 405. Then again, I usually steer clear of using DELETE with anything resembling a query.
10.4.10. 409 Conflict
The request could not be completed due to a conflict with the current state of the resource. This code is only allowed in situations where it is expected that the user might be able to resolve the conflict and resubmit the request. The response body SHOULD include enough information for the user to recognize the source of the conflict. Ideally, the response entity would include enough information for the user or user agent to fix the problem; however, that might not be possible and is not required.
This seems like the most appropriate status at first look. I would probably prefer a 400 in your case. A 409 would clearly indicate that there is a conflict with the resource but there really isn't anything that the requestor can do that could change the outcome short of completely altering the resource (i.e., add a contact first). Most of the 409 responses were optimistic concurrency failures such as trying to modify a resource that was modified since it was retrieved. For example, look at the concurrency failures returned by AtomServer built over Apache Adbera.
So with all of that. I would probably use something like 400 Cannot Delete Last Contact as the response line. Remember that you are allowed to change the phrase associated with the status code. This is a really good time to do such a thing.

HTTP response code for POST when resource already exists

I'm building a server that allows clients to store objects. Those objects are fully constructed at client side, complete with object IDs that are permanent for the whole lifetime of the object.
I have defined the API so that clients can create or modify objects using PUT:
PUT /objects/{id} HTTP/1.1
...
{json representation of the object}
The {id} is the object ID, so it is part of the Request-URI.
Now, I'm also considering allowing clients to create the object using POST:
POST /objects/ HTTP/1.1
...
{json representation of the object, including ID}
Since POST is meant as "append" operation, I'm not sure what to do in case the object is already there. Should I treat the request as modification request or should I return some error code (which)?
My feeling is 409 Conflict is the most appropriate, however, seldom seen in the wild of course:
The request could not be completed due to a conflict with the current state of the resource. This code is only allowed in situations where it is expected that the user might be able to resolve the conflict and resubmit the request. The response body SHOULD include enough information for the user to recognize the source of the conflict. Ideally, the response entity would include enough information for the user or user agent to fix the problem; however, that might not be possible and is not required.
Conflicts are most likely to occur in response to a PUT request. For example, if versioning were being used and the entity being PUT included changes to a resource which conflict with those made by an earlier (third-party) request, the server might use the 409 response to indicate that it can't complete the request. In this case, the response entity would likely contain a list of the differences between the two versions in a format defined by the response Content-Type.
According to RFC 7231, a 303 See Other MAY be used If the result of processing a POST would be equivalent to a
representation of an existing resource.
It's all about context, and also who is responsible for handling duplicates of requests (server or client or both)
If server just point the duplicate, look at 4xx:
400 Bad Request - when the server will not process a request because it's obvious client fault
409 Conflict - if the server will not process a request, but the reason for that is not the client's fault
...
For implicit handling of duplicates, look at 2XX:
200 OK
201 Created
...
if the server is expected to return something, look at 3XX:
302 Found
303 See Other
...
when the server is able to point the existing resource, it implies a redirection.
If the above is not enough, it's always a good practice to prepare some error message in the body of the response.
Personally I go with the WebDAV extension 422 Unprocessable Entity.
According to RFC 4918
The 422 Unprocessable Entity status code means the server understands the content type of the request entity (hence a 415 Unsupported Media Type status code is inappropriate), and the syntax of the request entity is correct (thus a 400 Bad Request status code is inappropriate) but was unable to process the contained instructions.
Late to the game maybe but I stumbled upon this semantics issue while trying to make a REST API.
To expand a little on Wrikken's answer, I think you could use either 409 Conflict or 403 Forbidden depending on the situation - in short, use a 403 error when the user can do absolutely nothing to resolve the conflict and complete the request (e.g. they can't send a DELETE request to explicitly remove the resource), or use 409 if something could possibly be done.
10.4.4 403 Forbidden
The server understood the request, but is refusing to fulfill it.
Authorization will not help and the request SHOULD NOT be repeated. If
the request method was not HEAD and the server wishes to make public
why the request has not been fulfilled, it SHOULD describe the reason
for the refusal in the entity. If the server does not wish to make
this information available to the client, the status code 404 (Not
Found) can be used instead.
Nowadays, someone says "403" and a permissions or authentication issue comes to mind, but the spec says that it's basically the server telling the client that it's not going to do it, don't ask it again, and here's why the client shouldn't.
As for PUT vs. POST... POST should be used to create a new instance of a resource when the user has no means to or shouldn't create an identifier for the resource. PUT is used when the resource's identity is known.
9.6 PUT
...
The fundamental difference between the POST and PUT requests is
reflected in the different meaning of the Request-URI. The URI in a
POST request identifies the resource that will handle the enclosed
entity. That resource might be a data-accepting process, a gateway to
some other protocol, or a separate entity that accepts annotations. In
contrast, the URI in a PUT request identifies the entity enclosed with
the request -- the user agent knows what URI is intended and the
server MUST NOT attempt to apply the request to some other resource.
If the server desires that the request be applied to a different URI,
it MUST send a 301 (Moved Permanently) response; the user agent MAY
then make its own decision regarding whether or not to redirect the
request.
I would go with 422 Unprocessable Entity, which is used when a request is invalid but the issue is not in syntax or authentication.
As an argument against other answers, to use any non-4xx error code would imply it's not a client error, and it obviously is. To use a non-4xx error code to represent a client error just makes no sense at all.
It seems that 409 Conflict is the most common answer here, but, according to the spec, that implies that the resource already exists and the new data you are applying to it is incompatible with its current state. If you are sending a POST request, with, for example, a username that is already taken, it's not actually conflicting with the target resource, as the target resource (the resource you're trying to create) has not yet been posted. It's an error specifically for version control, when there is a conflict between the version of the resource stored and the version of the resource requested. It's very useful for that purpose, for example when the client has cached an old version of the resource and sends a request based on that incorrect version which would no longer be conditionally valid. "In this case, the response representation would likely contain information useful for merging the differences based on the revision history." The request to create another user with that username is just unprocessable, having nothing to do with any version conflict.
For the record, 422 is also the status code GitHub uses when you try to create a repository by a name already in use.
After having read this and several other, years-long, discussions on status code usage, the main conclusion I came to is that the specifications have to be read carefully, focusing on the terms being used, their definition, relationship, and the surrounding context.
What often happens instead, as can be seen from different answers, is that parts of the specifications are ripped of their context and interpreted in isolation, based on feelings and assumptions.
This is going to be a pretty long answer, the short summary of which is that HTTP 409 is the most appropriate status code to report the failure of an "add new resource" operation, in case a resource with the same identifier already exists. What follows is the explanation why, based solely on what's stated in the authoritative source - RFC 7231.
So why is 409 Conflict the most appropriate status code in a situation described in the OP's question?
RFC 7231 describes 409 Conflict status code as follows:
The 409 (Conflict) status code indicates that the request could not be completed due to a conflict with the current state of the target resource.
The key components here are the target resource and its state.
Target resource
The resource is defined by the RFC 7231 as follows:
The target of an HTTP request is called a "resource". HTTP does not limit the nature of a resource; it merely defines an interface that might be used to interact with resources. Each resource is identified by a Uniform Resource Identifier (URI), as described in Section 2.7 of [RFC7230].
So, when using a HTTP interface, we always operate on the resources identified by URIs, by applying HTTP methods to them.
When our intention is to add a new resource, based on the OP's examples, we can:
use PUT with the resource /objects/{id};
use POST with the resource /objects.
/objects/{id} is out of interest, because there can be no conflict when using a PUT method:
The PUT method requests that the state of the target resource be created or replaced with the state defined by the representation enclosed in the request message payload.
If the resource with the same identifier already exists, it will be replaced by PUT.
So we'll focus on the /objects resource and POST.
RFC 7231 says about the POST:
The POST method requests that the target resource process the representation enclosed in the request according to the resource's own specific semantics. For example, POST is used for the following functions (among others): ... 3) Creating a new resource that has yet to be identified by the origin server; and 4) Appending data to a resource's existing representation(s).
Contrary to how the OP understands POST method:
Since POST is meant as "append" operation...
Appending data to a resource's existing representation is just one of the possible POST "functions". Moreover, what the OP actually does in the provided examples, is not directly appending data to the /objects representation, but creating a new independent resource /objects/{id}, which then becomes part of the /objects representation. But that's not important.
What's important is the notion of the resource representation, and it brings us to...
Resource state
RFC 7231 explains:
Considering that a resource could be anything, and that the uniform interface provided by HTTP is similar to a window through which one can observe and act upon such a thing only through the communication of messages to some independent actor on the other side, an abstraction is needed to represent ("take the place of") the current or desired state of that thing in our communications. That abstraction is called a representation [REST].
For the purposes of HTTP, a "representation" is information that is intended to reflect a past, current, or desired state of a given resource, in a format that can be readily communicated via the protocol, and that consists of a set of representation metadata and a potentially unbounded stream of representation data.
That's not all, the specification continues to describe representation parts - metadata and data, but we can summarize that a resource representation, that consists of metadata (headers) and data (payload), reflects the state of the resource.
Now we have both parts needed to understand the usage of the 409 Conflict status code.
409 Conflict
Let's reiterate:
The 409 (Conflict) status code indicates that the request could not be completed due to a conflict with the current state of the target resource.
So how does it fit?
We POST to /objects => our target resource is /objects.
OP does not describe the /objects resource, but the example looks like a common scenario where /objects is a resource collection, containing all individual "object" resources. That is, the state of the /objects resource includes the knowledge about all existing /object/{id} resources.
When the /objects resource processes a POST request it has to a) create a new /object/{id} resource from the data passed in the request payload; b) modify its own state by adding the data about the newly created resource.
When a resource to be created has a duplicate identifier, that is a resource with the same /object/{id} URI already exists, the /objects resource will fail to process the POST request, because its state already includes the duplicate /object/{id} URI in it.
This is exactly the conflict with the current state of the target resource, mentioned in the 409 Conflict status code description.
In your case you can use 409 Conflict
And if you want to check another HTTPs status codes from below list
1×× Informational
100 Continue
101 Switching Protocols
102 Processing
2×× Success
200 OK
201 Created
202 Accepted
203 Non-authoritative Information
204 No Content
205 Reset Content
206 Partial Content
207 Multi-Status
208 Already Reported
226 IM Used
3×× Redirection
300 Multiple Choices
301 Moved Permanently
302 Found
303 See Other
304 Not Modified
305 Use Proxy
307 Temporary Redirect
308 Permanent Redirect
4×× Client Error
400 Bad Request
401 Unauthorized
402 Payment Required
403 Forbidden
404 Not Found
405 Method Not Allowed
406 Not Acceptable
407 Proxy Authentication Required
408 Request Timeout
409 Conflict
410 Gone
411 Length Required
412 Precondition Failed
413 Payload Too Large
414 Request-URI Too Long
415 Unsupported Media Type
416 Requested Range Not Satisfiable
417 Expectation Failed
418 I’m a teapot
421 Misdirected Request
422 Unprocessable Entity
423 Locked
424 Failed Dependency
426 Upgrade Required
428 Precondition Required
429 Too Many Requests
431 Request Header Fields Too Large
444 Connection Closed Without Response
451 Unavailable For Legal Reasons
499 Client Closed Request
5×× Server Error
500 Internal Server Error
501 Not Implemented
502 Bad Gateway
503 Service Unavailable
504 Gateway Timeout
505 HTTP Version Not Supported
506 Variant Also Negotiates
507 Insufficient Storage
508 Loop Detected
510 Not Extended
511 Network Authentication Required
599 Network Connect Timeout Error
I don't think you should do this.
The POST is, as you know, to modify the collection and it's used to CREATE a new item. So, if you send the id (I think it's not a good idea), you should modify the collection, i.e., modify the item, but it's confusing.
Use it to add an item, without id. It's the best practice.
If you want to capture an UNIQUE constraint (not the id) you can response 409, as you can do in PUT requests. But not the ID.
"302 Found" sounds logical for me. And the RFC 2616 says that it CAN be answered for other requests than GET and HEAD (and this surely includes POST)
But it still keeps the visitor going to this URL to get this "Found" resource, by the RFC. To make it to go directly to the real "Found" URL one should be using "303 See Other", which makes sense, but forces another call to GET its following URL. On the good side, this GET is cacheable.
I think that I would use "303 See Other". I dont know if I can respond with the "thing" found in the body, but I would like to do so to save one roundtrip to the server.
UPDATE: After re-reading the RFC, I still think that an inexistent "4XX+303 Found" code should be the correct. However, the "409 Conflict" is the best existing answer code (as pointed by #Wrikken), maybe including a Location header pointing to the existing resource.
I think for REST, you just have to make a decision on the behavior for that particular system in which case, I think the "right" answer would be one of a couple answers given here. If you want the request to stop and behave as if the client made a mistake that it needs to fix before continuing, then use 409. If the conflict really isn't that important and want to keep the request going, then respond by redirecting the client to the entity that was found. I think proper REST APIs should be redirecting (or at least providing the location header) to the GET endpoint for that resource following a POST anyway, so this behavior would give a consistent experience.
EDIT:
It's also worth noting that you should consider a PUT since you're providing the ID. Then the behavior is simple: "I don't care what's there right now, put this thing there." Meaning, if nothing is there, it'll be created; if something is there it'll be replaced. I think a POST is more appropriate when the server manages that ID. Separating the two concepts basically tells you how to deal with it (i.e. PUT is idempotent so it should always work so long as the payload validates, POST always creates, so if there is a collision of IDs, then a 409 would describe that conflict).
Another potential treatment is using PATCH after all. A PATCH is defined as something that changes the internal state and is not restricted to appending.
PATCH would solve the problem by allowing you to update already existing items. See: RFC 5789: PATCH
What about 208 - http://httpstatusdogs.com/208-already-reported ? Is that a option?
In my opinion, if the only thing is a repeat resource no error should be raised. After all, there is no error neither on the client or server sides.
Stumbled upon this question while checking for correct code for duplicate record.
Pardon my ignorance but I don't understand why everyone is ignoring the code "300" which clearly says "multiple choice" or "Ambiguous"
In my opinion this would be the perfect code for building a non standard or a particular system for your own use. I could be wrong as well!
https://www.rfc-editor.org/rfc/rfc7231#section-6.4.1
More likely it is 400 Bad Request
[**6.5.1. 400 Bad Request**][1]
The 400 (Bad Request) status code indicates that the server cannot or
will not process the request due to something that is perceived to be
a client error (e.g., malformed request syntax, invalid request
message framing, or deceptive request routing).
As the request contains duplicate value(value that already exists), it can be perceived as a client error. Need to change the request before the next try.
By considering these facts we can conclude as HTTP STATUS 400 Bad Request.
Since you mentioned that the object create request using post contains the ID of the object, you should make it an idempotent request. Just return the exact same response as a successful create request. Idempotent request makes APIs simpler, eg. now client doesn't have to worry about 2 different cases (success, failure). or client can safely retry the request, in case something goes wrong in connectivity/ server temporarily down.
Error 402, payment required
I.E. this resource already exists but if you give me enough money I'll delete the current one and give it to you :D
...but looking at mozilla's definition of status codes at https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses
as a more serious answer that no one has provided here, what about 451: unavailable for legal reasons. You cannot "legally(by terms and conditions put in place by yourself)" give multiple people access to the same account information
422 is also a good option which is Unprocessable Entity
The request was well-formed but was unable to be followed due to semantic errors. since it is a perfectly valid request but due to it being semantically equal to another entry, it cannot be followed.
This is a user side fault and belongs to 4xx group. This is the right answer https://developers.rebrandly.com/docs/403-already-exists-errors