Had been working on one app, it was working fine with auth and webhooks but after enabling public distribution, it started giving error with status code 403 ( Graphql : Forbidden error) .
Actions tried :
Reinstalling after a clean uninstall ( along with shopify app dev --reset)
Clearing the sqlite db and pouring again.
Installing as a completely new app
Scopes and API credentials double check
Tried with different store as well
After all these , the issue persisted .
Response : {
“success”: false,
“message”: “Received an error response (403 Forbidden) from Shopify:\n{\n “networkStatusCode”: 403,\n “message”: “GraphQL Client: Forbidden”,\n “response”: {\n “size”: 0,\n “timeout”: 0\n }\n}\nIf you report this error, please include this id: 34925334-4d93-49b9-a398-042dd7561bbf-1784229648”
}
The detail that stands out is that it only broke when you flipped distribution to public, and that a clean reinstall on a brand new store doesn’t fix it. Between them those rule out scopes and rule out your session data, which is most of what you’ve already tried. What’s left is the token itself.
Public apps created on or after April 1 2026 are required to request and use expiring offline access tokens. Custom apps are not, and that exemption is why everything worked right up until the moment you enabled public distribution. Nothing in your code changed, the rules being applied to your app changed. If your OAuth flow is still asking for a plain non-expiring offline token, you get a token back and then the Admin API declines it, which surfaces as exactly what you pasted: 403, GraphQL Client: Forbidden, no useful detail.
Cheap way to confirm before you touch anything. Look at the token response you store at install time. If all you have is an access_token, with no expires_at, no refresh_token and no refresh_token_expires_at sitting next to it, that’s the mismatch. On the raw OAuth side this is an expiring=1 parameter on the token request. If you’re on the Remix template you turn it on in the shopifyApp config rather than by hand, and you also need somewhere to put the refresh token, because the stock sqlite session schema has no columns for it. That’s likely why clearing the db and pouring it again changed nothing, the columns were never there.
Worth skipping one dead end: the popular guess for a 403 here is protected customer data. It isn’t that. Missing PCD access returns a 200 with the fields nulled out and the reason in the errors hash, not a blanket 403. Shopify staff have said the same on the dev forum, so if someone points you at PCD you can park it.
What does your stored session row actually hold after a fresh install, just the access token, or is there a refresh token next to it?
A 403 Forbidden error usually points to an authentication or app configuration issue.
Since this started after enabling Public Distribution I’d recommend verifying that your app was reinstalled with a fresh access token and that your shopify.app.toml settings (especially the Application URL and Redirect URLs) match your Partner Dashboard configuration.
If the issue persists across multiple stores and even a new app it’s worth contacting Shopify Support with the error ID so they can check the backend logs.
Just to clarify are all GraphQL Admin API requests failing or only specific queries or mutations?
A 403 GraphQL Forbidden right after switching to public distribution usually points to an authentication or app configuration issue rather than your code, especially if it was working before.
A few things I’d check:
Make sure you’re using the access token from the current installation if the app was reinstalled after changing distribution. Any old offline token is no longer valid.
Verify that the app was reinstalled with all the required scopes. If you added or changed scopes, merchants must reauthorize the app.
Confirm you’re calling the correct Admin GraphQL endpoint for the shop and API version.
Check whether the request is failing for all GraphQL queries or only specific ones. If it’s only certain queries, it could be a missing scope rather than a general auth issue.
Review the app logs in the Partner Dashboard for any authentication or permission errors.
Since you’re already testing multiple stores and even a fresh app, I’d also open a Shopify Partner Support ticket and include the Request ID. They can trace that ID internally and usually pinpoint the exact reason for the 403.
Only Shopify can inspect that internally, but from experience it usually indicates one of:
Invalid/expired access token.
Missing scopes
Protected Customer Data restriction.
Wrong API endpoint
App Configuration mismatch after changing distribution.