Why Most API Abuse Looks Valid at First
Why Most API Abuse Looks Valid at First
There’s a comforting mental model of an attack: someone tries to get in, fails a check, and gets blocked. A wrong password. An invalid token. A request that doesn’t match the schema. The system says no, and that’s the end of it.
Most of the API abuse that actually hurts doesn’t look like that.
The requests that cause real damage usually pass every check you put in front of them. They authenticate successfully. They carry valid tokens. They match the schema. They stay under the rate limit. By every measure your gateway cares about, they are normal traffic — right up until you realize they weren’t.
This is the gap that defines modern API security, and it’s worth understanding clearly, because it changes what “detection” even means.

The request layer tells you less than you think
Most API security lives at the request layer. A request arrives, and a series of questions get asked about it in isolation:
- Is this authenticated?
- Is the token valid and unexpired?
- Does the body match the expected schema?
- Is this IP within its rate limit?
These are good questions. They catch a lot. But notice what they have in common: every one of them can be answered by looking at a single request, on its own, with no memory of what came before.
That’s exactly the property an attacker exploits. If the only thing standing between them and your data is a set of per-request checks, then the move is simple — make every individual request look fine. The abuse doesn’t live in any single request. It lives in the pattern across many of them.
Three attacks that pass every check
It’s easier to see this with concrete examples. None of these involve a malformed request or a failed login.
Credential stuffing that never trips a rate limit
An attacker has a database of leaked username and password pairs and wants to know which ones still work on your platform. The naive approach — thousands of attempts from one IP — gets blocked instantly. So they don’t do that.
Instead, the attempts are spread across residential proxies, so no single IP looks busy. The pace is throttled deliberately to stay under your thresholds. Each request to POST /api/v1/auth/login is structurally valid and passes schema validation. The timing mimics normal human logins.
Every request, on its own, is indistinguishable from a real user signing in. The attack only becomes visible as a shape over time: a slow, steady rise in failed authentications, the same credentials tested across many accounts, login patterns drifting away from normal timing and geography, and unusual spikes in token issuance once some credentials hit.
A stolen token that’s perfectly valid
An attacker gets hold of a real JWT — leaked in a log, intercepted, pulled from a compromised client. They start using it.
Here’s the uncomfortable part: the signature is valid, the token hasn’t expired, and every request it makes is authenticated. Your system trusts it, because it passes exactly the checks token validation was designed to perform.
So the token starts doing things:
GET /api/v2/user/profile
POST /api/v2/payments/initiate
The requests go through. Validation was never the question. The real signal is in how the token behaves — the same token active in two distant locations minutes apart, accessing services it has never touched, jumping into a payment flow with no prior history, with request timing that doesn’t match the real user it was issued to. Each request is individually legitimate. The behavior, taken together, is not.

Scraping that imitates a human
An attacker wants to extract a large catalog through GET /api/v1/products and GET /api/v1/search. A burst of requests would trip every alarm, so they go low and slow: requests distributed over time, IPs rotated, pacing that mimics human browsing, always staying under the rate limit.
The traffic looks valid, authenticated, and operationally normal. What gives it away isn’t volume — it’s the behavioral fingerprint: methodical endpoint traversal, excessive pagination, repetitive sequences that no real user would produce, sustained over far longer than any genuine session.
The common thread: valid is not the same as safe
In all three cases, the same thing is true. Authentication succeeded. The schema validated. The rate limit held. And something harmful happened anyway.
The lesson isn’t that per-request checks are useless — they’re necessary, and they stop a great deal. The lesson is that they answer the wrong question for this class of problem. They ask “is this request valid?” The question that actually matters is “is this pattern of valid requests normal?”
That second question can’t be answered one request at a time. It needs context: what this token, this key, this client usually does, and whether what it’s doing now departs from that.
What this means for detection
Once you accept that the signal lives in behavior rather than in individual requests, two things follow.
The first is that you have to watch behavior over time, not just inspect traffic as it passes. A credential-stuffing campaign is a trend in failed logins. A stolen token is a key acting out of character. Low-and-slow scraping is a traversal pattern that outlasts any real session. You only see these by comparing what’s happening now against what normally happens.
The second — and this is where a lot of tools go wrong — is that watching behavior does not require an unexplainable model deciding what’s suspicious. It’s tempting to reach for a black box here: feed it traffic, let it flag anomalies, trust the score. But “anomaly detected, confidence 0.87” is close to useless at 3am. It doesn’t tell you what changed, why it matters, or whether to get out of bed.
A behavioral signal can be a rule you can read. “This key is hitting an endpoint it has no history with.” “Failed-auth rate for this endpoint has climbed past its normal band.” “This token is active from two locations at once.” These are inspectable. You can tune the threshold. And when one of them fires, it can tell you exactly what tripped it and why.
That’s the approach behind APIGuard: deterministic detectors built around behavior, each mapping to a threshold you can read and adjust — so that when an alert pages you, it arrives with the severity and the reason already attached. Not a model’s verdict you have to take on faith. A rule you could have written yourself, watching the thing you’d want watched.
The takeaway
If you run APIs in production, the most dangerous traffic you’ll face this year probably won’t fail a single check. It’ll authenticate, validate, and stay within limits — and the only thing marking it as abuse will be the shape of its behavior over time.
Catching it means shifting the question from “was this request valid?” to “is this behavior normal?” — and answering that question in a way you can actually read, tune, and trust when it wakes you up.
APIGuard watches your production APIs for abuse, anomalies, and outages and sends one trustworthy alert per real problem — with the severity and the reason attached. Every alert traces to a deterministic rule you can read, not a black box. It’s early, and we’re opening access to the first teams now. If you run APIs in production and you’re tired of alert noise, get in touch.