# Versioning & deprecation

Versioning

# The path prefix is the contract

Within /v1, changes are additive. Anything that would break a parser ships as a new version path, and anything slated for removal is announced and carries Deprecation and Sunset headers for at least 90 days before it goes.

## /v1 only gains

The machine-readable contract is regenerated from the endpoint registry at [`/openapi.json`](https://www.monocrawl.com/openapi.json) and [`/openapi.yaml`](https://www.monocrawl.com/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.

## 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.

## Announced, signalled, then removed

An endpoint or field slated for removal is announced on the [changelog](https://www.monocrawl.com/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. |

**a deprecated endpoint, before its sunset date**

```
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.

**the same endpoint, after its sunset date · 410 gone**

```
{
  "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",
    "status": 410,
    "doc_url": "https://www.monocrawl.com/docs/errors#endpoint-not-found",
    "details": {
      "guidance": {
        "field": "endpoint",
        "accepted_values": null,
        "example": {
          "method": "GET",
          "path": "/v1/utility/endpoints"
        },
        "action": "This endpoint was retired. Use the replacement listed in this response or select a current endpoint from the catalogue."
      },
      "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.

## 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.
