You keep one saved request in your API client for the create-order flow. You open it, hit send against the local mock, see a 200, and move on. A week later that same request against staging comes back 400. The field was renamed, one new required field appeared, and the enum you still send moved to a new value — the mock accepted every one of it anyway.

This drift hides behind a comfortable green. The example request was typed by hand months ago, the mock was recorded once and never regenerated, and neither one is checked against the current spec. So local replay proves only that the mock is generous, not that the payload matches the operation.

Agents make this faster: asked to test an endpoint, they grab the last body in history, replay it against the mock, report success, and never diff that body against the schema on disk. The reported green carries no evidence that the field names, required set, and enum still match.

Why a stale example reads as correct

  • The mock accepts whatever you send. Most recorded fixtures return a fixed body regardless of the request; they do not validate the incoming payload against the schema, so a removed field or a missing required field never surfaces.
  • The response still looks plausible. A recorded 200 with a similar body reads as proof the call works, even when the request shape has moved away from the operation.
  • The example lives outside version control. Saved requests in a client, ad hoc fixtures, and pasted curl samples are not part of the repo, so a spec change never reaches them and nobody diffs them on merge.
  • You replay against the mock, not staging. Local green feels like coverage, but the mock enforces none of the validation the deployed backend runs.
  • Small schema edits feel cosmetic. A rename, a required flag flip, or an enum value change rarely looks worth updating every saved sample, so the sample keeps sending the old shape.

What request and mock drift look like in practice

  • The saved body sends a field the spec removed. The backend ignores or rejects it; the mock does neither and returns 200.
  • A new required field is missing. The operation now demands it, but the hand-written example predates the field, and the mock does not enforce requiredness.
  • An enum value changed but the example still sends the old one. The mock echoes the old value back; the live endpoint returns a validation error.
  • The mock returns a recorded response from a prior schema. It omits a field the contract now promises or keeps a field the contract dropped, so a consumer writing against that example inherits the drift.
  • The path or method drifted. The saved example targets the old route while the spec moved the operation to a new path; the mock may even be pinned to the old URL and never notice.

The gate: derive the example, regenerate the mock, validate before replay

  • Generate the example body from the spec operation instead of hand-typing it. A sample built from the current schema picks up renames, required fields, and enum values on its own; a saved JSON block does not.
  • Regenerate the mock when the spec changes. A recorded fixture frozen at v1 keeps passing regardless of v2; regenerating it from the schema keeps the response honest and the validation live.
  • Validate the outgoing payload against the schema before you replay it. A short local check that the request body matches the operation's defined parameters and request body catches the missing required field or stale enum before it reaches any server.
  • Replay a representative request against staging on change, not only against the mock. The mock proves format convenience; one real call against an environment that enforces the contract proves the payload still lands.
  • Keep the spec the source of truth locally. When the OpenAPI file is what generates both the example and the mock, a contract edit propagates to both instead of leaving hand-maintained copies that quietly age out. That is the local-first workflow we built around in Powerduck — keep the spec on disk, generate from it, and stop trusting the saved sample.

Before you call a replayed request working

  1. Does the body come from the current spec operation, or from a block typed by hand long ago?
  2. Is the mock regenerated from the schema, or a fixture recorded once and frozen?
  3. Was the outgoing payload validated against the schema before replay?
  4. Has one representative request actually hit an environment that enforces the contract?

Green against a generous mock only proves the mock accepted your payload. Generate the example from the spec, regenerate the mock on change, validate before replay, and let the contract — not the saved sample — decide what correct looks like.