Related
I'm building some REST API to be used in a native iOS/Android app.
One of the endpoints allows the user to update his password by providing 2 fields: old_password and password.
Which HTTP status code should I in the situation where the old_password is incorrect?
My first thought was a 401 error but I already use it when the authentication token is invalid and it automatically triggers a logout in the app.
400 doesn't seem to fit because the request is actually semantically correct, it is a specific authentication error. Maybe 422?
One thing to keep in mind is that status codes, like response headers, are metadata; they are there so that generic components that know nothing about the details of your API can participate intelligently -- for example, by invalidating caches, or throwing up dialogs to collect authentication credentials.
400 doesn't seem to fit because the request is actually semantically correct
In practice, 400 is usually fine; clients are supposed to treat an unrecognized 4xx class status code as they would treat 400. Put another way, you can use 400 unless you specifically want to induce a different behavior by the generic components.
For your specific case, 409 Conflict is probably the closest match
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. This code is used in situations where the user might be able to resolve the conflict and resubmit the request. The server SHOULD generate a payload that includes enough information for a user to recognize the source of the conflict.
RFC 5789 suggests a distinction between 409 and 422 that may be interesting. Paraphrasing this distinction
422: This might include attempts to modify a resource in a way that would cause the resource to become invalid
409: the request cannot be applied given the state of the resource.
You can also make a reasonable argument that the entire 4xx class of response codes is inappropriate. For example, if the request method is POST, then the server is expected to
process the representation enclosed in the request according to the resource's own specific semantics
Which it did; successfully, even. It just didn't produce the most commonly expected successful result.
On the other hand, the JSON Patch would argue the other direction; your attempt to change the password would probably look something like
[
{ "op": "test", "path": "/password", "value": "old_password" },
{ "op": "replace", "path": "/password", "value": "new_password" }
]
If you provided the wrong password in the test, then that operation would be considered unsuccessful, which would in turn mean that the PATCH is unsuccessful. That in turn would invoke the arguments for error handling as described in HTTP Patch.
We have an endpoint which when you post create a new version of resource and returns a 201 and the location of the newly created resource. It determines the new version number based on a comparison of the current version and the version being posted (using a semver like ruleset).
If the version you post is identical to the existing version then no version number is updated. What should we return in this case?
We could just return a 201 even though we have not technically created anything.
I don't want to return a 409 as its not really a conflict, like when you post something with the same id. If you posted the same thing when the existing version was slightly different then you would happily get a 201.
We could just return a 200, but then that would seem weird, and increases the response codes that the users have to deal with
Does the idempotency of the 201 response matter?
Any better suggestions?
How about 303 - See Other? Seems to fit. I draw your attention to this sentence
from the spec at https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
This method exists primarily to allow the output of a POST-activated script to redirect the user agent to a selected resource.
That sounds like what you want to do to me. Here's the rest of it.
10.3.4 303 See Other
The response to the request can be found under a different URI and SHOULD be retrieved using a GET method on that resource. This method exists primarily to allow the output of a POST-activated script to redirect the user agent to a selected resource. The new URI is not a substitute reference for the originally requested resource. The 303 response MUST NOT be cached, but the response to the second (redirected) request might be cacheable.
The different URI SHOULD be given by the Location field in the response. Unless the request method was HEAD, the entity of the response SHOULD contain a short hypertext note with a hyperlink to the new URI(s).
Note: Many pre-HTTP/1.1 user agents do not understand the 303
status. When interoperability with such clients is a concern, the
302 status code may be used instead, since most user agents react
to a 302 response as described here for 303
I am a bit puzzled by the other answers as some get it almost right. So, let's clear up things a bit. If all requests are indeed performed with the POST method, in the context of ReSTfulness, they are supposed to modify state on the target server. Otherwise, the meaning of POST is a bit relaxed as you can see in RFC 7231, sec. 4.3.3.
Since the intent of the requests is to create a new version of a resource, they have failed if a version with the given presentation already exists. This would disqualify any 2xx-class response codes. From section 6.3:
The 2xx (Successful) class of status code indicates that the client's request was successfully received, understood, and accepted.
If you absolutely wanted to, you could go for 202/Accepted, which "is intentionally noncommittal." This is a bit of a stretch, though, as this status code is intended for queued processing. I would advise against it.
The 204/No Content code suggested by others is a bit of a poor choice. It were absolutely correct if you POSTed to the resource you were updating, though.
As the result is neither informational (1xx) nor a fault by the server (5xx). Let us have a look at the 3xx class first. From section 6.4:
The 3xx (Redirection) class of status code indicates that further action needs to be taken by the user agent in order to fulfill the request.
One of the most prominent one here would be 304/Not Modified. While sounding like a perfect fit, this code is unfortunately not applicable here. It can only be returned in response to conditional GET or HEAD requests.
302/Found may sound like the next best fit. However, this code is intended for temporary redirects, which is in all likelyhood not what you want.
As has been suggested here, 303/See Other is indeed a good choice:
The 303 (See Other) status code indicates that the server is redirecting the user agent to a different resource [...] which is intended to provide an indirect response to the original request.
[...]
This status code is applicable to any HTTP method. It is primarily used to allow the output of a POST action to redirect the user agent to a selected resource
All other 3xx codes are dealing with various forms of redirects that hardly relate to the situation here.
A final look, 4xx-class of status codes. From RFC 7231, sec. 6.5:
The 4xx (Client Error) class of status code indicates that the client seems to have erred. Except when responding to a HEAD request, the server SHOULD send a representation containing an explanation of the error situation, and whether it is a temporary or permanent condition. These status codes are applicable to any request method.
Very few of these are actually deeling with the request body. Two of those who do would stand out here: One is 400/Bad Request, which is by design overly broad. It is - if you will - a catch-all solution. However, this would imply that the request body is malformed (as in syntactically incorrect) in some way, which is probably not the case.
More interesting is 409/Conflict. From the RFC (emphasis mine):
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 wording of the definition places this code close to the PUT method, but is not exclusive. To reiterate the definition of the 4xx codes:
These status codes are applicable to any request method.
422/Unprocessable Entity is a contender, but it implies a semantic error, which really isn't the case here.
Ultimately (drumroll) the final piece of the puzzle could be found in section 4.3.3:
If the result of processing a POST would be equivalent to a representation of an existing resource, an origin server MAY redirect the user agent to that resource by sending a 303 (See Other) response with the existing resource's identifier in the Location field.
Note the "MAY." So you can really choose between 303 and 409. I feel 409 were the better fit, as clearly an earlier request introduced a state that is incompatible with the current one. OTOH, 303 may be the politer way to go and is closer to the standard. Either way, as a consumer of your API, I would really like to know if my requests failed. And be it by not having any effect whatsoever.
If nothing has been created by the operation, 201 is not suitable for that:
6.3.2. 201 Created
The 201 (Created) status code indicates that the request has been fulfilled and has resulted in one or more new resources being created. [...]
See below some options you could consider if the operation succeeds:
6.3.1. 200 OK
The 200 (OK) status code indicates that the request has succeeded. The payload sent in a 200 response depends on the request method. For the methods defined by this specification, the intended meaning of the payload can be summarized as:
[...]
POST: a representation of the status of, or results obtained from, the action;
[...]
Aside from responses to CONNECT, a 200 response always has a payload, though an origin server MAY generate a payload body of zero length. If no payload is desired, an origin server ought to send 204 (No Content) instead. [...]
6.3.5. 204 No Content
The 204 (No Content) status code indicates that the server has successfully fulfilled the request and that there is no additional content to send in the response payload body. [...]
If the operation fails:
6.5.1. 400 Bad Request
The 400 (Bad Request) status code indicates that the server cannot 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).
11.2. 422 Unprocessable Entity
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. For example, this error condition may occur if an XML request body contains well-formed (i.e., syntactically correct), but semantically erroneous, XML instructions.
A 201 Created should be used whenever you creating a new resource without doubt.
As defined in HTTP Method Definitions RFC, either200 Ok or 204 No Contentis an appropriate response if the operation does not create a new resource depending on the response body content.
The action performed by the POST method might not result in a resource
that can be identified by a URI. In this case, either 200 (OK) or 204
(No Content) is the appropriate response status, depending on whether
or not the response includes an entity that describes the result.
If a resource has been created on the origin server, the response
SHOULD be 201 (Created) and contain an entity which describes the
status of the request and refers to the new resource, and a Location
header (see section 14.30).
Now, coming back to your original question about what to use when the operation is successful and there is nothing to return, you should use 204 No Content. This status code is specifically meant for scenarios where the requested operation is successfully completed but there is no additional relevant information that the server can provide.
The 204 (No Content) status code indicates that the server has successfully fulfilled the request and that there is no additional content to send in the response payload body.
I don't think that for this case the idempotency is an issue, because the state of the system is not the same as it was in the inicial request, because the entity now exists, so you can respond with a different code.
200 should be fine, but it is a little weird as you said.
I have never use this, but I read that for some case you should redirect with a 302, to make a get for other resource, in this case I think this apply, return a 302 and make a get pointing for the old semver, assuming that you have a get endpoint for this entity.
If the POST'd resource has the same version number, but different data, then a 409 would be fitting. But if the data is the same as what's already stored, then a 409 might not be required. Through process of elimination I would say 200 OK would be fine.
We could just return a 200, but then that would seem weird, and increases the response codes that the users have to deal with
If this is a costly concern, consider eliminating the 201, not the 200. The fact of the matter is that for any decently complex service there may be at some point a situation where a 20X (where X is not 0) is applicable. So does that mean we code with each of the 20X responses in mind and spend time checking if our services has situations where 20X is preferred over 200? I suspect not. So unless there is a specific reason to respond with a 20X, for example to deal with a specific use case, then just use 200 and reduce the amount of coding and documenting required. I suspect for most scenarios, the calling client does not care.
Ultimately, the correct answer probably depends on whatever client is consuming your API. If you are building the client too, you could do whatever you prefer... (Just don't get too crazy.)
Assuming you are writing the API and client:
My opinion/suggestion is...
If there IS a new version number: The 201 HTTP status code would fit will.
If there is NOT a new version number: The 200 or 204 HTTP status code would fit well.
If there is no benefit to the client knowing the version number has changed or is the same: Send the 200 HTTP status code.
If you don't control the client consuming your API: Obviously defer to what they expect.
You may also wish review all of the HTTP Status Codes in the HTTP RFC spec. The above status codes also link directly to the relevant section.
201 : when new version is created
202 : when existing version is updated
204 : when request is accepted but no processing is done
by def, 204 = No Content
The server has fulfilled the request but does not need to return an
entity-body, and might want to return updated metainformation. The
response MAY include new or updated metainformation in the form of
entity-headers, which if present SHOULD be associated with the
requested variant.
If the client is a user agent, it SHOULD NOT change its document view
from that which caused the request to be sent. This response is
primarily intended to allow input for actions to take place without
causing a change to the user agent's active document view, although
any new or updated metainformation SHOULD be applied to the document
currently in the user agent's active view.
The 204 response MUST NOT include a message-body, and thus is always
terminated by the first empty line after the header fields.
So its slight tangential to your needs but I think its the best fit.
I'm trying to design a REST method for an 'Add person' operation that has a bunch of business rules. There are multiple possible non-success payloads (for the business purposes), requiring defined structure (to allow the consumer to parse the detail).
For 'Add a person', one of the following non-successes could happen:
We believe the system already has person.
Payload: The ID of that person
There are some possible matches.
Payload: A list of possible duplicates, and an override code to submit the record 'for sure'
General validation errors
Payload: Array of 'Error' object. (Standard across the API)
Question - Response object
If they're all to return under a single HTTP error status code, would it be right to have a varied object like:
OverrideCode (for (1))
PersonPossibleMatches [] (also for (1))
PersonDuplicateId (for (2))
ErrorList [] (for (3))
And have the consumer + documentation explain the interpretation?
Question - Response code
Is 400 (Bad Request) the correct (or correct enough) HTTP status code for this? We use it largely for the field validation (also scenario (3) - just wondering if business rule / 'intermediate state' things like this are any different.
Are there a more appropriate codes to spread the 3x scenarios over? And is it ok for the payloads to be different?
Thanks.
There are two aspects you need to consider
HTTP response code.
Error response payload.
Point number 1 is relatively simple. You have 400 error code for bad requests. And 409 for conflicting resources. So far simple.
Now let us consider your scenarios:
We believe the system already has person.
Payload: The ID of that person
Design suggestion: you can send a response like below
Response code: 409
{
"error_code": "resource_exists",
"error_description": "Resource person with ID XXX already exists"
"debug_info": "",
"link" : [
{
"href": "http://host-name/persons/123456",
"rel": "person"
}
]
}
2. There are some possible matches.
Payload: A list of possible duplicates, and an override code to submit the record 'for sure'
Design suggestion:
In this case - you may want to use PUT to override the resource. No need to use special code.
Response Code: 400
{
"error_code": "potential_duplicates",
"error_description": "Potentially the resource is duplicate of one of the following. Please use PUT with the resource ID to update"
"debug_info": "",
"link" : [
{
"href": "http://host-name/persons/234",
"rel": "person"
},
{
"href": "http://host-name/persons/456",
"rel": "person"
},
{
"href": "http://host-name/persons/789",
"rel": "person"
}
]
}
General validation errors
Payload: Array of 'Error' object. (Standard across the API)
Design suggestion: Here you can simply use 400 response code and a meaningful response like the examples above.
This depends in part on how the operation is performed. Since you said the operation has a bunch of business rules, and the system returns a payload with an ID when the person already exists, let's assume the operation is non-idempotent due to unrelated side-effects, performed with a POST to a factory endpoint.
1. We believe the system already has person.
This is a no-brainer. As suggested by others, you should use a 409 Conflict status code, with a body describing the nature of the conflict. In this case, it seems like there's nothing else the user needs to do, and he can move forward to the next step in the workflow. If there's something he can do, it should follow a procedure similar to the next case.
2. There are some possible matches.
Assuming that the clients don't have any key to unambiguously identify a person, which seems to be your case since you're considering possible matches, here you should also use a 409 Conflict status code, with a body describing the nature of the conflict, but with instructions on how to solve it.
Some other answer suggests you to allow an overwrite parameter that could be used any time, other suggests using a PUT, but I disagree with that since there's nothing preventing a client from using the overwrite all the time, or skipping the POST and use the PUT to replace an existent close-match. Also, you may have concurrent clients trying to add or change a person that match each other, or a common existent group, which will lead to an ABA conflict.
The conflict resolution body should return a valid tag for each possible match, and the client should be instructed to resubmit the same request with the If-Match header and the collection of tags. It may be a single tag, as long as it's generated from key data from each member in the collection. This will enforce that the user first must try the request without any override. If there's a conflict the user is forced to specify the exact entities that will be overwritten, and you're protected from inconsistent updates in case someone changes the current state between the first and the second request.
If the tags don't match in the second request, meaning the state was changed by something else between them, you should fail with a 412 Precondition Failed error.
3. General validation errors
This is also a no-brainer. A 400 Bad Request detailing the error, which seems to be standard across your API.
You could use 409 for the duplicate entry - and arguably for the possible duplicate entries with the extra info in the payload.
http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.10
A 400 for validation errors would be the expected response.
It is a judgement call at the end of the day and it depends what would be easier for your rest clients and what they are doing.
Here's the design process I use when creating RESTful API responses for error cases:
Design the response payload for the error condition. Regardless of the error code that's used, it is always good practice to return some content within error responses so that clients can learn more about the error and how to avoid it in the future.
If there is an HTTP status code that accurately describes this error already, and it's not already in use for another error case, use that.
If the closest matching error code is already being used for another error case, it's still OK to use that code, but the response payload becomes the place where the different error cases under that code get distinguished from each other. Your documentation should clearly state that inspecting this code wouldn't be enough, and that clients should then also look into the response to see exactly what happened.
If none of the above are applicable, use the closest error code that's appropriate. Just as in #3, the documentation of your response payloads makes this approach possible. If it's an error that the client influenced, make it a 400-range error, probably 400 - Bad Request. If it's the server's fault, then it should be a 500-range error, probably 500 - Internal Server Error.
Please, please, never throw 200 - OK for errors. The world left that nonsense behind in SOAP land, and nobody wants to go back.
Now let's apply that thinking to your error cases:
We believe the system already has that person. As correctly stated in another answer, 409 - Conflict accurately describes that error, so you should just use that. Putting some descriptive error information in the response payload would help new users of your API, even with such a definitive and understandable code.
There are some possible matches. There really isn't an HTTP code that describes this, and it's something that the client could influence, so the closest would be the catch-all code of 400 - Bad Request. Including the list of possible duplicates is an interesting idea, but make sure you don't end up returning enormous responses with huge numbers of possible matches. Also, make sure to also return URIs to those matching resources so that your clients can easily consume them. As for the "override code" suggestion, I wouldn't return that in the payload. Rather, I'd just document a parameter to your "Add a Person" operation that would allow for overrides to occur at any time, not just after a failed first attempt. For example: POST /people?overwrite=true.
General validation errors This is definitely a job for 400 - Bad Request, along with a descriptive error payload. It sounds like you're already allowing an array of errors to be returned from any API call, so that should be good enough to capture all the validation failures for the client-supplied data.
How about explaining it with a payload back; That is how we deal with REST responses for clients.
Response HTTP 409 with following payload response indicating to client what should they do next
`
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<request-result>
<http-code>200</http-code>
<description>REST Request is successfully processed</description>
<internal-error-info>Person already Exists</internal-error-info>
<message>Person with <id> already exists in sytem. Try picking different ID/Name combination</message>
<requested-operation>Add a Person</requested-operation>
<resource-name>Person</resource-name>
<status>SUCCESSFUL</status>
</request-result>
`
First of all, I've read some relevant posts:
Best HTTP status code in REST API for “Not Ready Yet, Try Again Later”? It is about GET an item
Is it wrong to return 202 “Accepted” in response to HTTP GET? It is about GET an item
HTTP Status Code for Resource not yet available It is about POST
HTTP status code for in progress? It is about GET but no clear answer.
but I still think I should raise my question and my thoughts here. What should be the HTTP status code in REST API for using GET to QUERY a “Not Ready Yet, Try Again Later” resource? For example, client tries to query all local news happen in future(!) by make an HTTP GET to this url: http://example.com/news?city=chicago&date=2099-12-31 so what shall the server reply?
These are the http status code I considered, their rfc definition and why I am not fully satisfied with:
3xx Redirection. Comment: Not an option because there is no other link to be redirected to.
503 Service Unavailable: The server is currently unable to handle the request due to a temporary overloading or maintenance of the server. The implication is that this is a temporary condition which will be alleviated after some delay. If known, the length of the delay MAY be indicated in a Retry-After header. Comment: The retry behavior is desired, but semantically the situation is not server's fault at all, so all 5xx look weird.
4xx Client Error. Comment: Looks promising. See below.
413 Request Entity Too Large: The server is refusing to process a request because the request entity is larger than the server is willing or able to process. ... If the condition is temporary, the server SHOULD include a Retry- After header field to indicate that it is temporary and after what time the client MAY try again. Comment: The retry behavior is desired, however the "Entity Too Large" part is somewhat misleading.
417 Expectation Failed: The expectation given in an Expect request-header field (see section 14.20) could not be met by this server. Comment: So it should be caused by an Expect request-header, not applicable to my case.
406 Not Acceptable: The resource ... not acceptable according to the accept headers sent in the request. Comment: so it is caused by the Accept request-header, not applicable to my case.
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. ... Conflicts are most likely to occur in response to a PUT request. Comment: This one is close. Although my case is not about PUT, and isn't actually caused by conflict.
404 Not Found: The server has not found anything matching the Request-URI. Comment: Technically, my url path (http://example.com/news) DOES exist, it is the parameters causing problems. In this case, returning an empty collection instead of a 404, is probably more appropriate.
403 Forbidden: The server understood the request, but is refusing to fulfill it. Authorization will not help and the request SHOULD NOT be repeated. Comment: Generally this is supposed to be used in any restricted resource?
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. Comment: It is not true in my case. My server understands the request, its syntax is good, only the meaning is bad.
2xx Successful. Comment: If 4xx doesn't work, how about 2xx? See below.
200 OK. Comment: Fine. So what should I include in the response body? null or [] or {} or {"date": "2099-12-31", "content_list": null} or ... which one is more intuitive? On the other hand, I prefer a way to clearly differentiate the minor "future news" error from the more common "all query criteria are good, just no news this day" situation.
202 Accepted: The request has been accepted for processing, but the processing has not been completed. The request might or might not eventually be acted upon. Comment: Providing that we can use 202 in a GET request, it is acceptable. Then refer to the 200 comment.
204 No Content: The server has fulfilled the request but does not need to return an entity-body. Comment: Providing that we can use 204 in a GET request, it is acceptable. Just don't know whether this is better than 202 or 200.
More on 2xx: Comment: I assume all 2xx response will likely be cached somewhere. But in my case, if I return an empty body for "tomorrow's news", I don't want it to be cached. Ok, explicitly specify the "no cache" headers should help.
Your thoughts?
Use 404.
Your objection to it is based on a popular understanding of a URI as not including the querystring. "Because I have multiple URI's that map to the same handler," goes the logic, "my resource does in fact exist and is just being parameterized by querystring args."
This is incorrect. As the URI spec itself says in Section 3.3 (emphasis mine),
"The path component contains data, usually organized in hierarchical
form, that, along with data in the non-hierarchical query
component (Section 3.4), serves to identify a resource within the
scope of the URI's scheme and naming authority (if any)."
Resources are identified by URI's, and any change to any part of an absolute-URI identifies a separate resource. Tweet that to everyone you know once a day until they tell you to stop. Therefore a 404 is a perfect match: "The 404 (Not Found) status code indicates that the origin server did not find a current representation for the target resource or is not willing to disclose that one exists."
You are retrieving the news for that day, which is a valid day, there just isn't any news. A 200 response of an empty body, or a what ever makes sense based on the mediatype would seem the logical. This depends on the media type you have decided with the client.
404 would make more sense if the date format was wrong (you asked for the 45th day of November, or asked for a city that doesn't exist.)
As an aside the URL would be better in the format http://example.com/news/chicago/2099-12-31 since that is the specific resource you want to retrieve. This format would make things like 404s clearer as well.
According to the "REST ideology" what should be in the response body for a PUT/POST/DELETE requests?
What about return codes? Is HTTP_OK enough?
What is the reason for such conventions, if any?
I've found a good post describing POST/PUT differences: POST vs PUT
But it still doesn't answer my question.
Forgive the flippancy, but if you are doing REST over HTTP then RFC7231 describes exactly what behaviour is expected from GET, PUT, POST and DELETE.
Update (Jul 3 '14):
The HTTP spec intentionally does not define what is returned from POST or DELETE. The spec only defines what needs to be defined. The rest is left up to the implementer to choose.
Overall, the conventions are “think like you're just delivering web pages”.
For a PUT, I'd return the same view that you'd get if you did a GET immediately after; that would result in a 200 (well, assuming the rendering succeeds of course). For a POST, I'd do a redirect to the resource created (assuming you're doing a creation operation; if not, just return the results); the code for a successful create is a 201, which is really the only HTTP code for a redirect that isn't in the 300 range.
I've never been happy about what a DELETE should return (my code currently produces an HTTP 204 and an empty body in this case).
Creating a resource is generally mapped to POST, and that should return the location of the new resource; for example, in a Rails scaffold a CREATE will redirect to the SHOW for the newly created resource. The same approach might make sense for updating (PUT), but that's less of a convention; an update need only indicate success. A delete probably only needs to indicate success as well; if you wanted to redirect, returning the LIST of resources probably makes the most sense.
Success can be indicated by HTTP_OK, yes.
The only hard-and-fast rule in what I've said above is that a CREATE should return the location of the new resource. That seems like a no-brainer to me; it makes perfect sense that the client will need to be able to access the new item.
I like Alfonso Tienda responce from
HTTP status code for update and delete?
Here are some Tips:
DELETE
200 (if you want send some additional data in the Response) or 204 (recommended).
202 Operation deleted has not been committed yet.
If there's nothing to delete, use 204 or 404 (DELETE operation is idempotent, delete an already deleted item is operation successful, so you can return 204, but it's true that idempotent doesn't necessarily imply the same response)
Other errors:
400 Bad Request (Malformed syntax or a bad query is strange but possible).
401 Unauthorized Authentication failure
403 Forbidden: Authorization failure or invalid Application ID.
405 Not Allowed. Sure.
409 Resource Conflict can be possible in complex systems.
And 501, 502 in case of errors.
PUT
If you're updating an element of a collection
200/204 with the same reasons as DELETE above.
202 if the operation has not been commited yet.
The referenced element doesn't exists:
PUT can be 201 (if you created the element because that is your behaviour)
404 If you don't want to create elements via PUT.
400 Bad Request (Malformed syntax or a bad query more common than in case of DELETE).
401 Unauthorized
403 Forbidden: Authentication failure or invalid Application ID.
405 Not Allowed. Sure.
409 Resource Conflict can be possible in complex systems, as in DELETE.
422 Unprocessable entity It helps to distinguish between a "Bad request" (e.g. malformed XML/JSON) and invalid field values
And 501, 502 in case of errors.
By the RFC7231 it does not matter and may be empty
How we implement json api standard based solution in the project:
post/put: outputs object attributes as in get (field filter/relations applies the same)
delete: data only contains null (for its a representation of missing object)
status for standard delete: 200