---
title: Manage your app credentials
description: >-
  Find your client ID and secret, rotate credentials safely, and secure them in
  production.
source_url:
  html: >-
    https://shopify.dev/docs/apps/build/authentication-authorization/manage-credentials
  md: >-
    https://shopify.dev/docs/apps/build/authentication-authorization/manage-credentials.md
---

# Manage your app credentials

Your app's client credentials consist of a client ID and a client secret. The client ID identifies your app to Shopify, and the client secret authorizes it to make OAuth calls. Some tools and documentation call these the API key and API secret: `SHOPIFY_API_KEY` holds your client ID, and `SHOPIFY_API_SECRET` holds your client secret.

Reference this page when you need to locate your credentials for environment configuration, apply security best practices, or rotate your client secret after launch.

**Info:**

An App Automation Token is a separate credential for authenticating the Shopify CLI in CI/CD, not for API requests. To create, use, or rotate one, see [Manage App Automation Tokens](https://shopify.dev/docs/apps/build/dev-dashboard/app-automation-tokens).

***

## Find your credentials

Your credentials are available in the Dev Dashboard:

1. Open the [Dev Dashboard](https://shopify.dev/docs/apps/build/dev-dashboard).
2. Click **Apps** and select your app.
3. Click **Settings**.
4. View or copy your client ID and secret under **Credentials**.

![Dev Dashboard settings page showing the Client ID and Secret fields.](https://shopify.dev/assets/assets/images/apps/dev-dashboard/app-settings-BERWjF61.png)

Your client ID is permanent and doesn't change. Your client secret must be kept secure. Treat it like a password. Shopify also signs your app's webhooks with it, so you use it to [verify that webhook requests are genuinely from Shopify](https://shopify.dev/docs/apps/build/webhooks/verify-deliveries#hmac-verification).

Your app uses these credentials to get an [access token](https://shopify.dev/docs/apps/build/authentication-authorization/access-tokens). If your app acts only on stores in your own organization, you can exchange them for a token directly. See [Authenticate an app for stores in your organization](https://shopify.dev/docs/apps/build/authentication-authorization/client-credentials-grant).

***

## Secure your credentials

* Never commit credentials to version control. Use environment variables or a secrets manager.
* Your client ID is safe to include in frontend code. Your client secret must never be exposed to the browser or included in client-side code.
* Rotate your client secret regularly, or immediately if you suspect it's been compromised.

***

## Rotate your client secret

Rotate your client secret if it's been exposed, if an employee with access has left your organization, and as part of regular security hygiene. You can rotate your secret without causing downtime for your app if you follow these steps in order.

The steps below avoid downtime, which is the right approach for routine rotation. If a secret is actively being misused, prioritize locking out the attacker over avoiding downtime: revoke the exposed secret immediately, before you generate and roll out a new one. Merchants lose access until the new secret is in place, but the leaked secret can't be used in the meantime.

**Caution:**

Don't revoke your old secret until you've updated all stored access tokens to use the new one. Revoking early can cause merchants to lose access to your app.

### Step 1: Generate a new secret

1. Open the [Dev Dashboard](https://shopify.dev/docs/apps/build/dev-dashboard).
2. Click **Apps** and select your app.
3. Click **Settings**.
4. In the **Credentials** section, click **Rotate** next to your client secret.
5. Click **Generate new secret** to confirm.

The new secret appears with a **New** label. Your old secret stays active until you revoke it.

### Step 2: Update webhook validation

Shopify signs webhooks with your app's oldest unrevoked client secret, so during rotation your webhooks keep being signed with the old secret until you revoke it. If your app [verifies webhook signatures](https://shopify.dev/docs/apps/build/webhooks/verify-deliveries), update your verification logic to accept signatures from both the old and new secret during the transition. Don't switch to validating with only the new secret until after you revoke the old one in the final step, or you'll reject genuine webhooks.

### Step 3: Update your app to use the new secret

Update your app's environment configuration to use the new client secret for all OAuth calls: token exchange, the authorization code grant, and refresh token requests. Don't revoke the old secret yet.

### Step 4: Replace access tokens minted under the old secret

An access token stays pinned to the secret that minted it, so every token your app has stored is still tied to the old one. Each of those tokens needs to be replaced with a token minted under the new secret before you revoke the old secret.

How a token gets replaced depends on how your app obtained it:

* **Token exchange**: The next exchange for a store returns a token pinned to the new secret, so coverage follows merchants opening your app.
* **Client credentials grant**: Request a new token using the new secret. Tokens from this grant last 24 hours, so they turn over on their own.
* **Expiring offline tokens**: Each store's token is pinned to the new secret when it refreshes. Let the refresh cycle run, or send a `grant_type=refresh_token` request for each store's stored refresh token to move every store at once.

**Info:**

If a refresh request times out, hits a network error, or returns a transient `5xx`, retry promptly with the same `refresh_token`. The repeated request returns the same rotated credentials rather than issuing another set, so a partial failure during a bulk pass doesn't cost you a store's token. Don't rely on a fixed retry-window duration. See [Refresh an expiring offline token](https://shopify.dev/docs/apps/build/authentication-authorization/implement-token-exchange#refresh-an-expiring-offline-token) for the full error behavior.

#### Re-pin a non-expiring offline token

A non-expiring offline token has no refresh token of its own, so none of the paths above reaches it. To move one to the new secret, use the rotation refresh token that the Dev Dashboard issues while two secrets are active.

Non-expiring offline tokens remain available to custom apps. Public apps must use expiring offline tokens, so if yours is public and still holds non-expiring tokens, re-pin them to finish rotation, then [migrate to expiring offline access tokens](https://shopify.dev/docs/apps/build/authentication-authorization/migrate-to-expiring-offline-access-tokens).

1. In the **Credentials** section, find **Refresh token** and click **Generate refresh token**. This section only appears while your app has more than one active secret, so you won't see it before Step 1 or after Step 5.
2. For each store, send the following request. Include `access_token` so that Shopify re-pins the existing token rather than running an OAuth refresh. No `grant_type` is needed.

## POST https://{shop}.myshopify.com/admin/oauth/access\_token

```text
Content-Type: application/x-www-form-urlencoded


client_id={your_client_id}
&client_secret={your_new_client_secret}
&refresh_token={refresh_token_from_dev_dashboard}
&access_token={access_token_to_re_pin}
```

The response contains a new access token, and the old one is destroyed, so store the response before moving to the next store. The token stays non-expiring. Repeated calls with the same access token within 10 seconds return the same result, so a retry after a network timeout is safe.

A rotation refresh token lasts one hour. If your app is installed on more stores than you can work through in that time, generate another one and continue where you left off.

**Info:**

[Admin-created custom apps](https://shopify.dev/docs/apps/build/authentication-authorization/legacy/admin-custom-apps) have no Dev Dashboard entry and no way to rotate a client secret, so this flow doesn't apply to them. To change their credentials, the merchant uninstalls and reinstalls the app.

### Step 5: Revoke the old secret

Once every stored access token has been replaced with one minted under the new secret, revoke the old secret in the Dev Dashboard. This finalizes rotation and destroys the old secret row. Any access tokens still pinned to the old secret stop working.

After revoking, update your webhook validation to accept only signatures from the new secret.

### Rotation and token refresh

Two different credentials are called a refresh token in this flow, and they aren't interchangeable:

* A **rotation refresh token** comes from the Dev Dashboard, covers your whole app, and lasts one hour. You send it with an existing `access_token` to re-pin that token to your new secret, as in Step 4.
* A **store's refresh token** is returned alongside an expiring offline access token, and your app stores one per store. You send it with `grant_type=refresh_token` to renew that store's access token before it expires. See [Refresh an expiring offline token](https://shopify.dev/docs/apps/build/authentication-authorization/implement-token-exchange#refresh-an-expiring-offline-token).

Rotating a secret invalidates every access token tied to the old secret, so it requires moving all of your stores. Refreshing a token renews one store's access token and leaves your credentials unchanged.

***

## Next steps

* Learn how your app exchanges its credentials for the [access token](https://shopify.dev/docs/apps/build/authentication-authorization/access-tokens) it sends on API requests.
* Use your client secret to [verify webhook requests](https://shopify.dev/docs/apps/build/webhooks/verify-deliveries#hmac-verification) genuinely came from Shopify.
* Create and rotate [App Automation Tokens](https://shopify.dev/docs/apps/build/dev-dashboard/app-automation-tokens), the separate credential that authenticates Shopify CLI in CI/CD.

***
