I’m implementing a Payments App. After marking a payment session as pending (paymentSessionPending
, which works), I immediately call paymentSessionModal
to show a QR modal after checkout.
Both paymentSessionPending
and paymentSessionModal
mutations require the write_payment_sessions
access scope. However, only paymentSessionPending
works; calling paymentSessionModal
always fails.
The paymentSessionModal
mutation always returns:
{
"errors": [
{
"message": "Access denied for paymentSessionModal field. Required access: `write_payment_sessions` access scope.",
"locations": [
{
"line": 1,
"column": 87
}
],
"path": [
"paymentSessionModal"
],
"extensions": {
"code": "ACCESS_DENIED",
"documentation": "https://shopify.dev/api/usage/access-scopes",
"requiredAccess": "`write_payment_sessions` access scope."
}
}
]
}
The same access token works for paymentSessionPending
right before this.
Both use the same session ID, same shop, same endpoint call and require the same access scope.
Extra info
-
Endpoint:
https://{shop}/payments_apps/api/2025-07/graphql.json
-
Access Token Scopes (via
/admin/oauth/access_scopes.json
):
{
"access_scopes": [
{ "handle": "read_orders" },
{ "handle": "read_payment_gateways" },
{ "handle": "write_orders" },
{ "handle": "write_payment_gateways" },
{ "handle": "write_payment_sessions" },
{ "handle": "write_products" },
{ "handle": "read_payment_sessions" },
{ "handle": "read_products" }
]
}
- Available mutations
Querying the schema at:
https://{{shop}}/payments_apps/api/2025-07/graphql.json
With:
{
__type(name: "MutationRoot") {
fields {
name
}
}
}
returns paymentSessionModal as available in the list of mutations:
{ "name": "paymentSessionModal" }