The drift report
The question the subscription is for: what does my API do that my contract does not say?
One row per shape of disagreement, however many million times it
happened. "POST /pets rejected because name is missing" is one row
with a counter, not a million rows - which is both what makes the
report readable and what makes it affordable.
What a row is
A fingerprint: the operation, the response status, the schema
pointer, the failing keyword, and the spec version it happened under.
Array indices in the pointer are collapsed, so /items/3/sku and
/items/4/sku are one bug rather than five hundred.
No value from your payload is ever part of that key. Keys travel to us, are stored, indexed and displayed; nothing derived from your customers' data belongs in one. A single redacted example is kept beside the row instead - see What leaves your network.
Windows
Three, one click each:
- Since Friday - 18:00 on the last Friday that has passed. Not midnight: Monday's question is about what shipped on Friday afternoon.
- 24 hours - the default.
- 7 days.
The window decides three things at once: what counts as new (a fingerprint first seen inside it), what the rate is measured over, and which rows are "active" rather than "seen before, quiet in this window". Nothing is hidden by narrowing the window - quiet rows move to their own table rather than disappearing, because a problem you stopped seeing is not a problem you fixed.
Rates, not counts
Each row shows occurrences per 1,000 requests through the proxy, using the request metering the gateway already ships.
This matters more than it sounds. Four thousand violations is a catastrophe on four thousand requests and a rounding error on forty million, and a count without its denominator has caused more bad deploys than it has prevented. Where no metering has arrived for the window, the report says so instead of showing a bare number.
The order
New drift first, then by volume.
A problem that started this morning outranks one the team triaged a month ago and decided to live with, however much louder the old one is. The alternative - sorting purely by volume - turns the page into a leaderboard for problems everybody has already agreed about.
The sparkline
The last 48 hours, hourly, scaled to that row's own peak. The question each line answers is "is this one getting worse", so a shared scale would be the wrong choice: it would flatten every row that is not the loudest into a straight line.
An empty report means two things
Your API conforms, or nothing has been looked at. Those are opposite situations and an empty page renders them identically, which is why Coverage is a page rather than a footnote. Read it before you trust a quiet report.
From a terminal
apip violations 42 --since friday
apip violations 42 --operation createOrder --json
See The API and the CLI.