Within a version
/v1 only gains
The machine-readable contract is regenerated from the endpoint registry at /openapi.json and /openapi.yaml. It documents every operation with parameters, credit cost and an x-live-proven flag derived from real upstream evidence, where proof is available. A registered operation can still be unavailable; this is historical evidence, not a live health guarantee. Within the version, our compatibility policy is:
Fields are only added
Our compatibility policy is to retain documented envelope fields and parameter contracts within /v1. New keys can appear at any time; parse defensively and ignore what you do not use.
Parameters are only added
New optional query parameters arrive with a default that preserves the previous behaviour. A required parameter is never introduced to an existing endpoint.
Errors are only added
The error envelope keeps its shape; a new error type may join the list on the errors page, so branch on the types you handle and treat the rest generically.
Values are the platform’s
What a platform publishes is outside the contract. An unavailable source field may be null or absent, depending on the endpoint — the honest-null policy on Responses & schemas — and that is not a schema change.
Across versions
Breaking changes get a new path
Renaming a field, removing one, changing a type, or changing what a parameter means is a breaking change, and none of it happens under /v1. It ships as a new version prefix — /v2/{platform}/{endpoint} — while /v1 keeps answering exactly as before. The old version is then subject to the deprecation policy below, endpoint by endpoint, rather than switched off.
The compatibility test suite rebuilds the OpenAPI document from the registry and compares it with a committed baseline: a removed path, method, parameter or envelope field, a parameter that became required, or an error type that disappeared fails that suite until the baseline is deliberately updated in the same change, which leaves a written record of every exception. This is a separate release check, not part of the Next.js build itself, and it does not prove every upstream payload field is unchanged.
Deprecation
Announced, signalled, then removed
An endpoint or field slated for removal is announced on the changelog with a removal date at least 90 days out. From the announcement until that date, every direct /v1 response for the endpoint carries three headers, in the formats generic HTTP clients already recognise:
| Header | Format | Meaning |
|---|---|---|
deprecation | @{unix seconds} (RFC 9745) | When the deprecation was announced. |
sunset | HTTP-date (RFC 8594) | The first moment the endpoint will answer 410. |
link | rel="deprecation", rel="successor-version" | Where it was announced and, when there is one, the operation to call instead. |
HTTP/1.1 200 OK content-type: application/json deprecation: @1798761600 sunset: Thu, 01 Apr 2027 00:00:00 GMT link: <https://www.monocrawl.com/changelog#2027-01-01>; rel="deprecation", <https://www.monocrawl.com/v1/demo/search>; rel="successor-version"
On the sunset date the endpoint is removed. It does not become a 404 — a path that used to work and now says it never existed is the worst outcome for a parser — but a 410 in the standard error envelope, with the successor and the announcement in details. Like every error, it costs 0 credits.
{
"success": false,
"error": {
"type": "ENDPOINT_NOT_FOUND",
"message": "demo/legacy-search was retired on 1 April 2027 — call /v1/demo/search instead. See https://www.monocrawl.com/changelog#2027-01-01.",
"status": 410,
"doc_url": "https://www.monocrawl.com/docs/errors#endpoint-not-found",
"details": {
"reason": "endpoint_removed",
"successor": "demo/search",
"changelog": "/changelog#2027-01-01"
}
},
"credits_used": 0,
"request_id": "req_9c2e41a7d0b35f8e16"
}Catalogue ids that were never wired are not covered by this policy: they answer 501 ENDPOINT_NOT_AVAILABLE today and may be renamed or dropped before they are built, since nothing can depend on them yet.
Right now
Currently deprecated
Nothing. No /v1 endpoint carries a deprecation header today. This sentence is read from the same list the router consults, so it changes the moment that does.