I’ve been involved with helping a number of teams start-out with Web API development, and I always encourage them to agree their HTTP response codes sooner-rather-than-later.
Personally, I’m a fan of documenting this as a flow-chart. That way, both those writing and those consuming the API have a straightforward means of knowing what to do for a given situation.
Many of these “error” state codes should also be accompanied with a brief random pause (e.g., …
usleep(rand()*100); ) to help protect against timing attacks.
For consumers, the HTTP response code should give clear indication as to whether the request should be retried or not. This may prove particularly useful for your operations team, who may be configuring load balancers, API gateways, service meshes, proxies, or other L7 devices to circuit-break or deprioritise backends upon seeing a flood of specific response codes.