HTTP 200 does not mean it worked
The workflow reports success while nothing actually happened. Why a green status code tells you nothing about the outcome, and how we verify write calls before trusting them.
A green checkmark is not proof of anything. It is proof the request arrived.
There is a specific kind of bug that survives for months because everything about it looks healthy. The dashboard is green. The success rate is one hundred percent. No failed runs, no error emails, nothing for a monitor to catch. And yet the thing the workflow was supposed to do never happened.
I have walked into this exact situation more than once. The most memorable was an online shop sending order confirmations through an email service, wired up in a no-code scenario. Order comes in, call the send API, status 200, move on. For weeks it looked perfect. Then the calls started: customers who never got a confirmation. The API had answered 200 every single time. The body of that response said something the workflow never read: "accepted: false, reason: recipient rejected." The service had taken the message, inspected it, and thrown it away.
A status code describes the pipe, not the outcome
An HTTP status tells you the request reached the server and was handled without a protocol-level error. It does not tell you that your actual goal was met. The server can say "I understood your request and processed it cleanly," and the result of that clean processing can still be "and I declined it."
Most people picture status codes as binary. 2xx good, 4xx and 5xx bad. Reality is blurrier. Plenty of APIs wrap a business failure inside a 200, because from the server's point of view it did its job correctly. Whether the result is what you wanted is a separate question, and the answer lives in the response body, not in the status line.
The usual suspects
Three places trip teams up again and again.
Batch endpoints are the classic. You send fifty records in one call. The response is 200 because the server accepted the list. Buried in the body it tells you forty-seven went through and three were rejected. Check only the status and those three vanish without a sound.
Async services are the second. A 200 or 202 there means "queued," nothing more. Whether the job actually ran later is something you learn through a separate poll or a callback. The green step only proves someone took the order.
Then there are older or oddly built interfaces that return 200 no matter what and stash the real result in a field like errorCode. For those, the HTTP status is worthless on its own.
Why no-code hides it so well
In Make, n8n, or Zapier, the HTTP step is marked successful the moment any 2xx comes back. The response body flows downstream as data, but nobody inspects it unless you explicitly tell them to. So the default path always continues straight ahead, even when the body literally says "rejected."
That is what makes this bug so persistent. The interface shows a flawless success rate. There is no red error, no failed execution, nothing that would wake up an alert. The workflow is not lying to you. It is answering a different question than the one you meant to ask.
What we check instead
After every write call, we read the body, not just the status. For each interface we decide in advance what success actually looks like. For that email service it was not "status 200," it was "accepted is true." That definition belongs in the documentation, otherwise the next person guesses all over again.
Then comes an explicit branch. A 200 with a business error in the body has to flow into the same error handling as a real 500. To the automation both are a failure; only the wrapping differs.
For batch calls we count. We sent fifty records, so fifty confirmations should come back. If the number is off, the workflow stops or writes the gap to a list a human reviews. A response that says "three failed" only helps if that sentence reaches someone.
How to find it in a workflow you already run
If you have a live automation and want to know whether this bug is sitting in it, walk through the write calls and ask two questions per call. First: am I checking anything beyond the status code here? If the next step sits right after the HTTP module with no condition reading the response body, the answer is almost always no. Second: what happens to the data if this call quietly declines? A missing email, a record that never gets created, an invoice that never goes out?
Then read how the API provider actually signals failure. Some of them state plainly that business errors come back as a 200 with a flag in the body. Those are the dangerous ones, because the behavior is technically correct and invisible to a naive branch. Ten minutes in the error section of the docs tends to save weeks of silent data loss.
The pattern underneath
Do not trust the envelope. Read the letter. The status code tells you the mail arrived. Whether it holds a yes or a no is in the contents.
This class of failure is dangerous precisely because it feels exactly like success. No warning, no retry, no trace in the logs. You will not notice it at the workflow. You will notice it three weeks later, in the customer asking why they never heard back.