Admin GraphQL API 2027-01 / New mutation

appDowngradeAccessScopes
Apps can now downgrade permissions from write to read

Apps using Shopify-managed installation can replace any optional write scope with its corresponding read scope. This lets them give up write access without losing read access. No action is required for existing apps.

On this page
  1. What's changing (30-second overview)
  2. How it works: Revoke vs. Downgrade
  3. Validation rules
  4. Revoke vs. Downgrade comparison
  5. Which apps this applies to
  6. How to use it (3 steps + code example)
  7. 5 key points for developers
  8. 3 practical use cases
  9. One-line summary for proposals

1What's changing

Admin GraphQL API 2027-01 onward, a new mutation, appDowngradeAccessScopes , is available.
It lets apps replace any optional write scope with its corresponding read scope . No action is required for existing apps.

Before: Revoke was the only option

appRevokeAccessScopes : revoking a write scope with it also removes any read access that was granted only through that write scope.

Now: You can choose Downgrade

appDowngradeAccessScopes drops only the write scope and keeps the corresponding read scope. For example: write_products → read_products.

2How it works: Revoke vs. Downgrade

Current permissions write_products (read is granted via write) appRevokeAccessScopes After Revoke write_products ✕ read access is also ✕ appDowngradeAccessScopes After Downgrade write_products ✕ read_products ✓ Can no longer read product data Not suitable if you need read Can still read product data Only create/update is blocked
Rule of thumb : If read access is granted only through a write scope, revoking it removes read access too.If your app still needs read access, use Downgrade, as the changelog explicitly states.

3Validation rules

optional
Declared in optional_scopes
Optional scopes only
W R
A write scope with a matching read
write → read of the same name
Required scopes not allowed
Required scopes can't be downgraded
Ungranted write scopes are ignored
Skipped without an error
All or nothing : if any of the requested scopes fails validation, the entire request is rejected, and the installation's scopes stay unchanged. The change only affects the calling app's own installation.

4Revoke vs. Downgrade

ItemappRevokeAccessScopesappDowngradeAccessScopes
write scope Removed Removed
read granted only through write Removed along with it Replaced with the matching read and kept
Best for You no longer need access to the resource at all You no longer need to write, but still need to read
Available versions Not specified 2027-01~ Admin GraphQL API

5Eligible apps

Uses Shopify-managed installation

Applies to apps that let Shopify manage installation and scopes.

Declares an optional write scope and its matching read

The app must have an optional write scope and the matching read scope.

No action needed for existing apps.This is an opt-in feature: only apps that want it need to call it on API 2027-01 or later.

6How to use it (3 steps + code example)

1

Find write scopes you no longer need

List the optional write scopes you no longer need for creating or updating data.

2

Call the mutation

On API 2027-01 or later, call appDowngradeAccessScopes with the target scopes.

3

Check the result

downgraded lists the successfully changed scopes;userErrors explains any failures.

mutation { appDowngradeAccessScopes(scopes: ["write_products"]) { downgraded { handle } userErrors { field message } } }
downgraded

Write scopes successfully downgraded

For the successfully changed write scopes, handle is returned.

userErrors

Validation failure

field and message show what failed. If even one item fails, the entire request is rejected.

75 key points for engineers

2027-01

1. Available only from API version 2027-01

Earlier versions can't call it. Using it requires upgrading your API version.

optional

2. Only optional_scopes are eligible

Required scopes can't be downgraded. Any write scope you might later downgrade should be declared in optional_scopes from the start.

ALL NONE

3. Validation is atomic

If any entry is invalid, the whole request is rejected and no scopes change. When passing multiple scopes at once, handling userErrors is essential.

4. Ungranted write scopes are ignored

Write scopes that aren't currently granted are ignored rather than raising an error. To see what actually changed, check downgraded .

5. Don't confuse Revoke with Downgrade

appRevokeAccessScopes revokes the write scope and also removes any read access that was granted only through it.If code still relies on read access (sync, display, etc.), choose Downgrade. The change affects only the calling app's own installation.

83 business use cases

USE CASE 1

Moving to least privilege (giving up write access you no longer use)

Challenge
The app used to create and update products, but that feature has been removed.write_products is still granted, though the app still reads product data.
Approach
appDowngradeAccessScopes(scopes: ["write_products"]) is called to downgrade the scope toread_products .
Impact
Drop only the unneeded write access without disrupting read-based features.
Tech notes
write_products must be declared in optional_scopes. If it's required, it can't be downgraded.
W R
USE CASE 2

Implementing gradual feature reduction as a "read-only mode"

Challenge
You want to disable in-app editing and allow viewing only. Revoking would remove read access too, breaking the viewing features.
Approach
When disabling editing, downgrade the corresponding optional write scopes.
Impact
Align permissions with what the app actually does while keeping read access intact.
Technical notes
Clarify the difference from Revoke (whether read access remains) at the design stage. Choose between them based on whether you still need read access.
userErrors
USE CASE 3

Safely build in bulk downgrades of multiple scopes

Challenge
You want to downgrade several write scopes at once, but avoid a half-applied state where only some changes take effect.
Approach
Pass multiple scopes in a single call, then check whetheruserErrors is empty, and inspectdowngraded to see what was returned.
Impact
If even one scope fails, the entire request is rejected, so scope state is never partially changed.
Technical notes
Write scopes the app hasn't been granted are ignored (no error), so determine the outcome from the contents of downgraded rather than from what you passed in.

9One-line summary for proposals

"Starting with API 2027-01, apps can downgrade any write scope to its corresponding read scope.
A new mutation for least privilege that lets apps give up write access while keeping read access.
No action is required for existing apps; only apps that need it have to use it."