Ask
24
@api_dilan ·

Why do so many JSON API conventions put a success flag in the body when HTTP already has status codes?

Reading around for a standard response shape, the recurring recommendation is an envelope containing a boolean success field, then either data or an error object.

This seems redundant. HTTP already carries that information in the status line, and it carries it in a place every client, proxy and cache understands without parsing anything.

So what is the reasoning? I am prepared to believe there is one, since the convention is very widespread, but every article I find asserts the shape without justifying it.

4 answers Share
Report

Answering anonymously — a moderator will review it first.

  • @architect_ayla · 2w ago

    The cost of the envelope is worth stating, because it is real and it accumulates.

    You lose the layers between you and the client. Caches, proxies, load balancers, monitoring, retry logic and alerting all understand status codes and none of them can read your body. A service returning 200 for everything looks perfectly healthy on every dashboard while failing every request.

    That last one bites eventually. I have watched an outage last far longer than it should have because the error rate graph was flat.

    The position I have settled on is a middle one and it is fairly common in practice:

    • Use status codes honestly for transport and protocol outcomes. 400 for malformed, 401 and 403 for auth, 404 for missing, 5xx when you broke.
    • Use the body for domain outcomes, with a 200 and a structured result, when the operation completed and produced a negative answer.

    That keeps the infrastructure informed and keeps domain semantics out of a four-hundred-code vocabulary that was never designed for them.

    24
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
  • @api_dilan · 2w ago

    There are three real reasons, and one of them is good.

    The good one: transport failure and business failure are different things. A request to buy something with insufficient funds is a successful HTTP exchange — the server understood, processed, and answered correctly. The answer happens to be no. Conflating that with a 500, where the server broke, or a 404, where the route does not exist, loses a distinction that clients genuinely need.

    Some people map that onto 4xx codes anyway, and it works until you have twenty domain outcomes and four vaguely appropriate codes.

    The pragmatic one: many HTTP clients throw on non-2xx. That means a business outcome delivered as a 4xx arrives in the error path, where the response body is awkward to reach and stack traces get logged. A 200 with a success flag arrives in the normal path.

    The weak one: uniformity. Every response has the same shape, so client code has one parsing path. Genuinely convenient and not a reason on its own.

    28
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
  • @js_runtime_jonas · 2w ago

    Worth adding that the redundancy objection assumes the client always sees your status code, and there are cases where it does not.

    An intermediate proxy can replace the response. A gateway can produce its own 502 that never reached your service. A CDN error page has a status but no body of yours at all. In those situations, a body that carries its own outcome lets a client distinguish "your service said no" from "something in between produced this".

    That argument is stronger for public APIs crossing many networks than for a service called by your own front end over one hop.

    19
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
  • @entropy_elif · 2w ago

    One practical note whichever way you go: be consistent, and document it in one paragraph at the top of your API reference.

    The worst outcome is not either convention. It is a service where some endpoints use status codes, some use the envelope, and a few use both with different meanings. Clients then need per-endpoint knowledge, which is exactly what an API is supposed to avoid.

    12
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report