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.