The average API error tells you that something went wrong and stops. The developer reading it is now doing forensics on a string. This is the cheapest thing in your whole product to improve and one of the last things anyone gets to.
Four fields
- A stable machine-readable type. Not a message, not a number that changes.
- A human message written for the developer, not the end user.
- The parameter or field at fault, when there is one.
- A link to the documentation for that specific error type.
Stable types matter more than pretty messages
Clients will branch on something. If you do not give them a stable type, they will branch on the message string, and then your copy edit becomes their outage. Pick the type vocabulary early and treat it as part of the contract.
Every error message is eventually parsed by a regular expression written by someone who had no other option.
Include the identifier
Put the request identifier in the error body as well as the headers. Half of the people who report the problem will paste the body and nothing else, and you will be glad it is in there.