Executive summary
- What changed: From Admin GraphQL API version 2027-01, apps that use Shopify-managed installation can call appDowngradeAccessScopes to replace optional write scopes with their matching read scopes.
- Why it happened: Revoking a write scope previously removed read access along with it when the read scope had only been granted implicitly through the write scope. This mutation closes that gap, so an app can shed write access while keeping the read access it still needs.
- Who should care: Teams maintaining custom or private apps that declare optional write scopes. No action is required for existing apps.
What changed
The mutation operates only on the calling app's own installation, which is a sensible constraint and worth stating plainly. The scopes you pass must be declared in optional_scopes, must be write scopes, and must have a matching read scope. Required scopes cannot be downgraded. Write scopes that are not currently granted are simply ignored.
Validation is all or nothing. If any requested scope fails validation the whole request is rejected and the installation's scopes stay unchanged, which means you will not end up in a half-applied state. The response returns a downgraded field listing the write scopes that were successfully changed, alongside userErrors for anything that failed. A call downgrading write_products to read_products is a single mutation returning the downgraded handles.
Why it matters
This is a developer convenience rather than a merchant feature, and its value is least-privilege hygiene. Enterprise apps accumulate scopes: a write scope requested for a one-time backfill tends to stay granted indefinitely, because removing it risked the read access other parts of the app still depended on. That made the safe choice look expensive, so teams left write access in place.
For a Plus merchant, the relevant question is governance. Each app holding write access to products, orders, or customers is a surface that appears in security reviews and vendor assessments. Being able to narrow scopes without a reinstall makes periodic access review a realistic practice rather than an aspiration, which matters most for custom Shopify apps built years ago and still running. If you request a scope list from your app vendors annually, this is the mechanism that lets them actually act on the result.
Role-specific impact
- Marketers: No impact. No app behaviour changes unless a developer deliberately downgrades a scope, and app functionality that depends on read access is preserved by design.
- Developers: If your app uses Shopify-managed installation and declares optional write scopes it no longer needs, call appDowngradeAccessScopes with those scopes once you are on 2027-01. Check userErrors rather than assuming success, and remember that only optional scopes with a matching read counterpart qualify.
- Store admins: Nothing to configure. The useful consequence is that when you ask an internal team or vendor to reduce an app's permissions, narrowing write to read is now a supported operation instead of a reinstall conversation.
Use-case example
Real-world scenario
A merchant runs a private app built three years ago to sync a product catalogue from a PIM. It holds write_products because it once performed the initial load and ongoing enrichment. Enrichment has since moved to middleware, so the app only reads product data to build a reconciliation report, yet it still carries write access to roughly 14,000 products. Under the old behaviour, revoking write_products would have removed the read access the report relies on, so the scope stayed. With this mutation the team downgrades to read_products in a single call, the report keeps working, and one app with unnecessary write access to the whole catalogue drops off the next security review.
Implementation checklist
- Confirm the app uses Shopify-managed installation, since the mutation does not apply otherwise.
- List currently granted scopes and identify write scopes that are no longer exercised by any code path.
- Check that each candidate is declared in optional_scopes and has a matching read scope, because required scopes cannot be downgraded.
- Upgrade the app to Admin GraphQL API version 2027-01 when it becomes available.
- Call appDowngradeAccessScopes with the target write scopes and inspect both downgraded and userErrors in the response.
- Exercise the app's read paths afterwards to confirm nothing depended on write access implicitly.
- Record the resulting scope set so the next access review starts from a known baseline.
FAQ
- Q: Is this urgent?
- A: No. Shopify states no action is required for existing apps. It is an opportunity to tighten permissions on your own schedule, not a breaking change with a deadline.
- Q: What happens if one scope in the request is invalid?
- A: The entire request is rejected and the installation's scopes remain unchanged. Validation failures surface in userErrors, so you can correct the list and retry without worrying about a partially applied downgrade.
Resources
appDowngradeAccessScopes mutation reference
Need guidance? Talk to Makro.