Your API returns 200. The health check is green. And yet, the mobile app shows a blank screen because the response body is an empty array instead of user data.
This is the gap most uptime monitoring setups never close. They confirm the server responded. They do not confirm the server responded correctly. A 200 with a malformed body, a stale cache response, or a latency spike that exceeds your client's timeout is functionally equivalent to downtime — your users cannot complete their task.
API uptime monitoring, done properly, goes well beyond status code checks. It validates that responses are structurally correct, arrive within acceptable time, and behave consistently across regions. Here is what that looks like in practice.
The problem with status-code-only monitoring
HTTP status codes exist to communicate transport-level outcomes. RFC 9110 (the successor to RFC 7231) defines 200 as "the request has succeeded" — but that success is from the server's perspective. The server processed the request without throwing an exception. It says nothing about whether the response payload is what your client expects.
Common failure modes that return 200:
-
Empty or truncated responses. A cache layer returns a stale empty object. A database timeout causes the API to return
{ "results": [] }instead of erroring. -
Error payloads wrapped in 200. Many APIs (especially GraphQL endpoints and legacy REST services) return errors inside the body:
{ "error": "rate_limit_exceeded" }with a 200 status. -
Schema drift. A deploy renames a field from
user_idtouserId. The endpoint still returns 200, but every client parsinguser_idbreaks. - Wrong content type. An HTML error page served with a 200 when the reverse proxy falls through to a default handler.
If your monitoring only checks for status == 200, all four of these look like a healthy API. Your dashboard stays green while users file support tickets.
What to assert beyond the status code
Assertion-based monitoring treats the HTTP response as a document with multiple checkable properties. Each assertion is a pass/fail condition — if any fails, the check fails, and an alert fires. Here is the practical checklist.
Response body validation
The most common gap. At minimum, confirm the response body contains expected structure:
-
Key existence. The JSON response contains a
datafield (or whatever your envelope uses). -
Value constraints. A list endpoint returns at least one item. A health endpoint returns
"status": "ok". -
Absence of error markers. The body does not contain an
errororerrorskey at the top level.
For stricter validation, JSON Schema checks confirm that every field has the expected type and required fields are present. This catches schema drift within minutes of a bad deploy.
Latency thresholds
An API that responds in 8 seconds is not "up" for a mobile client with a 5-second timeout. Latency assertions set an upper bound:
- p95 response time under 500ms for your primary endpoints
- Timeout threshold matching your client's actual configuration
- Degradation detection: alert when latency exceeds 2x the baseline, even if it's still under the hard timeout
Latency matters differently per region. An endpoint that responds in 120ms from US-East might take 900ms from Singapore due to a missing CDN edge or a database replica that only exists in one availability zone. Multi-region probes surface these discrepancies before users in specific geographies start churning. See best API monitoring tools for how different tools handle regional probe distribution.
Header assertions
Response headers carry meaningful signals that body validation misses:
-
Content-Type is
application/json(nottext/html, which indicates a proxy error page) - Cache-Control headers match expectations (stale responses behind a CDN often carry unexpected cache headers)
-
Rate limit headers (
X-RateLimit-Remaining) stay above zero for synthetic checks -
CORS headers are present (a missing
Access-Control-Allow-Originbreaks browser clients silently)
Multi-step API flows
Single-endpoint checks miss dependency chains. A login flow involves:
- POST credentials → receive token
- GET user profile with token → receive user object
- GET workspace data → confirm the session is valid end-to-end
If step 1 succeeds but step 3 fails because the token format changed or a downstream service is unreachable, a single-endpoint check on step 1 stays green while the app is broken. Multi-step monitors chain requests, passing values between steps, and fail the entire sequence if any step produces an unexpected result.
This is especially relevant for APIs that issue short-lived tokens, require specific request ordering, or depend on eventually-consistent data stores where writes don't immediately reflect in reads.
Certificate and DNS checks
API uptime is not just application-layer health. If your TLS certificate expires, clients cannot establish a connection — the API is unreachable regardless of whether the process is running. If DNS resolution fails or returns a stale record, traffic never arrives.
These checks sit alongside HTTP monitors as part of a complete API monitoring setup:
- Certificate expiry warnings at 30, 14, and 7 days
- Certificate chain validation (intermediate certs missing is a common mobile-only failure)
- DNS record value assertions (A/AAAA/CNAME match expected targets)
- DNS resolution time (elevated resolution time often precedes full failures)
Structuring your API monitoring stack
A pragmatic API monitoring setup layers these assertions by criticality:
Tier 1 — Every endpoint (runs every 30–60 seconds):
- Status code in expected range
- Response time under threshold
- Content-Type header correct
Tier 2 — Critical paths (runs every 1–5 minutes):
- Response body contains required fields
- No error markers in body
- Multi-step flows complete end-to-end
Tier 3 — Infrastructure layer (runs every 5–15 minutes):
- SSL certificate validity and chain
- DNS resolution correctness
- Regional latency consistency
This layering keeps alert volume manageable. Not every endpoint needs full JSON Schema validation on a 30-second interval. But your authentication flow, your payment endpoint, and your primary data API should have body assertions running frequently from multiple regions.
When assertions fail, alerting needs to reach the right team quickly. The difference between an SLO breach and an all-clear often comes down to whether the alert fired on a genuine body validation failure or a transient network blip. Multi-region confirmation (the check fails from 2+ regions before alerting) reduces noise without adding dangerous delay. For the relationship between these checks and your contractual commitments, see SLO vs SLA vs SLI.
Monitoring APIs is different from monitoring websites
Website monitoring can often get away with "is the page loading and returning HTML?" API monitoring cannot, because:
- APIs have no visual rendering to sanity-check — the response is data, not a page
- Clients depend on exact field names, types, and structures
- Multiple consumers (mobile, web, third-party integrations) may depend on the same endpoint with different timeout budgets
- Versioned APIs can drift between versions silently
This is why API testing and API monitoring are complementary but distinct practices. Testing catches contract violations before deploy. Monitoring catches them after — in production, under real load, across real network paths.
Where to start
If your current monitoring only checks status codes, the highest-value addition is response body validation on your three most critical endpoints. Pick the endpoints that, when broken, generate the most support tickets or revenue impact. Add a content-type header assertion and a latency threshold. Run the checks from at least two geographic regions.
DevHelm's assertion-based monitors let you define these checks as part of the monitor configuration — status code, headers, body keywords, JSON path assertions, and response time thresholds all evaluate on every probe from every region. Combined with multi-region confirmation and escalation policies, you catch the failures that status-code-only monitoring misses.
A 200 is a starting point, not a finish line.
Originally published on DevHelm.
Top comments (0)