The API versioning decision record: why the versioning strategy you chose determines your backward compatibility window and your client migration cost
The API versioning strategy is chosen the day the API is first published. Someone adds /api/v1/ to the route prefix — or, after a brief discussion about REST purity, decides not to version the URL at all and to handle version negotiation via headers — and the decision is made. The backward compatibility commitment, the deprecation enforcement model, the client identification approach, and the migration cost framework are not written down because they feel like operational details that will be worked out when the time comes. The time comes when a product decision requires a breaking change to the API's resource model. At that point the team discovers that "when the time comes" is not a versioning strategy: nobody wrote down what backward compatible means, nobody wrote down how long the compatibility window lasts, nobody built a way to identify which clients are calling which version, and the migration guide and the deadline that were published with v2 are now eighteen months old with 30% of integration partners still on v1 and no mechanism to determine who they are or how to reach them.
The API versioning decision record makes the versioning scheme, the backward compatibility commitment, the breaking change classification, the client identification model, and the deprecation enforcement trigger explicit before the team is managing three simultaneous API versions with no documented basis for retiring any of them. This is not a record for API consumers — the changelog and migration guide serve that audience. This is the record that allows the engineering team, the product team, and the partner success team to answer a different set of questions: what did we commit to when we said "v1 is supported for twelve months," how do we know when it is safe to shut down v1, who is authorized to decide that the remaining v1 traffic is acceptable to break, and what does the next version require before it can be launched.
Two things that happen when the decision is not written down
The version that was never retired
A 45-person B2B SaaS company launched its public API with URL versioning at /api/v1/ — the obvious choice, made in a 20-minute design meeting, never written down as a decision with explicit reasoning. The v1 resource model used nested objects where the engineering team later determined flat attribute arrays would be more performant and easier to paginate. The company launched /api/v2/ fourteen months after v1, with a published migration guide, a documented list of breaking changes (three field renames, one nested-to-flat restructure, one authentication parameter change), and a blog post announcing a six-month migration deadline.
No documentation recorded what the backward compatibility commitment actually was for v1 — whether the six-month window was a firm shutdown date or a soft target. No documentation recorded whether the compatibility commitment applied equally to all clients or whether enterprise integration partners with contractual SLAs had a different commitment window. No documentation recorded how clients would be identified: the API gateway logged requests, but the logs used API key IDs as the client identifier, and the mapping from API key ID to customer name, customer contact, and customer technical stack was in the customer database, not the log aggregation system. Identifying which clients were still calling v1 required a join across the API gateway logs, the API key table, the customer account table, and the partner success CRM that stored whether a customer had enterprise integration support — a join that nobody had built and that required four engineering-hours to construct each time it was needed.
Six months after the v2 launch, the v1 deprecation deadline passed. The partner success team had reached out to the clients identified in the initial log join, but 30% had not responded to deprecation notices and were still generating v1 traffic. The engineering team proposed enforcing the deadline by returning HTTP 410 on v1 endpoints. The product team pushed back: several of the still-on-v1 clients were in contract renewal conversations, and breaking their integrations during a renewal cycle was commercially risky. The partner success team pushed back: the clients who had not responded to deprecation notices might not have received them — the email addresses in the CRM for some integration partners were technical contact addresses that had changed with staff turnover. The six-month deadline became an eight-month deadline became a twelve-month deadline became a standing commitment to keep v1 alive until the remaining traffic dropped below an undefined threshold. Eighteen months after the v2 launch, v1 was still receiving 12% of API traffic. The team had since designed v3 to address additional resource model problems, but the prospect of maintaining three simultaneous versions — each requiring its own authentication middleware, its own test suite validation, and its own mention in every change review — had stalled the v3 launch for six months while the team debated whether v1 could be retired first.
The versioning scheme that became the wrong choice
A 20-person developer-tools company built an internal API that was initially consumed only by their own frontend and three internal microservices. An engineering lead who had strong opinions about REST API design argued against URL versioning: embedding the version number in the URL conflates the resource identity with the implementation version, he explained; the resource /users is the same resource regardless of which version of the API is serving it, and URL versioning creates the false impression that /v1/users and /v2/users are different resources. The team adopted a custom request header approach: clients included an X-API-Version: 2 header, and the API router dispatched to the appropriate handler based on the header value. For the frontend and internal services — all written by the same team, all deployable in a single afternoon — this worked. The version was just a string in a request configuration object.
The API was opened to external developers eighteen months later. The API documentation showed request examples with the X-API-Version header. The generated OpenAPI specification included the header as a required parameter. The problems arrived within the first month of external access. The Postman collection that external developers expected to import and use immediately required manual header configuration for every request. The Python SDK generated from the OpenAPI spec included the header as a required argument to every method call, which was unusual enough that a support ticket was opened asking whether the header was really required or whether a sensible default would be selected. The curl examples in the documentation required the -H "X-API-Version: 2" flag on every command — easy to miss when copying examples for quick testing. The company's own log aggregation, which had been built to filter requests by URL path, could not easily segment traffic by API version: all requests went to /api/users regardless of which version they were calling, and version breakdown required parsing request headers from the raw log format.
Eight months after external access opened, the team added URL versioning for v3 — not because v3 required a breaking change, but because the header-based versioning scheme was generating a disproportionate share of developer support tickets and the log routing problem had prevented them from building the version-specific usage dashboards they needed for the deprecation decision. The original decision — the philosophical reasoning behind header versioning and the specific operational risks it overlooked for an externally-consumed API — was never written down. The v1 and v2 header-versioned endpoints remained live alongside the v3 URL-versioned endpoint, and new engineers joining the team were confused about why there were two versioning schemes in the same API. The technical debt of the mixed versioning model was invisible to anyone who had not been present for the original design discussion.
Both outcomes share the same root cause: the versioning strategy was chosen quickly and never documented with the reasoning that would have made later decisions tractable. The B2B SaaS company's deprecation problem was not that they chose URL versioning — URL versioning was the right choice. The problem was that they never wrote down what the backward compatibility commitment meant, so every enforcement decision was a fresh negotiation. The developer-tools company's mixed versioning problem was not that they chose header versioning for internal consumers — header versioning worked fine for the original use case. The problem was that they never wrote down the assumption that the API would always be consumed by internal clients under the team's own control, so when that assumption broke, the operational implications of the header-versioning choice were discovered through user friction rather than through design review.
Three structural properties that are set at versioning strategy selection time
1. The backward compatibility commitment and its concrete scope
The backward compatibility commitment is the claim the API team makes to clients about what will not change across minor updates. In the absence of a written commitment, the de facto commitment is whatever clients have come to depend on — which may include undocumented fields, response ordering behavior, error code formats, and authentication edge cases that the team would prefer to change but cannot because changing them would break clients who depend on the current behavior. The undocumented commitment is always broader than the intended commitment and harder to reason about because it is defined by client behavior rather than by the API team's explicit design.
The backward compatibility commitment has four concrete dimensions that should be documented explicitly. The first is the field stability commitment: which fields in request and response objects are part of the stable contract (cannot be removed or renamed without a version increment) and which are experimental or internal (may change or disappear without a version increment). Most APIs treat all documented fields as stable, but the distinction between documented fields and undocumented fields — fields that appear in responses but are not in the API reference — is frequently not written down, which means clients who depend on undocumented fields experience breaking changes that the API team did not classify as breaking. The second dimension is the behavior stability commitment: which behaviors are guaranteed (the pagination cursor returned on page N can be used to retrieve page N+1 at any point within the session; the ordering of results within a page is stable for the same query parameters) and which are implementation details that may change. The third dimension is the error response stability commitment: whether error codes, error messages, and error response shapes are part of the stable contract or can change between minor releases. Error codes are commonly treated as stable because clients write code like if (error.code === 'RATE_LIMIT_EXCEEDED'), but error messages — which are often displayed directly to end users by simple client implementations — are frequently changed without treating them as breaking changes. The fourth dimension is the authentication and authorization stability commitment: whether the authentication model, token format, required scopes, and authorization rules for existing endpoints are stable across minor releases.
The compatibility window — how long the commitment lasts — should be documented for each client category. A startup with a few internal tools consuming the API may need only a 30-day migration window for breaking changes. An enterprise integration partner who has embedded the API in a compliance-validated internal system may need a twelve-month window. A third-party developer who has built a publicly distributed application on top of the API may need indefinite backward compatibility because they cannot control when their users update. Document the client categories and their respective windows explicitly, including what evidence the API team needs to verify which category a client falls into — because if client categorization is not documented, the default is to apply the longest window to all clients, which is the outcome that makes deprecation impossible.
2. The versioning scheme and its operational cost
The versioning scheme — URL versioning, header versioning, content-type negotiation, or no versioning — determines three operational properties that are difficult to change after the API has external consumers: log segment visibility, routing infrastructure complexity, and SDK distribution surface.
Log segment visibility is the ease with which the API team can answer: how many requests per day are we receiving on each version, and which clients are sending them? URL versioning makes version breakdown trivial in any log aggregation system — filter by URL prefix, group by /api/v1/ versus /api/v2/, count. Header versioning requires parsing the request header from the raw log format, which is available in structured log formats (JSON access logs) but requires custom parsing from common formats (Combined Log Format, nginx default). The operational consequence is that version-specific usage dashboards — the dashboards that show whether it is safe to retire a version — are easier to build and maintain on URL-versioned APIs. This is not a reason to avoid header versioning for all APIs; it is a property of the scheme that should be acknowledged in the decision record so that the team knows the log infrastructure requirement that header versioning creates.
Routing infrastructure complexity is the difficulty of implementing version-aware request dispatch in the API gateway or web framework. URL versioning routes requests based on the URL path — a primitive that every API gateway, load balancer, and web framework supports natively. Header versioning routes requests based on a request header — supported by most API gateways but requiring explicit configuration of header-based routing rules, and potentially conflicting with caching infrastructure that caches based on URL rather than header values. The API gateway decision record governs the routing infrastructure; the versioning scheme selection should be made in the context of the gateway's native routing capabilities, not as an independent decision that the gateway must later be configured to support.
SDK distribution surface is the effect of the versioning scheme on SDK clients. A URL-versioned API requires that SDK clients be pointed at the versioned base URL — either as a constructor argument or as a constant in the generated client. When v3 is launched, SDK users update the base URL or install the updated SDK version that has v3 as its default. A header-versioned API requires that SDK clients set the version header on every request — either as a static configuration or as a parameter to every method call. The SDK distribution implication is that SDK users on a header-versioned API cannot switch between versions by changing the base URL; they must change the header configuration, which may not be exposed as a first-class configuration option in generated clients. Document the SDK distribution model explicitly: will the API team publish official SDK packages, and if so, how will SDK versioning align with API version launches? An SDK that ships as api-sdk@2.0.0 corresponding to API v2 makes the alignment clear. An SDK that ships as api-sdk@1.3.0 with an internal default of X-API-Version: 2 obscures the relationship between the SDK package version and the API version it targets.
3. The client identification model and the deprecation enforcement mechanism
Client identification is the capability that makes deprecation enforceable rather than aspirational. Without a mechanism to identify which clients are calling which API version, the deprecation enforcement decision reduces to: "the metrics show that some traffic is still hitting v1 — we can't shut it down because we don't know who it is or what breaking their integration would cost." This is the most common outcome of undocumented API versioning decisions, and it results in indefinite version maintenance because the enforcement trigger is never satisfiable.
Client identification requires three things: a client identifier that is present in every API request (an API key, a client certificate, an OAuth client ID, or a session token that maps to a client record), a mapping from that identifier to the client's metadata (company name, technical contact email, tier, and whether they have a contractual support SLA), and a join capability that allows the API team to answer "which companies are still calling v1" from the API gateway logs without a manual engineering investigation. The client identifier is usually present — most APIs require authentication, and the authentication credential is a client identifier. The metadata mapping is usually available — the customer database has the company name and contact information for authenticated clients. The join capability is the piece that is frequently missing: the API gateway logs are in one system, the customer database is in another, and the join has never been built because there was no operational requirement for it until the deprecation decision created the requirement.
Document the client identification model at the time the versioning strategy is chosen, not at the time a deprecation is being planned. The documentation should specify: what is the client identifier in API requests (API key ID, OAuth client ID, JWT subject), where is the mapping from client identifier to client metadata stored, how can the operations or engineering team query "list all clients calling v1 in the last 30 days with their company name and contact email," and who is responsible for executing that query when a deprecation notice needs to be sent. The logging strategy decision record governs the log format and retention policy; the versioning decision record should reference the specific log fields that carry the client identifier and confirm that those fields are present in the retained log format used for the client identification query.
The deprecation enforcement mechanism is the technical implementation of what happens when the shutdown date is reached: what HTTP response is returned on deprecated endpoints (HTTP 410 Gone is the correct status for a permanently removed resource), what response body format is returned with the 410 (a JSON body with a migration_guide_url field and a human-readable message is more useful than an empty body), and how the enforcement is implemented in the routing infrastructure. The enforcement implementation should be built and tested in a non-production environment before the shutdown date — not designed on the day of shutdown — because discovering that the 410 response is missing required CORS headers on shutdown day creates an incident for clients who are trying to migrate in real time while the outage is in progress.
The five ADR sections for an API versioning decision
1. Versioning scheme selection and routing infrastructure rationale
Document the chosen versioning scheme with explicit reasoning about the alternatives evaluated and their rejection rationale. URL versioning and header versioning are the two dominant approaches; document which was chosen and which was rejected, with the specific properties that drove the decision. The rejection reasoning should address the operational properties — log segment visibility, routing infrastructure complexity, SDK distribution surface — not only the philosophical properties. A decision record that says "URL versioning was chosen over header versioning because it is more consistent with REST principles" is less useful than one that says "URL versioning was chosen because our API gateway's header-based routing adds 15-20 minutes of infrastructure change per version launch, our log aggregation infrastructure filters by URL prefix and would require a custom parser for header-based versioning, and our SDK distribution model relies on SDK major version increments corresponding to API version increments — a correspondence that is clearer with URL versioning than with header-versioned APIs where the SDK configuration for version selection is a header value rather than a base URL."
Document the routing infrastructure configuration that implements the versioning scheme: which component (API gateway, load balancer, web framework router) handles version dispatch, how that component determines which version handler receives a request, and the latency impact of the version dispatch configuration. Document any version-specific middleware — authentication, rate limiting, request validation, response serialization — and whether version-specific middleware is shared with other versions or is independent. The service mesh decision record governs traffic routing between services; if the API gateway version dispatch integrates with the service mesh, document the integration point and the version-specific traffic policy.
2. Backward compatibility commitment and breaking change classification
Document the backward compatibility commitment concretely: which fields, behaviors, authentication mechanisms, and error formats are part of the stable contract; how long the commitment lasts per client category; and what observable conditions trigger a version increment requirement. The breaking change classification should enumerate the specific change categories that require a version increment. A representative classification: removing any documented field from a request or response schema is breaking; renaming any documented field is breaking; changing any field's data type is breaking; making any previously optional parameter required is breaking; removing any endpoint is breaking; changing the HTTP method of any endpoint is breaking; changing the authentication requirements for any endpoint is breaking. Conversely: adding a new optional parameter to a request is non-breaking; adding a new field to a response is non-breaking (with the documented assumption that clients follow the robustness principle and ignore unknown fields); adding a new endpoint is non-breaking; relaxing validation to accept previously-rejected values is non-breaking.
The non-breaking change assumptions deserve explicit documentation because they are not universally true. Adding a new field to a response is non-breaking only if clients deserialize responses into flexible structures that ignore unknown fields — a JSON object deserialized into a typed struct with strict unknown-field rejection will fail when a new field is added. Document whether the API team's backward compatibility commitment assumes that clients follow the robustness principle, and whether the API documentation for SDK clients explicitly instructs them to configure their deserialization to allow unknown fields. The test strategy decision record governs the test suite; breaking change classification should be validated by a test that verifies the API's response schema against the documented stable contract — a schema regression test that fails when a documented field is removed or its type changes, and passes when a new field is added.
3. Client identification and usage tracking model
Document the client identification model: what identifier is present in every authenticated API request, where the mapping from that identifier to client metadata is stored, and how the version-specific usage query is constructed. Include the specific query or query template that the team will use to answer "which clients called /api/v1/ in the last 30 days" — not as pseudocode, but as the actual query against the actual data stores the team has. If the query requires a join across multiple data stores, document which data stores, what the join key is, and what the expected latency of the query is at the API's current scale.
Document the deprecation notice delivery mechanism: how are identified clients notified that a version they depend on is being deprecated? Options include email to the technical contact in the customer database, in-API deprecation headers on responses from deprecated versions (Deprecation: true, Sunset: Sat, 31 Dec 2026 00:00:00 GMT per RFC 8594), webhook delivery to a developer-registered endpoint, or in-product notification in the developer dashboard. Each mechanism has different reach and different confirmation capability. Documenting the chosen mechanism and the confirmation mechanism — how the team knows that a deprecation notice was received and understood, not just sent — is what makes the "we notified all clients" claim verifiable rather than asserted. The observability platform decision record governs the monitoring infrastructure; document whether the observability platform provides version-specific traffic breakdown dashboards, and if not, what the plan is for building that capability before the first deprecation needs to be enforced.
4. Deprecation timeline, communication model, and enforcement triggers
Document the standard deprecation timeline template that the team will follow for each version being retired: the minimum notice period from announcement to enforcement, the communication cadence (initial announcement, 90-day reminder, 30-day warning, 7-day final warning), and the response expected from clients at each stage. The minimum notice period should be set in the context of the longest client migration window documented in the backward compatibility commitment — if enterprise integration partners have a twelve-month compatibility window, the deprecation notice period must be at least twelve months for those clients.
Document the enforcement trigger explicitly. This is the single most important element of the deprecation timeline because it is the element that most frequently goes undocumented, and its absence is what causes deprecated versions to remain permanently live. Three viable enforcement trigger models: commit-based (the shutdown date is a calendar date, enforced on that date regardless of remaining traffic); traffic-threshold (shutdown occurs when v1 traffic drops below X% of total API traffic, with a maximum deadline if the threshold is not reached); consent-based (shutdown occurs when all identified clients have confirmed migration, with a maximum deadline for non-responding clients). Commit-based enforcement is the only model that reliably results in version removal; the others create conditions under which the shutdown can always be deferred by pointing to remaining traffic or uncollected consent. If the team chooses traffic-threshold or consent-based enforcement, document the maximum deadline explicitly — the date after which the team proceeds with shutdown regardless of remaining traffic or unconfirmed consent.
Document who is authorized to approve a deprecation enforcement delay — an extension of the shutdown date beyond the documented deadline. Authorization should require a specific type of evidence (a customer with a signed contract that includes a support SLA extending beyond the deadline), not a general "business judgment" that the impact of breaking remaining clients is too high. Without authorization criteria, every enforcement date becomes a negotiation with the partner success team who, reasonably, prefers not to break any client's integration regardless of the documented commitment. The feature flag decision record governs the feature flag infrastructure; if the deprecation enforcement is implemented as a feature flag that returns 410 on deprecated endpoints when the flag is enabled, document the flag name, the flag owner, and the authorization process for enabling the flag on the shutdown date.
5. SDK versioning alignment and distribution strategy
Document how SDK versioning aligns with API version launches: whether the team publishes official SDK packages, which languages are officially supported, how the SDK package version relates to the API version it targets, and what the migration path is for SDK users when a new API version is launched. The SDK versioning alignment question is most consequential for generated SDKs — SDKs generated from the OpenAPI specification — because a new API version launch requires regenerating the SDK from the new specification and publishing a new package version, and the timing of the SDK release relative to the API version launch determines how long external developers must wait to use the new API version with a typed SDK rather than raw HTTP calls.
Document the SDK release process: what triggers an SDK regeneration and release (a new API version launch, a change to the OpenAPI specification, or a fixed cadence), who owns the SDK release process, and what the expected time between API version launch and SDK package publication is. The CI/CD pipeline decision record governs the deployment pipeline; the SDK release process should be documented in the context of the pipeline's capability for automated package publishing. If the SDK generation and publication are not automated, document the manual steps and the responsible team, because a new API version launch that requires a week of manual SDK work before external developers can use it creates adoption friction at exactly the moment when adoption of the new version is most important for enabling v1 deprecation.
Document the SDK backward compatibility commitment in the context of the API backward compatibility commitment. If the API team commits to twelve months of v1 support, the SDK team must commit to maintaining the v1 SDK package for the same period — including security patches and bug fixes — because SDK users who have not migrated to v2 should not be forced to choose between receiving security patches and migrating to a new API version simultaneously. An SDK that stops receiving security fixes when its corresponding API version is deprecated creates a migration incentive but also creates risk for SDK users who cannot immediately migrate. The commitment to SDK maintenance during the deprecation window should be explicit in the decision record so that the SDK maintenance cost is included in the deprecation planning budget rather than discovered as an unplanned obligation when the security patch request arrives for the deprecated SDK version.
The versioning conversation buried in your AI chat history
API versioning decisions belong to the class of decisions that are made in AI chat conversations — a quick question to Claude or ChatGPT about whether to use URL versioning or header versioning, a follow-up question about how other companies handle deprecation timelines, a question about whether adding a field to a response body is a breaking change if the client SDK uses strict deserialization. The reasoning in those conversations — the trade-off between URL versioning's operational transparency and header versioning's philosophical correctness, the analysis of the client categories and their different migration windows, the question about what "backward compatible" means for a partner with a compliance-validated integration — is the content of the versioning decision record. It was produced in the context of the specific API, the specific client base, and the specific operational constraints. And it was never committed to the repository alongside the API routing configuration.
The WhyChose open-source extractor recovers exactly these API design conversations from your AI chat history — the versioning scheme evaluation, the deprecation timeline discussion, the breaking change classification reasoning that informed the original API contract. That reasoning is what the next API engineer needs when they are designing v3 and want to know what backward compatibility commitment was made when v1 was launched. The alternative is a team inheriting a /api/v1/ route prefix and a /api/v2/ route prefix with no documentation of what was committed, no client identification capability, and no enforcement trigger — and an undocumented v1 that will be live in production for as long as the API server is running.
Further reading
- The API gateway decision record — the versioning scheme is implemented in the API gateway's routing configuration; the gateway decision record governs the routing infrastructure that dispatches requests to version-specific handlers, and the versioning scheme should be chosen in the context of the gateway's native routing capabilities rather than as an independent design decision that the gateway must later be configured to support
- The authentication strategy decision record — authentication model changes are a breaking change category that requires a version increment; the authentication decision record documents the token format, expiry model, and scope model that are part of the API's stable contract, and the versioning decision record should document whether the authentication model is version-specific or shared across versions
- The database migration strategy decision record — API version launches that introduce breaking changes to the resource model frequently require database schema changes to support the new model alongside the old model; the database migration decision record governs how schema changes are deployed without downtime, and the versioning decision record should document how the database migration strategy handles the period when both the old and new resource models must be served simultaneously
- The service mesh decision record — in microservice architectures where multiple internal services consume the API, version-specific traffic routing may be handled by the service mesh rather than the API gateway; the service mesh decision record governs internal traffic policy, and the versioning decision should document whether version-specific routing is implemented at the gateway layer, the service mesh layer, or both
- The CI/CD pipeline decision record — API version launches require coordination between the API deployment and the SDK package publication; the CI/CD pipeline decision record governs the deployment pipeline, and the versioning decision record should document the release process for both the API version and the corresponding SDK package, including the automation that keeps the two in sync
- The test strategy decision record — breaking change classification requires a schema regression test that validates the API's response schema against the documented stable contract; the test strategy decision record governs the test suite architecture, and the versioning decision should document the schema regression tests that enforce the breaking change classification on every pull request
- The observability platform decision record — deprecation enforcement requires version-specific traffic dashboards showing daily request volume per version and per client; the observability platform decision record governs the monitoring infrastructure, and the versioning decision should document whether version-specific traffic breakdown is available in the current platform or requires custom instrumentation
- The logging strategy decision record — client identification for deprecation notice delivery requires joining API gateway logs against customer metadata; the logging strategy decision record governs the log format and retention policy, and the versioning decision should document which log fields carry the client identifier and confirm that those fields are present in the retained log format used for the deprecation client identification query
- The feature flag decision record — deprecation enforcement can be implemented as a feature flag that returns HTTP 410 on deprecated endpoints when enabled; the feature flag decision record governs the flag management infrastructure, and the versioning decision should document the flag name, the flag owner, and the authorization process for enabling the flag on the shutdown date
- ADR template in Markdown — the versioning decision record follows the standard ADR structure with context, decision, and consequences sections; the Markdown ADR template provides the scaffolding for recording the backward compatibility commitment, the versioning scheme rationale, and the deprecation enforcement trigger in a format that is searchable in the repository and discoverable for future engineers
- The decisions that never get written down — API versioning decisions join the class of consequential undocumented technical choices: made in an afternoon, generating maintenance debt that compounds across every subsequent version launch, and discovered as organizational incidents when the undefined backward compatibility commitment becomes the contested claim that stalls a deprecation enforcement for eighteen months
- The WhyChose open-source extractor — recover the original API versioning conversation from your AI chat history, including the scheme evaluation, the backward compatibility reasoning, and the deprecation timeline discussion that informed the original API contract before anyone wrote it down