See all services → Shopify Plus Partner
API Developer

Retry Token Migration Exchanges for Up to Seven Days

Apps migrating non-expiring offline tokens without a user session can now retry a lost exchange for up to seven days and receive the same token pair, avoiding a merchant re-authorization.

Executive summary

What changed

The direct migration flow exists so apps need not wait for a user to open the app before moving to expiring tokens. Its weakness was a single use response: lose it to a failed database write or a timeout and the store was stranded until a merchant triggered a fresh authorization.

A retry using the same original token and the same client credentials is now idempotent within a window. Shopify returns the same access token and refresh token, and extends the access token expiry where needed. It does not extend the refresh token expiry, so the refresh clock started at the first exchange. Recovery ends at whichever comes first: seven days from the initial exchange, a successful refresh of the issued pair, or a later token acquisition for that store replacing the pair, such as an ID token exchange or authorization code grant.

Existing flows need no changes. The original non expiring token remains invalid for Admin GraphQL API requests once migrated, so it is a recovery key only, never a fallback credential. A retry answering with invalid_subject_token means the window has closed and you need a fresh token through ID token exchange or the authorization code grant.

Why it matters

The apps most exposed are the ones merchants notice least until they break: ERP and OMS connectors, inventory and order sync services, scheduled middleware with no human in the admin. For those, asking a merchant to reopen an app means a support ticket, a wait on someone with the right permissions, and a sync gap in between.

A seven day idempotent recovery window turns a class of unrecoverable failure into an operational retry. Build around it deliberately rather than treating it as a safety net, because the window is bounded and one successful refresh closes it. For merchants the benefit is fewer silent integration outages during a migration that should be invisible. Teams weighing how much of this to own internally can see how we approach it on the Shopify development side.

Role-specific impact

Use-case example

Real-world scenario

An app vendor migrates offline tokens across roughly 200 merchant stores in one batch. Connection pool exhaustion partway through drops the persistence step for about 40 stores while the exchanges succeed. Previously each of those merchants had to reopen the app, which can take days where the only authorized admin is an ops manager. With the retry window the vendor replays those 40 exchanges with the original tokens, persists correctly, and contacts no merchant. Roughly 40 support conversations are avoided.

Implementation checklist

  1. Identify every store where your app holds a non expiring offline token.
  2. Make persistence atomic: store access token, refresh token and expiry together, or not at all.
  3. Record the initial exchange timestamp per store to know how much of the seven day window remains.
  4. Build the retry path to reuse the original token and the same client credentials.
  5. On invalid_subject_token, acquire a new token through ID token exchange or the authorization code grant and update stored credentials.
  6. Discard the original token once migration is confirmed, since it no longer works for Admin GraphQL API requests.
  7. Migrate in cohorts small enough that a persistence failure stays inside the window.

FAQ

Q: Does a retry extend the refresh token expiry?

A: No. Shopify returns the same pair and extends the access token expiry where needed, but not the refresh token expiry. The refresh clock runs from the initial exchange.

Q: Can we keep using the original non expiring token as a fallback?

A: No. Once migrated it is invalid for Admin GraphQL API requests. Its only remaining use is as the subject token on an eligible retry inside the seven day window.

Resources

Migrating existing tokens without a user session

Need guidance? Talk to Makro.