How to Refresh or Rotate a Shopify Access Token
The short answer: there’s no refresh endpoint for the Shopify Admin API. Offline tokens don’t expire, and to rotate one you re-run OAuth and revoke the old. Here’s the safe procedure, plus what to do if a token leaks.
By Datora Team · Updated
If a token has leaked, do this right now:
- Issue a new token via OAuth for the affected shop.
- Roll the new token into your secrets store and deploy.
- Call
DELETE /admin/api/<ver>/api-permissions/current.jsonwith the OLD token to revoke it server-side. - Audit logs for what the leaked token may have done.
Detailed walk-through below, including the offline vs online distinction and code snippets for the revoke call.
Do Shopify access tokens expire?
It depends on which kind of token you have. Shopify issues two types from the Admin OAuth flow:
Offline token
DefaultLong-lived, non-expiring. Issued when you complete an OAuth flow without the grant_options[]=per-user parameter. Used by Custom apps, server-side integrations, back-office tools.
Stays valid until: the merchant uninstalls your app, you explicitly revoke, or Shopify revokes for policy reasons.
Online token
Embedded appsShort-lived, ~24 hours. Bound to a specific staff user’s session. Issued when you pass grant_options[]=per-user to OAuth.
“Refreshed” via the Token Exchange API: trade the embedded app’s session token for a new Admin token on each session.
Most non-embedded tools — back-office sync apps, ETL pipelines, one-off scripts, agency-built admin dashboards — use offline tokens. The rest of this page is about offline-token rotation unless noted otherwise.
Why there’s no refresh_token
Many OAuth systems pair every short-lived access token with a long-lived refresh_token you trade in periodically for a new access token. Shopify Admin API doesn’t. That trips up developers coming from Google, GitHub, or standard OAuth 2.0 RFC implementations.
The reason: offline access tokens already are the long-lived token. There’s no shorter-lived sibling to refresh. Online tokens have a different mechanism (Token Exchange) that doesn’t use refresh_token either.
If your code looks for a refresh_token field in the OAuth response, you won’t find one — and you don’t need it. The token Shopify hands back is the final token.
The safe rotation procedure
The pattern is issue first, revoke after — never the other way around. Both tokens are valid simultaneously for a brief window, which means zero downtime.
Confirm the token type and the reason for rotation
Offline (long-lived, default) or online (~24h, embedded apps)? Routine rotation, suspected leak, employee departure, or merchant reinstall? The procedure is the same but the urgency and audit scope differ.
Issue a new token via OAuth on the same shop
Run the standard Authorization Code flow with the same scope set. The new token is independent of the old — both are valid until you revoke. If you'd rather not script the OAuth flow yourself, accesstokengen.com runs it for you in under a minute.
Roll the new token into your secret store and verify
Update your secrets manager, deploy, and probe with a sample Admin API call (GET /admin/api/<ver>/shop.json is the cheapest read). Make sure the new token returns 200 before moving on.
Revoke the old token
Send DELETE /admin/api/<ver>/api-permissions/current.json with the OLD token in the X-Shopify-Access-Token header. The token is invalidated server-side — any further calls with it return 401.
Audit and clean up
Search git, CI logs, Sentry, screenshots, and any monitoring tools that may have captured the old token in HTTP request bodies or error reports. If the rotation was incident-driven, audit Admin API usage during the window the token was potentially compromised.
Revoke the old token
Authenticate the revoke call with the token you want to kill. Shopify identifies which token to invalidate from the request header.
cURL
curl -X DELETE \
"https://{shop}.myshopify.com/admin/api/2026-04/api-permissions/current.json" \
-H "X-Shopify-Access-Token: shpat_OLD_TOKEN_HERE"Node.js (fetch)
// Revoke the OLD token by calling the API as that token
const SHOP = "your-store.myshopify.com";
const OLD_TOKEN = process.env.OLD_SHOPIFY_ACCESS_TOKEN;
const res = await fetch(
`https://${SHOP}/admin/api/2026-04/api-permissions/current.json`,
{
method: "DELETE",
headers: { "X-Shopify-Access-Token": OLD_TOKEN },
}
);
if (!res.ok && res.status !== 404) {
throw new Error(`Revoke failed ${res.status}: ${await res.text()}`);
}
// 200 OK or 404 (already revoked) both mean the token is dead.Don’t revoke before the new token is live. Once you call DELETE on the old token, every running process still using it starts failing with 401. Cut traffic to the new token first, confirm with a probe call, then revoke.
For a complete reset across every token your app holds for the shop, ask the merchant to uninstall and reinstall — uninstall revokes every token your app issued for that store. That’s the nuclear option.
Embedded apps: Token Exchange instead of refresh
If you’re building an embedded app that needs online tokens, the modern pattern is the Token Exchange API: each embedded session comes with a session token (JWT) that you trade in for a short-lived Admin token, scoped to the active staff user.
Token Exchange replaced the old “authorization code on every load” pattern. It’s faster, doesn’t require a redirect, and gives you a valid online token without maintaining your own session storage.
In this model you don’t schedule rotations — the session-token-to-access-token exchange happens inline, on each user request that needs Admin API access. There’s no long-lived secret to leak.
Common mistakes
Looking for a refresh_token in the OAuth response and assuming the integration is broken when it's missing. Shopify Admin doesn't issue one.
Revoking the old token before the new one is in production. Cut traffic over first, then revoke.
Scheduling automatic rotation without a reason. Offline tokens are designed to live for years; calendar-driven rotation just adds risk of bugs in the rotation pipeline.
Forgetting to audit downstream copies after a leak. The old token may live in CI environment variables, Sentry breadcrumbs, dev machine .env files, screenshots in support tickets.
Mixing up online and offline tokens. If your app is embedded and you're getting 401s after a day, you're probably treating a per-user token as if it were offline.
Issue a fresh Admin API token
Skip the OAuth scaffolding — paste your Custom App credentials, pick scopes, approve on Shopify, copy your new token. Then call the revoke endpoint above to retire the old.
Frequently asked questions
Do Shopify Admin API access tokens expire?+
Offline tokens (the default for Custom apps and most integrations) do not expire — they remain valid until the merchant uninstalls the app or you explicitly revoke them. Online tokens, used by embedded apps for session-bound access, expire after about 24 hours and are refreshed via the Token Exchange API rather than a refresh_token.
Is there a refresh_token for the Shopify Admin API?+
No. Unlike many OAuth systems, the Shopify Admin API does not issue a refresh_token alongside the access token. Offline tokens never expire, so refresh isn't needed; for online tokens, Shopify uses the Token Exchange API instead. To rotate an offline token you re-run OAuth and revoke the old token.
How do I revoke a Shopify Admin API access token?+
Call DELETE https://{shop}.myshopify.com/admin/api/{version}/api-permissions/current.json with the X-Shopify-Access-Token header set to the token you want to revoke. The token is invalidated immediately. Alternatively, uninstalling your app from the store revokes every token that app holds for that shop.
What should I do if a Shopify access token leaks?+
Treat it as compromised: 1) immediately issue a new token via OAuth and deploy it; 2) revoke the leaked token via the api-permissions endpoint; 3) audit your logs for what the leaked token may have done — list recent orders, customers, products it touched; 4) check git history, CI logs, screenshots, Sentry for other places it may have been written; 5) if customer data was potentially exfiltrated, follow your incident-disclosure policy.
Should I rotate Shopify access tokens on a schedule?+
Generally no for offline tokens. They're designed to be long-lived and rotation requires re-running OAuth, which is harder to fully automate without merchant involvement. Rotate on incident (leak, employee departure, suspicious activity) rather than calendar. The exception is if you have a compliance requirement that mandates rotation — in that case build the OAuth re-issue into your annual review workflow.