We’re updating how public apps handle offline access tokens to better protect merchant data. New public apps created on or after April 1, 2026 must request and use expiring offline access tokens.
This change affects only new public apps. Custom apps, merchant apps, and all apps created before April 1, 2026 are not affected.
Expiring tokens enhance security. If a token is ever leaked, its limited lifespan significantly narrows the risk to both your app and the merchants who trust it. This change aligns with modern OAuth practices, and as a developer it lets you build your app around predictable refresh flows.
Learn more:
Learn more on how to acquire expiring offline tokens, including refresh handling and rotation in the dev docs.
I scanned the doc quickly but couldn’t find an answer to my question which is: Does it require that the merchant opens the app in the admin to request a new offline token, or can we acquire a new token without actions from the merchant?
We have an app that runs in the background, and once set up it’s very likely that the client never opens the app for more than 90 days, but the app still requires a token to operate in the background, even after 90 days.
I just finished migrating. The refresh token is used to get a new offline and refresh token with updated expiration. The offline token expires after 1 hour. So whenever you get the offline token, you can check if it’s expired or close to expiring and refresh it if so. The refresh token will be updated also, so as long as your background jobs run sooner than every 90 days you’ll be fine.
But you can also do what I did and implement a background job that runs once a day and refreshes all sessions that the refresh token expires within 7 days or whatever.
@DavidT thanks for the insights, you mentioned the offline token expires after one hour. Does that mean every one hour we should use a refresh token to acquire a new offline token? Does that change from how it’s implemented at the moment? I guess at the moment the offline token has no expiration and we don’t even need to refresh it when running background tasks?
My worry with this new system is around error management and the need to protect against “refresh request stamped”, in the case multiple runtimes try to acquire a new offline token simultaneously for the same shop. This introduce a new class of errors we have to protect against. We have to use a distributed lock to handle it. If that’s done automatically at the shopify api client level, it might be hard to implement properly in large codebases.
You should just check the session expiration before using the offline token and only refresh if it’s about to expire. That way you only refresh tokens on demand.
Yeah I worry about parallelization issues as well. I’m not sure what happens when refreshed, but I assume the previous token is invalidated. Maybe not though.