I have used #2 myself a couple times. Is it better than #1? I think that depends on what your API is being used for.
I like #2 because it gives a developer who is testing the API with some test calls a quick overview of all the errors/mistakes he made in a request, so he knows immediately which errors/mistakes he has to fix to make that request valid. If you return the errors one by one (like in #1) you have to keep retrying the request and cross fingers hoping it will be valid this time.
But as I said #2 is very useful for developers, but the reasons don't really apply to end users. End users don't usually care how it's implemented. Whether the software is doing 1 request which returns 5 errors or 5 subsequent requests which return 1 error each.
As long as it's handled well in the client, the end user shouldn't notice the difference. How to handle that of course very much depends on what the client actually is.
Next to speeding up the development, another benefit of #2 (in production) is that it requires less requests to be made, which of course decreases the server load.
I would like to know if anyone went #2 and maybe have any improvements on it so I opened a bounty.
Sure there are improvements to be made. As it is, there is some data in the body that can be omitted.
{ "status": 400, "error": { "code": 1 //General bad Request code "message": "Bad Request", "developer_message": "Field validation errors." "more_info": "www.api.com/help/errors/1", "error_details": { 0: { "code": 2 // Specific field validation error code "message": "Field \"x\" is missing from the array structure", "developer_message": "The request structure must contain the following fields {a,b,c{x,y,z}}", "more_info": "www.api.com/help/errors/2" }, 1: { ( "code": 3 // Specific field validation error code "message": "Incorrect Format for field \"y\"", "developer_message": "The field \"y\" must be in the form of \"Y-m-d\"", "more_info": "www.api.com/help/errors/3" ) } )
With HTTP responses, the status code should not go in the body, but in the header. This means that "status": 400 and "message": "Bad Request" can be omitted here. 400 should be the response's status code, and 400 means Bad Request. It's a HTTP standard and doesn't have to be explained in the response. Also "developer_message": "Field validation errors." is kind of a duplicate, since the specific errors are already included in each seperate error, so we could leave that out.
That leaves
{ "error": { "code": 1 //General bad Request code "more_info": "www.api.com/help/errors/1", "error_details": { 0: { "code": 2 // Specific field validation error code "message": "Field \"x\" is missing from the array structure", "developer_message": "The request structure must contain the following fields {a,b,c{x,y,z}}", "more_info": "www.api.com/help/errors/2" }, 1: { ( "code": 3 // Specific field validation error code "message": "Incorrect Format for field \"y\"", "developer_message": "The field \"y\" must be in the form of \"Y-m-d\"", "more_info": "www.api.com/help/errors/3" ) } )
"code": 1 //General bad Request code "more_info": "www.api.com/help/errors/1",
These 2 lines don't really make sense anymore now. They are also not required, since each error has it's own code and info link, so we might strip these lines as well, leaving this
{ "error": { "error_details": { 0: { "code": 2 // Specific field validation error code "message": "Field \"x\" is missing from the array structure", "developer_message": "The request structure must contain the following fields {a,b,c{x,y,z}}", "more_info": "www.api.com/help/errors/2" }, 1: { ( "code": 3 // Specific field validation error code "message": "Incorrect Format for field \"y\"", "developer_message": "The field \"y\" must be in the form of \"Y-m-d\"", "more_info": "www.api.com/help/errors/3" ) } )
The 400 status code already indicates there was an error, so you don't have to indicate "error": {error details} anymore, because we already know there was an error. The list of errors can simply become the root object:
[ { "code": 2//Specificfieldvalidationerrorcode "message": "Field \"x\" is missing from the array structure", "developer_message": "The request structure must contain the following fields {a,b,c{x,y,z}}", "more_info": "www.api.com/help/errors/2" }, { "code": 3//Specificfieldvalidationerrorcode "message": "Incorrect Format for field \"y\"", "developer_message": "The field \"y\" must be in the form of \"Y-m-d\"", "more_info": "www.api.com/help/errors/3" } ]
So all that's left in the body now is simply a list of errors.
The status code is specified in the response header.
The details are specified in the response body.