You’re trying to make a server-side Admin API call from your Remix loader, which is the right place for it. The App Bridge direct API access documentation you linked is for client-side calls directly from a React component running in the browser, where App Bridge handles injecting the authentication automatically.
For a server-side call like this, you need to explicitly include the access token in your request headers. Your prismaSession object should contain the accessToken that was granted during the OAuth flow.
Modify your fetch call to include the X-Shopify-Access-Token header:
const verificationUpdate = await fetch(`https://${prismaSession?.shop}/admin/api/2026-01/graphql.json`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Shopify-Access-Token': prismaSession?.accessToken // Make sure your session object has this
},
body: JSON.stringify({
query: `
mutation MetafieldsSet($metafields: [MetafieldsSetInput!]!) {
metafieldsSet(metafields: $metafields) {
metafields {
key
namespace
value
createdAt
updatedAt
}
userErrors {
field
message
code
}
}
}`,
variables : {
"metafields": [
{
"key": "sms_verification",
"namespace": "custom",
"ownerId": `gid://shopify/Order/${smsUpdate.order}`, // This needs to be a GID
"type": "boolean",
"value": "true",
}
]
}
})
})
Also, for setting metafields, the ownerId needs to be a Global ID (GID), not just a plain ID. So, if smsUpdate.order is a numeric ID, you’ll need to prefix it like gid://shopify/Order/${smsUpdate.order}.