"Deprecated offline token use detected" warning persists despite confirmed clean usage

Hi

I’ve built a shoping app on the Node/Express app template (@shopify/shopify-api), and my Partner Dashboard continues to show “Deprecated offline token use detected in last 30 days” / “in last 14 days” even though I’ve confirmed there’s no actual deprecated activity happening.

What I’m doing:

On every install, immediately inside my OAuth callback, I migrate the token before doing anything else:

const migration = await shopify.api.auth.migrateToExpiringToken({
shop: session.shop,
nonExpiringOfflineAccessToken: session.accessToken,
});
session = migration.session;

This runs right after shopify.api.auth.callback() resolves, before any other Admin API calls (webhook registration, billing charge, etc.) are made using the session. So new installs should never actually use a non-expiring token against the Admin API — it’s exchanged first.

For shops that installed before I added this code, I also run a lazy migration check in my own backend middleware before any outbound Shopify call, so those get migrated on their next request too.

What I’ve verified:

  • The migrateToExpiringToken call succeeds with no errors, for every install I’ve checked
  • No cron jobs, scheduled workers, or webhook handlers in my app call the Shopify Admin API directly with a stored token outside this migration path
  • Checking the 1-day view in Partner Dashboard has shown zero deprecated calls for 5+ consecutive days
  • I’m confident there’s no deprecated call activity within the 14-day window either

Despite this, the 14-day and 30-day warnings continue to display.

Could you help clarify:

  1. Whether this warning reflects an actual detected API call within the stated window

  2. Should i ask for non-expiring access token directly and not via shopify.api.auth.migrateToExpiringToken

  3. Whether this is a known display/refresh issue with the Monitoring dashboard.

Thanks for your help.

Hi @srithin_camweara

I think what’s happening here is that you just need to wait for the deprecated calls in the 14 day and 30 day window to time out.

The reason you see it persist while the 1-day view is clean: the 14- and 30-day figures are trailing, cumulative windows. One deprecated call 8-13 days ago keeps showing in the 14-day view until it ages out, and for up to 30 days in the 30-day view, even while every recent day reads zero. “1-day clean for 5 days but 14/30-day still lit” is the expected mid-transition state if your fix rolled out roughly a week ago. Treat the 1-day view as the leading indicator; you should see the 14-day clear first, then the 30-day.

RE: migrateToExpiringToken, this is a one-time backfill for existing shops. For new installs they should stop minting non-expiring tokens at all: move to token exchange / managed installation (Shopify-managed install) so fresh installs get an expiring offline token from the start.

Hi, @Liam-Shopify

The reason I’m using migrateToExpiringToken is that I’m using the @shopify/shopify-app-express template. At the moment, the template doesn’t provide a way to request an expiring offline access token during the initial OAuth flow—it only requests a non-expiring offline access token by default.

I also checked the latest version of the template, and this functionality still hasn’t been added. That’s why I’m using migrateToExpiringToken to migrate existing non-expiring tokens to expiring ones.