I know this question is nearly a year old, but thought I'd add an answer based on my own experience designing and building a very large API domain across nearly 400 microservices.
Ideally, APIs should follow Postel's Law and be tolerant of what it receives. This has helped us clarify when to use 400
and when to use 422
.
In the answer above, we would see the example 400 response as a 422 response. Why? Because we're tolerant of an "unknown" property by ignoring it. But the required <date>
field is missing so we would return a 422 containing an error indicating as a such.
A 400 response would be raised if the consumer sent through a JSON payload under the application/xml
content type or if the XML request was invalid (ie. they had <date>2020-01-07</dat>
field).
An advantage this approach has given us is that we can define a different response contract for 422 responses while allowing 400 responses to remain a fairly generic "WTF are you trying to ask?" responses. Our 422 responses contain a collection of error messages that list every request constraint or requirement that has been broken.
We've also found this approach to be particularly useful for our UX guys who can submit forms to APIs and get back a response with human-readable errors they can map straight back onto the form fields (ie. hitting submit and not having filled in a compulsory field will generate a 422 response with a message stating that property is required).