The email arrives on a Tuesday: version one of the extraction API will be retired in ninety days, please migrate to version two. The integration team reads the migration guide, finds that every field they consume still exists under the same name and type, updates a base URL, runs the contract tests and ships. Everything passes. Nothing in the response shape changed.
Three weeks later, accounts payable notices that invoice dates from one European supplier are landing a month off. Version two normalizes ambiguous day-month dates using the document’s detected locale; version one used the tenant’s. Around the same time, the auto-approval rate on low-value invoices climbs by a few points, because the new version’s confidence scores run higher on the same pages and the threshold the team tuned last year now lets more through. Neither change touched a schema. Both changed what the numbers mean.
This is the part of API deprecation that generic advice misses when the API reads documents. The response of a document API is not a record retrieved from a database. It is a judgment about a page, and a new version can change the judgment while keeping the shape. A buyer who negotiates deprecation terms as if the shape were the whole contract has negotiated the part that was never going to hurt them.
The schema is the smallest part of the contract
Most definitions of a breaking change were written for APIs that move stored data. Removing a field breaks consumers; adding an optional field does not. That rule still holds for a document API, and it covers perhaps half of what can go wrong. The other half lives in the values.
| Change in a new version | What a schema diff shows | Who it breaks |
|---|---|---|
| A field is renamed or removed | An obvious difference. | Every consumer that reads it. This is the case every policy already covers. |
| A new optional field appears | An addition. | Only strict deserializers that reject unknown properties. Usually safe. |
| A classifier gains a new document type | Nothing, if the enum is typed as a string. | Any router with an exhaustive switch and no default branch. |
| Dates, amounts or names are normalized differently | Nothing. | Matching, deduplication and anything keyed on the value. |
| Confidence is recalibrated | Nothing. | Every threshold that decides between automation and review. |
| An unreadable field becomes null instead of absent | Nothing, or a nullable flag. | Code that treats a missing key and a null value as different facts. |
| A different value is chosen when a page carries two candidates | Nothing. | Reconciliation against the source, and any audit that reads the old output. |
Five of those seven rows are invisible to a schema diff, and they are the ones that surface weeks later as a business discrepancy instead of an integration error. That is the first thing a buyer should put in writing: a definition of breaking that includes value semantics, not just structure.
Pin three versions, not one
A document API usually has three things that can change independently, and a single version number in the URL rarely covers all of them.
- The API version — endpoints, authentication, request parameters, error codes and status semantics. This is what the path segment normally names.
- The output schema version — the shape of what comes back: field names, types, nesting, enums and the rules for null and absent.
- The model or engine version — what fills the shape. It moves most often, and it moves the values in the table above without touching either of the other two.
The question to ask a vendor is which of the three you can pin, and for how long. An API that lets you pin the path but silently upgrades the engine behind it offers a stable contract for the part that was least likely to change. Where the vendor offers a floating alias such as latest, ask whether it is the default, and whether a request that pins nothing is told which versions actually served it. A response that names its own model and schema versions is the minimum you need to diagnose the three-weeks-later discrepancy at all.
How you version models and schemas inside your own platform is a separate design problem, covered in the document AI control plane. The buyer’s version of the question is narrower: what does the vendor expose, and what does the vendor promise not to move under you.
Deprecation and sunset are two different dates
A retirement notice usually collapses two events into one sentence. They are separate, and the IETF has standardized a header field for each.
RFC 9745, published on the Standards Track in March 2025, defines the Deprecation response header field. It carries the date on which the resource was or will be deprecated, and it can be paired with a Link using the deprecation relation that points to human-readable guidance. The RFC is explicit on two points buyers tend to miss: deprecation does not change the resource’s behavior, and deprecation information is a hint that client applications should be able to function without.
The date the resource actually stops responding is a different field. RFC 8594, an Informational RFC from May 2019, defines the Sunset header for it, and RFC 9745 requires that the sunset timestamp is not earlier than the deprecation timestamp. A response carrying both looks like this:
Deprecation: @1798761599
Sunset: Wed, 30 Jun 2027 23:59:59 GMT
Link: <https://vendor.example/migrate-v2>; rel="deprecation"; type="text/html"
The practical value is not the header itself; it is that a deprecation signal carried on every response can be logged, counted and alerted on by the system that makes the calls, instead of living in an inbox that belongs to whoever signed the order form. Ask whether the vendor emits these signals, and on which responses. Then ask the question the headers cannot answer: after the sunset date, what does a request to the old version get? An explicit error is recoverable. A silent reroute to the new version is the worst outcome available, because the integration keeps working and the values quietly change.
The parallel run is where the migration actually happens
A notice period is only useful if both versions can be called during it. The window that matters is not the time between announcement and sunset; it is the time during which the old and the new version both answer, on the same tenant, for the same documents.
That window is where the value-level changes become measurable. Replay a fixed set of documents with known answers through both versions and diff the outputs field by field, not document by document. A document-level diff says “something changed on 14% of invoices”; a field-level diff says the invoice date moved on the suppliers whose dates are ambiguous, which is a sentence someone can act on. The fixed set has to be one you own and can reproduce, which is the argument for owning the ground-truth dataset rather than borrowing the vendor’s benchmark.
Two outputs of the replay deserve their own attention. The distribution of confidence scores on the same pages tells you whether every threshold needs re-tuning before cut-over. And the fields that go from populated to null, or the reverse, tell you whether downstream code distinguishes “not on the page” from “not legible” the way the new version does.
The checklist
None of this requires the vendor to adopt any particular retirement window. It requires the terms to be written down, testable and specific to a document API.
- A written definition of a breaking change — covering value semantics, normalization, enum sets, null handling and confidence calibration, not just field names and types.
- Independent pinning — of the API, the output schema and the model, with each response naming the versions that produced it.
- A minimum notice period in the contract — stated separately for deprecation and for sunset, and not shortened by a change of ownership or a model provider retiring its own version.
- Machine-readable signals —
DeprecationandSunsetheaders, or an equivalent the vendor documents, on the responses your system actually receives. - A parallel-run window — both versions callable on the same tenant, long enough to replay your own document set and re-tune thresholds.
- A migration artifact — a release note that separates compatibility, migration steps and deprecations, and a field-level mapping when anything moves.
- A stated behavior after sunset — an explicit error, never a silent reroute to a newer version.
The shape of a useful release note is worth asking to see before signing. The Cogneris release notes, for instance, record impact, compatibility, migration, deprecations and rollout as separate fields on every entry, so a reader can tell “nothing to do” from “nothing was said”. Whatever the vendor, a changelog that mixes features and breaking changes in one paragraph will be read by someone skimming for features.
What you owe the vendor back
A deprecation policy binds both sides. A vendor can promise not to remove a field; it cannot promise that your code tolerates a field it has never seen, and a consumer that fails on additions turns every compatible release into a breaking one.
The consumer side of the bargain is short. Ignore unknown properties rather than rejecting them. Give every switch on a document type or a status a default branch that routes to review instead of throwing. Log the deprecation signals your calls receive and put the next sunset date on a dashboard someone looks at. And decide in advance what happens to outputs you already stored under the old version: documents extracted last year keep last year’s shape and last year’s semantics unless someone reprocesses them, and an audit that compares a 2025 record with a 2027 record needs to know which version produced each.
That last point is the one most often left out of the migration plan, because it is not a code change. It is a data decision, and it belongs in the same document as the cut-over date.
Where this sits next to the other contracts
This checklist is about the buyer’s leverage over a vendor’s retirement of a version. Neighbouring problems have their own answers. Receiving events safely — signatures, retries, replay and subscribing to versioned event types — is the webhook callback contract. Versioning the ingestion layer you run yourself, and keeping the contract version separate from the format adapters, is the document ingestion contract. Deprecation policy as one component of an internal data contract, with an owner and a registry, is covered in data contracts for agentic AI. And the coordinate convention on bounding boxes, which is its own versioned promise, is treated in coordinates as contract.
A retirement date is a promise you can test
The version-one email is not the problem. Versions have to retire, and a vendor that never retires anything is a vendor carrying every old decision forward at your expense. The problem is a notice that treats the migration as a change of address, when for a document API it can be a change of meaning.
Written down properly, the terms are all testable: the definition of breaking can be checked against a replay, the pins can be checked against the version each response names, the headers can be counted in your own logs, and the parallel window can be measured in days during which both versions answered. A buyer who holds those four things does not need to trust the email. They can measure the migration before it happens, which is the only point at which measuring it is cheap.
