Skip to main content
DeploTeka Set up your first store

By DeploTeka · Last updated November 7, 2026 · 10 min read

Shopify client credentials grant: token lifetime, who can use it, and common errors

Short answer: the client credentials grant lets a server-side app exchange its own client ID and client secret for an Admin API access token, with no redirect and no merchant session. It works only for stores in the same Shopify organization as the app. The token is valid for 24 hours (expires_in is 86399), and there is no refresh token: when it expires, you send the same request again. Since October 27, 2026 there is a second form of the grant. The app signs a client assertion with a private key instead of sending its secret, and an app with public distribution can then get tokens for any store that installed it, valid for up to one hour.

What is the client credentials grant?

It is one of the three grants Shopify uses to issue Admin API tokens, next to token exchange and the authorization code grant. Shopify describes it in one line: "Server-side integrations acting on your own stores use this grant to exchange your app's own credentials for an access token, with no merchant interaction" (Access tokens). Of the three, Shopify says it "takes the least setup": no redirect flow to build (Authenticate an app for stores in your organization).

It matters more since January 1, 2026, when Shopify stopped letting anyone create new custom apps in the Shopify admin. Admin-created apps came with a pre-generated token you could copy. Apps created in the Dev Dashboard don't: "With a client credentials grant, you won't see a token in the Shopify admin. Instead, you request tokens programmatically when you need them." If a setup screen asks you to paste a token, it was written for the old flow. Shopify's own troubleshooting advice for that case is to contact the tool's vendor "about updating their integration to use OAuth." The deprecation guide covers the wider change.

Which apps can use it?

Shopify's rule, from About app authentication: "The client credentials grant works only for stores in your organization, unless your app has public distribution and authenticates with a client assertion."

Your situationClient credentials?What to use
App and store in the same organization, such as a merchant building for its own stores, or your own dev storesYes, with the client secret or a client assertion. 24-hour tokensThis grant
Custom-distribution app in your organization, installed on a client's storeNoToken exchange if embedded, or the authorization code grant if not
Public-distribution app, on any store that installed itYes, with a client assertion only. Tokens up to 1 hourApplication-only access tokens
Legacy app created in the Shopify admin before 2026No grant neededThe pre-generated token

Merchants don't need a Partner organization for the first row. Shopify's Dev Dashboard page says a merchant, or a developer building for the company's own stores, can open the Dev Dashboard from the Shopify admin, and that "Apps that you create there are custom apps for your organization's stores."

"Same organization" is narrower than it sounds. Shopify defines it as "both appear under the same org in the Dev Dashboard", and warns: "Owning a store or having it installed doesn't automatically place it in your org." A store you reach as a collaborator stays in the merchant's organization. For a client's store, Shopify's answer is to distribute the app with custom distribution "so that a merchant installs it", then use token exchange or the authorization code grant.

How do you request a token?

First the prerequisites from Shopify's tutorial: the app exists in the Dev Dashboard, its released version has the access scopes you need, and the app is installed on the store. Then:

  1. Open the app in the Dev Dashboard and go to Settings.
  2. Copy the Client ID and Client secret. Keep the secret in an environment variable or a secret manager, never in version control.
  3. Send a form-encoded POST to the store's token endpoint.
POST https://{shop}.myshopify.com/admin/oauth/access_token
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials&client_id={client_id}&client_secret={client_secret}

The response has three fields:

{
  "access_token": "<opaque token>",
  "scope": "read_products",
  "expires_in": 86399
}

Send access_token in the X-Shopify-Access-Token header on Admin API requests. Three details from Shopify's docs catch people out:

  • {shop} is the store's myshopify.com subdomain, and Shopify's troubleshooting says it must match exactly.
  • Don't send a scope parameter. Shopify ignores it. The token carries every scope the store granted to your installation, and the scope field in the response reports what that is. An optional scope the store declined won't be there.
  • Read expires_in instead of hard-coding 24 hours, so your code survives a lifetime change. Shopify's docs give the same advice.

How long does the token last, and how do you renew it?

24 hours. Shopify's tutorial documents expires_in as "Always 86399 (24 hours)." There is no refresh token: "To refresh it, send the same request again." Shopify's example code caches the token and requests a new one 60 seconds before expiry, rather than calling the token endpoint on every request.

For comparison, Shopify's token lifetime table:

TokenLifetime
Client credentials with the client secret, store in your organization24 hours (expires_in is 86399)
Client credentials with a client assertion, app with public distributionUp to 1 hour (expires_in at most 3600)
Client credentials with a client assertion, other apps24 hours
Expiring offline token from token exchange or the authorization code grant1 hour, plus a 90-day refresh token
Non-expiring offline tokenNo expiry. Valid until the app is uninstalled or its client secret is revoked

A 24-hour credential can't sit in a settings field. Whatever reads it needs a small renewal loop, and every process that calls the Admin API needs access to the same cache or its own way to get a token.

What is the client assertion variant?

Shopify added it on October 27, 2026, in a security update that called it "client credentials access" (changelog). The docs call the result an application-only access token.

Instead of the client secret, your server signs a short-lived JWT, the client assertion, with a private key that only it holds. You add the matching public key to the app in the Dev Dashboard as a JSON Web Key, under Settings, Credentials, Public keys. Shopify accepts RS256 and ES256 keys, and an app can have up to two active public keys. The token request sends client_assertion, client_assertion_type (urn:ietf:params:oauth:client-assertion-type:jwt-bearer), client_id and grant_type=client_credentials, and the response has no refresh token.

What it changes depends on how the app is distributed. Shopify's wording: an app with public distribution "can use this flow for any store that has installed it, and gets tokens that are valid for up to one hour. Other apps, such as custom apps, keep the client credentials grant rules: they can get tokens only for stores in their organization, and the tokens are valid for 24 hours." So the assertion lets a custom app stop sending its secret. It does not let a custom app reach a client's store.

A Shopify staff member describes it as "a supported long-term acquisition method" (TerenceShopify, Token Expiry FAQ, October 30, 2026).

How do you rotate the client secret?

Shopify's Manage your app credentials page gives an order that avoids downtime:

  1. In the Dev Dashboard, open the app's Settings, click Rotate next to the client secret, then Generate new secret. The old secret stays active until you revoke it.
  2. Accept webhook signatures from both secrets. Shopify signs webhooks with "your app's oldest unrevoked client secret", so they keep using the old one until you revoke it.
  3. Switch your app's configuration to the new secret for every OAuth call, including client credentials requests.
  4. Replace tokens minted under the old secret. For this grant Shopify notes: "Request a new token using the new secret. Tokens from this grant last 24 hours, so they turn over on their own."
  5. Revoke the old secret. Any token still tied to it stops working. Then validate webhooks with the new secret only.

If a secret is being misused right now, Shopify's advice flips: revoke it first and accept the downtime. Tokens from a client assertion are not tied to the secret, so rotating the secret doesn't affect them. Public keys rotate on their own schedule: add the new key, sign with it, let old tokens expire, then revoke the old key.

Two more controls are worth turning on. An IP allowlist, added in the same October 2026 update, makes Admin API requests that use your app's tokens fail with a 403 when they come from outside the addresses or networks you list. Shopify made it mandatory for public apps in November 2026. For custom apps it isn't required, but Shopify calls it "highly recommended". And keep the client secret out of browsers: Shopify says the client ID is safe in frontend code and the secret never is.

What do the common errors mean?

Oauth error shop_not_permitted: Client credentials cannot be performed on this shop. The app and the store are not in the same organization. Shopify's checklist: confirm the app is listed under Apps, confirm the store is listed under Dev stores in the same organization, and check the organization ID in the URL (dev.shopify.com/dashboard/<org-id>) if you belong to several. A dev store created from the Shopify admin instead of the Dev Dashboard isn't in your organization. A client's store isn't either.

application_cannot_be_found, with "Could not find Shopify API application with api_key". A Shopify staff member says this "usually pops up when the Client ID being passed doesn't match what we have on file for the app", and suggests copying the client ID fresh and checking that this app is installed on this store (Alan_G, April 10, 2026). Credentials from one app don't work for another.

"Invalid API key or access token". You sent the client ID or secret straight to the GraphQL Admin API. Exchange them for an access_token at the token endpoint first.

401 Unauthorized from the Admin API. The token expired or was revoked. Uninstalling the app ends all its tokens for that store, and revoking a secret ends the tokens minted with it. Request a new token. Shopify's own example for application-only tokens requests a new token once on a 401, and stops to investigate if the new token is rejected too.

A scope you need is missing from scope. The store hasn't granted it. Release a new app version that includes it and approve the change on the store. Shopify's docs note that new scopes in a version are not applied to installed stores automatically.

When is client credentials the wrong tool?

  • Client stores in other organizations. Use one custom-distribution app per client merchant, installed by link, with token exchange or the authorization code grant. The collaborator guide explains why collaborator access doesn't change this.
  • An embedded app built with Shopify CLI. Shopify says the CLI "handles authentication automatically."
  • Actions on behalf of a logged-in staff member. Use online access tokens, which respect that user's permissions.

Where DeploTeka fits (product note). If every store you serve is in your own organization, the client credentials grant and a small token cache are the whole job, and you don't need DeploTeka. DeploTeka is for the case this grant can't reach: client stores in other organizations, where each store gets its own dedicated custom-distribution Shopify app, created inside your own organization, and the token comes from the merchant's install. It seals each app's credentials and delivers them to your backend, and pauses with a named action when a step needs a person. It does not clone, build, or run your source on our servers, and the merchant still approves each install. Shopify requires that, and no tool removes it. deploteka.com


Sources: Shopify — Authenticate an app for stores in your organization, Shopify — Access tokens, Shopify — About app authentication, Shopify — Get application-only access tokens for installed stores, Shopify — Manage your app credentials, Shopify — Dev Dashboard, Shopify — Create apps using the Dev Dashboard, Shopify changelog — security update, October 27, 2026, Shopify — Restrict API access with an IP allowlist, Shopify changelog — legacy custom apps can't be created after January 1, 2026. Community threads are linked as evidence of what Shopify staff said in them, not as statements of Shopify policy. DeploTeka is independent software and is not affiliated with or endorsed by Shopify.

Frequently asked questions

What is the Shopify client credentials grant?

An OAuth grant where your server sends an app’s client ID and client secret to a store’s token endpoint and gets an Admin API access token back. There is no redirect and no merchant session. It works only for stores in the same Shopify organization as the app.

How long does a Shopify client credentials token last?

24 hours: expires_in is 86399. There is no refresh token, so you send the same request again. With a client assertion, an app with public distribution gets tokens valid for up to one hour.

Can I use the client credentials grant on a client’s store?

Not with a custom app. The grant can’t reach a store outside your organization unless the app has public distribution and uses a client assertion. For a client’s store, use custom distribution plus token exchange or the authorization code grant.

What does shop_not_permitted mean?

The store is not in the same Shopify organization as the app. Check that the store is listed under Dev stores in the app’s organization. A dev store created from the Shopify admin is not in your organization.

Does rotating the client secret break client credentials tokens?

Tokens minted with the old secret stop working when you revoke it. Request new tokens with the new secret before revoking; they only last 24 hours anyway. Tokens from a client assertion are not tied to the secret.