Start here. This is the direct spoken answer to practice first.
Why this question matters
HTTP status codes communicate a broad outcome, while a problem document gives clients a stable reason and enough safe context to react. It is an interface contract, not a serialized exception or a debugging dump.
I use Problem Details as the common error envelope because it already defines type, title, status, detail, and instance. The type identifies the kind of problem, while detail describes this occurrence safely. I add only useful extensions such as a stable application code, field errors, or a support correlation reference. A custom format can work, but it creates another contract that every endpoint, client, and document must keep consistent.