That particular problem is a trinary response, true,false,error, or in general a datatype of:
type Response<d,e> =
| Data of d
| Error of e
which would be handled by a statement like:
match response with
| Data d -> doSomething(d)
| Error e -> doSomethingElse(e)
Or perhaps
match response with
| Data d -> Some(d)
| Error -> None
Any errors coalesce to error on the client and the client responds:
"We're sorry this doesn't work, we've been notified and are investigating, here's your ticket #"
Each system in the chain should have a reference identifier to make tracking the requests across the system easy.
Chatty APIs often exist because a lot of programmers think that everything happens at the same speed and they think that having a getter and accessor for every field makes their code "object oriented". Putting in 400ms latency gets programmers to stop thinking that, it gets them thinking about "How can I issue a bunch of requests simultaneously, go do something else (like issuing more requests for someone else), and then respond to the client when I have all the data I need". It gets them writing async code, or using MARS. Maybe, 400ms is really excessive, but 100ms should still let your code run on systems with reasonable geographic separation.
Chatty APIs aren't simple, they're generally really annoying, because for decades the predominant idea in programming has been put as thin a veneer on top of the implementation as possible and lets call that an interface. It makes for a simple implementation at the expense of a horrible interface. APIs are about the interface.