Non-expiring tokens stay valid forever if they leak. Shopify is requiring all Public apps to migrate to "Expiring Offline Access Tokens" that expire in 60 minutes and rotate automatically.
January 1, 2027. After this date, calling the Admin API with a non-expiring token returns an authentication error.
All Public apps, including those created before 2026/4/1. Custom apps, apps built in the Dev Dashboard, and apps created in the Admin are not affected.
Exchange existing tokens via code to switch them to expiring tokens. No reinstall is required on the merchant's side.
Including those created before 2026/4/1. Any app of the Public type is affected, regardless of whether it's published on the App Store.
Already required to use expiring tokens. This announcement is a follow-up rule extending the requirement to existing apps as well.
Custom apps built for a single merchant are not included in this requirement.
Apps the merchant created themselves in the Dev Dashboard.
Apps created from the Shopify admin.
| Item | Non-expiring (OLD) | Expiring (NEW) |
|---|---|---|
| Validity period | No expiration | 60 minutes |
| Renewal | None | Auto-rotation |
| Impact if leaked | Can be abused permanently | Expires within 60 minutes, minimizing the blast radius |
| Admin API on or after 2027/1/1 | Authentication error | Works normally |
| Alignment with OAuth best practices | Not aligned | Compliant |
If a non-expiring token leaks, it stays valid forever. That runs counter to modern OAuth best practices. Expiring tokens plus automatic refresh shrink the leak window to 60 minutes.
Because refresh behavior is always the same, token-management design is simplified. It's already implemented in Shopify's templates and official API libraries.
Audit your database for which stores and which scopes you're holding non-expiring tokens for.
No merchant reinstall required. Your app's code exchanges "non-expiring → expiring" tokens.
Store the new access_token / refresh_token / expires_at and get the refresh flow running.
No grace period. The moment you call the Admin API with a non-expiring token, an auth error is returned. To avoid production impact, switching over at a time that doesn't span the year-end/new-year freeze is the realistic choice.
You only need to exchange existing tokens in your app's code. There's basically no need to ask installed stores for extra operations, and notifications to sales/CS are lightweight too.
If you're using Shopify's official Library, refresh handling is already built in. The more a legacy implementation hand-wrote its own OAuth, the more work it takes.
Move from a single access_token column to operating with the three-piece set of access_token / refresh_token / expires_at. Decide on your migration design and how you'll backfill existing records.
The impact is limited to "Public apps" only.Apps that merchants create in the Admin or Dev Dashboard, and Custom apps, are not included in this requirement, so start by classifying the app type for your project and producing an impact assessment.