Technical

Keep Deprecated API Examples out of Current Guidance

Maintain versioned API examples with clear lifecycle notices, explicit migration steps and tested contract boundaries while preserving useful historical documentation.

By Jia Chen

Published

Sources checked

Keep current examples on the current implementation path, label older examples with their version and lifecycle, and provide an explicit migration guide when behavior changes. Preserve useful documentation for a still-supported old version instead of silently rewriting its meaning or redirecting developers to an incompatible new contract.

The goal is to prevent someone from following an old request as if it were current. That applies to developers arriving from search, support links, copied snippets or an AI assistant. Clear versioning improves the available evidence; it does not guarantee that every answer system stops citing historical material.

This guide uses a fictional two-version event API and a runnable in-memory contract example. It does not call a real service, implement authentication or claim to test a production migration.

Separate documentation age from compatibility

An old publication date does not necessarily make a page wrong. A version-one guide can remain correct for clients that still use version one. A recently updated page can still contain an incompatible command copied from an older release.

Review the example against its intended contract, not its age alone. Record the version and support status explicitly:

LifecycleWhat the reader should understand
CurrentPreferred version for the stated use case and new integrations
Supported older versionStill usable within its documented support conditions
DeprecatedMigration is advised; the notice explains scope and timing
RetiredThe documented service behavior is no longer offered; historical context remains labeled

These are editorial labels to apply according to the product's actual policy. They are not a universal promise about how long every API remains available.

GitHub's version documentation gives a concrete example of explicit version selection, breaking-change guidance and testing when upgrading. Its version header and support terms are GitHub-specific. Use your own service's actual mechanism and policy rather than copying those details indiscriminately. GitHub REST API versions

Inventory where the old contract appears

A deprecated example may live outside the API reference: an onboarding email, a blog tutorial, an SDK README, a help-center answer, a comparison page or a copied command in a product screen. Start with the places your team controls and the routes users actually follow.

Use a compact inventory:

FieldPurpose
Page or repository pathLocate the example precisely
Product and contract versionEstablish what behavior it describes
Current lifecycle statusDistinguish old-supported from retired
Entry linksIdentify where current users encounter it
Dependent code or screenshotsFind artifacts affected by the same change
Owner and review triggerMake maintenance actionable
Intended dispositionUpdate, retain with notice, replace or archive

Inspect incoming links before changing URLs. A current quickstart that sends readers to an older authentication page can make a correct historical page look like incorrect current guidance. Sometimes the repair belongs in navigation rather than in the old article itself.

Do not erase a migration example simply because it contains an old field name. That field may be necessary to show what changes. The important question is whether the reader knows which side of the migration it belongs to.

Make the breaking change concrete

Our fictional Example Events API changes both request and response fields between v1 and v2. The intended business operation remains accepting an event for later work.

The v1 request is:

{
  "event_type": "workspace.created",
  "payload": {
    "workspace_id": "ws_example_001"
  }
}

The v2 request is:

{
  "name": "workspace.created",
  "properties": {
    "workspace_id": "ws_example_001"
  }
}

In this example, changing the path from /v1/events to /v2/events without changing the body fails validation. The migration guide must therefore describe both changes. A redirect or a new URL alone cannot translate an incompatible payload.

Responses also change:

VersionAcceptance response
v1receipt_id with state set to queued
v2event_id with status set to accepted

The two states have the same limited meaning under this fictional contract: accepted for later work. Neither means delivered. A real migration must establish whether the semantics are genuinely equivalent rather than assuming that renamed fields preserve behavior.

Document changes to authentication, validation, limits and failure handling as well as field names when they occur. GitHub's version guide lists several kinds of breaking changes, illustrating why a migration review needs more than a search-and-replace of the endpoint string. GitHub version-change guidance

Write the migration as an explicit transformation

For the toy contract, the mapping is:

Request:
  event_type -> name
  payload -> properties

Response handling:
  receipt_id -> event_id
  state: queued -> status: accepted

Endpoint:
  /v1/events -> /v2/events

The downloadable example validates the complete v1 shape before constructing v2. It rejects unknown top-level fields rather than silently dropping data it does not understand. It also deep-copies the nested payload so modifying the new representation need not mutate the old object.

Those are fixture design choices. A real API may permit additional fields or use a different transformation. The migration document should state how unknown, optional and newly required values are handled, including any information that cannot be mapped automatically.

Show the changes next to a complete example, not only in a diff. A reader implementing v2 from scratch needs the final request; a reader upgrading v1 needs the relationship between the two.

Give supported old pages a visible notice

A historical page should identify its version near the title and near version-sensitive examples. A clear fictional notice could say:

This page describes Example Events API v1. The version is deprecated but remains supported under the example's published lifecycle. New integrations should use v2. Existing integrations must update the endpoint, request fields and response handling using the migration guide.

If there is a verified retirement date, include it and explain the expected behavior after that date. If there is no scheduled retirement, say so rather than inventing urgency.

Link the notice to the current documentation and the migration guide with distinct anchor text. They serve different tasks: one describes the destination, the other explains how to get there. Keep the old example readable for users maintaining that version.

The documentation page-types guide helps keep the current reference, tutorial and migration guide from becoming confusing duplicates. The context-preservation guide explains why version scope belongs beside instructions, not only in a distant banner.

Distinguish deprecation from sunset

Deprecation communicates lifecycle information and encourages migration. It does not, by itself, rewrite the resource's behavior or turn an old endpoint into a redirect. RFC9745 defines the Deprecation response header using a Structured Fields Date. RFC8594 defines Sunset using an HTTP-date to signal anticipated unavailability. Deprecation header specification and Sunset specification

The fictional fixture includes this metadata for v1:

Deprecation: @1788220800
Sunset: Mon, 01 Mar 2027 00:00:00 GMT
Link: <https://example.com/migrations/events-v2>; rel="deprecation"

The illustrative deprecation date is September 1, 2026, and the illustrative sunset date is March 1, 2027. These are invented schedule values, not dates for a real API. The example.com link is a reserved-domain example.

The fixture returns these values as an in-memory response object. It does not send actual HTTP headers, operate a clock-based retirement system or make v1 stop working on that date. A production service must implement and verify its declared lifecycle separately.

Vendor behavior can differ from a newer standard's syntax. The GitHub page inspected for this guide describes an HTTP-date value for its Deprecation header, while RFC9745 defines the Structured Fields form shown above. Treat those as distinct documented conventions. Do not claim that copying our fixture necessarily matches GitHub's current wire response.

Run the local migration checks

Download version-migration-example.mjs, inspect it, then run:

node version-migration-example.mjs

The recorded runs used Node 23.11.0 and Node 24.19.0, each passing 16 assertions. There are no dependencies to install, credentials to supply or external services to contact. The script exercises local functions that represent request validation and response shapes.

The checks establish:

ScenarioFixture result
Valid v1 body on v1Accepted
Unchanged v1 body on v2Rejected as incompatible
Explicitly mapped body on v2Accepted
v2 body on v1Rejected as incompatible
Unknown v3 pathNot found
Unknown v1 fieldMapper rejects the input
Invalid name or payload shapeMapper rejects the input
Supported deprecated v1Response remains accepted with lifecycle metadata
Nested payload mappingValue preserved through a separate copied object

Other assertions check the exact lifecycle date formats, response state names and absence of a Location redirect field. The output prints both old and migrated requests so the transformation can be inspected.

This is contract-example evidence, not a real migration of persisted events or customer traffic. It does not test distributed compatibility, network behavior, authentication, rollback or every schema edge case. Do not describe passing these assertions as production migration readiness.

Update the current reader path as one change

When moving current guidance to v2, review the overview, getting-started links, API reference, SDK examples, tutorials and troubleshooting destinations together. A new current page linked from an outdated sidebar is an incomplete release.

For each current example, ask whether the endpoint, body, response parser and version label agree. Check copied examples in repository READMEs and resource articles as well as the central docs. A code snippet whose response parser still expects receipt_id will fail after the request has already been migrated to v2.

Run the example from its stated prerequisites. The integration tutorial guide covers that clean-start verification. Use the error documentation guide to explain the incompatible-contract error instead of leaving readers with an unexplained validation response.

Preserve the release record: what changed, which versions were tested, which historical pages remain, and who owns unresolved examples. An updated date should reflect substantive maintenance, not substitute for it.

Handle redirects and removals by meaning

A moved page with the same meaning can have a relevant redirect. A v1 instruction and an incompatible v2 instruction are not equivalent merely because they describe similarly named operations.

Do not automatically redirect the old API endpoint to the new one when clients need to change payloads or permissions. Do not redirect a still-useful historical documentation URL to an unrelated current homepage. Choose the disposition according to the actual service and reader contract.

When a version is retired, retain a clear explanation of the retirement and migration path where useful. Whether the old service returns 410, another documented error or a compatibility response is a product/API decision. Do not invent that behavior because a documentation template expects it.

Historical pages can remain useful for debugging stored integrations, understanding release notes or planning upgrades. Label their status and prevent current navigation from presenting them as the recommended starting point.

Review questions for versioned examples

Age alone is not a sufficient reason. Determine whether the page still supports a legitimate reader task and whether its version is clear. Search visibility and answer citations require separate observation; deleting context does not guarantee that external copies disappear.

Is an update date enough to show the current version?

No. Name the API contract or package version near the instruction. A recent editorial date cannot tell a developer which payload schema the example uses.

Can an automated migration rewrite every example?

It can propose changes, but verify the request, response handling and intended behavior. A field rename may be straightforward; a changed permission model or asynchronous outcome can require product judgment. Preserve cases that cannot be transformed safely.

What is the most useful maintenance test?

Run the documented path for each version you claim to support and check the expected results. Keep explicit negative tests for incompatible combinations. That demonstrates the boundary instead of relying on a banner that says the versions are different.

Sources and verification

Sources checked September 17, 2026: GitHub REST version guidance, RFC9745 Deprecation and RFC8594 Sunset. The Example Events versions, fields and lifecycle dates are original fictional teaching data. Sixteen local assertions passed on Node 23.11.0 and Node 24.19.0; no production migration, network API or real retirement schedule was tested.

Explore GEO with Jam

See how Jam approaches AI visibility research and content improvements for developer-tool teams.

Explore Jam for GEO