Set two separate cutover rules
Route retirement closes an endpoint. Token retirement stops accepting an old credential format, signing key, issuer, or audience. Give each its own owner, date, and expected response. A retired token can fail on an active route while that route remains fully supported. A retired route must stop serving private data and running changes even when the caller has a valid current token.
The Sunset header announces when a resource is expected to become unavailable. The header does not shut down a handler. Record the gateway rule and application change that enforce the closure, and list every hostname, path alias, version header, and rewrite that reaches it.
Build a valid baseline for each version
Use staging accounts with known roles and balances. Create a valid request for v1 and another for v2 using each version’s documented schema. Confirm that both work while supported. Keep the account, amount, recipient, and business action the same, while mapping renamed fields and required headers. Replaying v2 JSON into v1 can fail parsing before it reaches authorization; that result does not prove the old security rule works.
Synthetic transfer example
Assume v1 accepts amount_kobo and recipient_id, while v2 accepts amount_minor, currency, and beneficiary_id. A transfer of ₦5,000 uses 500000 in both amount fields. First submit each version’s valid request with two approved staff accounts. Save the resulting transfer IDs and verify one transfer per request. Reset the fixture, remove the second approval, and repeat with each valid schema. Both supported versions must reject the transfer under this product’s two-person approval rule, with no debit or queued payout.
Next change only the recipient to one owned by tenant B while keeping the tenant A token. A version that rejects this valid request for lack of access passes that check. A version that returns a schema error needs a corrected test before drawing a result. Keep the parser result, authorization result, and stored transfer state as separate facts.
Run the cutover sequence
- Before closure, test both valid baselines and both negative cases on every supported version.
- At the token cutoff, call an active route with a retired token and a current token. The retired token must fail; the current token must still reach the expected business checks.
- At the route cutoff, call every retired alias with a valid current token and a valid legacy payload. Expect the planned closure response with no private data or side effect.
- Repeat from the public gateway and through the origin path in staging. Check that gateway rewrites do not reach an old handler.
- Read the account and transfer records through an authorized test account. Confirm no debit, new approval, or queued job followed the denied calls.
Test cases and proof
| Case | Expected result | Proof |
|---|---|---|
| Active route, retired token | Authentication denied | Token policy and response |
| Active old route, current token, valid payload without second approval | Business rule denies transfer | Parsed request and unchanged stored state |
| Retired route, current token, valid old payload | Closure response; no handler side effect | Gateway mapping and authorized readback |
Give old clients a useful response
Test the closure response on the oldest signed app build still in use. Check that it displays an update link or support route before the customer completes a transfer form. Keep the last supported build, route owner, and closure time in the support record. If a protected compatibility path is required, assign its end date and enforce the current money and access rules there.
Keep enough evidence to repeat the test
Save each version’s request schema, sanitized payload, client build, route inventory, token policy, and request ID. Record the response and authorized readback of affected rows and jobs. After cutover, track rejected calls by client build without logging tokens or private payloads. Use those counts to find customers who need help updating and aliases missing from the inventory.
Related reading
Why these checks matter
OWASP API9 calls for an inventory of API hosts and versions and warns that old versions need the same protection as current ones. Use that inventory to find each live alias. A retirement notice only changes client expectations; the gateway and origin still need to reject calls to a closed route.