Help improve docs quality by sharing anonymous interaction telemetry (no PII or token data).

Migration Guide

Detect deprecated usage, migrate safely with dual-read patterns, and roll out in stages.

MonetizeKit versions the API by URL path and gives every deprecation a minimum warning window before removal — but a smooth migration is still on you: you need to know what you're using, verify the replacement, and roll the change out without a big-bang cutover. This guide covers all three.

How versioning works

AspectDetail
Version schemeURL-path versioning — /api/v1/, with /api/v2/ served alongside it once introduced.
Unsupported version404 with error: "unsupported_api_version".
Current version headerX-API-Version: v1 is present on every response, success or error.
Minimum deprecation windowAt least one minor release with active warnings before removal; enterprise plans may get an extended window.

1. Find what you're using that's deprecated

Deprecated endpoints and GraphQL fields are marked in the API reference and enumerated with removal dates on the Deprecations page. There is no per-call response header that flags deprecated usage — the signal lives in the docs, not the wire protocol — so cross-reference the paths your integration actually calls (from your own access logs) against that page:

bash
# There is no runtime Deprecation/Sunset response header to grep for — the# only version-related header on every response is X-API-Version. Detect# deprecated usage by cross-referencing every endpoint/field your integration# calls against the Deprecations page (/docs/changelog/deprecations) instead.# Example entry as of this writing:##   item:                  "GET /integrations/legacy-webhooks"#   removalVersion:         v2.4#   removalDate:            2026-09-30#   migrationInstructions: "Use GET /webhooks/endpoints for endpoint management and replay operations."grep -A1 "GET /integrations/legacy-webhooks" your-access-log.txt

Anything already returning 404 unsupported_api_version means you're calling an unsupported version prefix outright, not merely a deprecated field — fix that first.

2. Add a dual-read fallback

Don't cut over in one deploy. Read from the new shape first and fall back to the deprecated one only if the new call fails, logging every fallback so you can measure how much traffic still depends on the old path.

javascript
// Neither the deprecated endpoint nor its replacement has an// @monetizekit/node SDK method (webhook endpoint management is REST-only —// see the Webhooks guide), so call both directly.async function getWebhookIntegrations() {  const [legacy, current] = await Promise.allSettled([    fetch(`${baseUrl}/integrations/legacy-webhooks`, { headers: authHeaders }).then((r) => r.json()),    fetch(`${baseUrl}/webhooks/endpoints`, { headers: authHeaders }).then((r) => r.json()),  ]);  // Prefer the new shape; fall back only while the legacy path is still live.  if (current.status === "fulfilled") return normalize(current.value.data);  console.warn("Falling back to deprecated GET /integrations/legacy-webhooks", legacy);  if (legacy.status === "fulfilled") return normalize(legacy.value.data);  throw new AggregateError([current.reason, legacy.reason], "Both webhook integration APIs failed");}

3. Roll out in stages

Once the new path works, move traffic over gradually and deterministically — the same workspace should stay on the same side of the gate across requests, so a problem surfaces as a contained blast radius rather than a random flicker.

javascript
// Route a percentage of traffic to the new integration path first,// keyed deterministically so a given workspace always lands on the same side.function useNewWebhooksApi(workspaceId, rolloutPercent) {  const bucket = hashToPercent(workspaceId); // stable 0-99 bucket per workspace  return bucket < rolloutPercent;}const rolloutPercent = 10; // start small: 10% -> 50% -> 100% over successive deploysconst path = useNewWebhooksApi(workspaceId, rolloutPercent)  ? "/webhooks/endpoints"  : "/integrations/legacy-webhooks";await fetch(`${baseUrl}${path}`, { headers: authHeaders });
Watch, then widen

Hold each rollout percentage long enough to observe error rates and fallback volume before widening it. A migration that silently regresses at 10% and isn't caught until 100% is far more expensive to unwind than one caught early.

Migration checklist

Before you remove the old code path

Common pitfalls

Waiting until the removal date

A removal date is a hard cutoff, not a target to start migrating on. Start as soon as a deprecation is announced — the minimum warning window is the floor, not a comfortable buffer.

Big-bang cutover

Switching every workspace at once means every migration bug ships to every customer at once. A staged percentage rollout turns that into a contained, quickly-reversible blast radius.

No fallback logging

Without logging when the dual-read fallback triggers, you can't tell when it's safe to delete the legacy path — you're guessing instead of measuring.

Ignoring GraphQL field deprecations

Deprecated GraphQL fields (like legacyFlags) keep working until removal, so nothing breaks today — but they carry the same removal-date risk as REST endpoints. Check the GraphQL reference for deprecationReason annotations, not just REST responses.

FAQ

How much notice do I get before a breaking change?

At least one minor release with active deprecation warnings before removal. See Breaking Changes for the running list with exact removal dates.

Will /api/v1 stop working once /api/v2 ships?

No — a new major version is served alongside the previous one, not as a replacement for it. /api/v1 keeps working until it is explicitly deprecated and removed under the same policy as any other endpoint.

Can I test against a future API version before it's generally available?

Watch the Changelog for early-access announcements. Until a version is documented in the API reference, treat any behavior you observe from it as unstable and don't build against it in production.

Related guides

Audit and Trace

Correlate migration-related errors with request IDs.

Open guide

Webhook Verification and Retries

Migrating a webhook integration follows the same dual-read pattern.

Open guide

Was this page helpful?