# Scopes Contains functions used to manage scopes for your app. This object is returned on authenticated Admin requests. ## scopes Provides utilities that apps can use to [manage scopes](https://shopify.dev/docs/apps/build/authentication-authorization/app-installation/manage-access-scopes) for the app using the Admin API. ### ScopesApiContext The Scopes API enables embedded apps and extensions to request merchant consent for access scopes. ### query value: `() => Promise` - ScopesDetail: export interface ScopesDetail { /** * The scopes that have been granted on the shop for this app */ granted: Scope[]; /** * The required scopes that the app has declared in its configuration */ required: Scope[]; /** * The optional scopes that the app has declared in its configuration */ optional: Scope[]; } Queries Shopify for the scopes for this app on this shop ### request value: `(scopes: string[]) => Promise` Requests the merchant to grant the provided scopes for this app on this shop Warning: This method performs a server-side redirect. ### revoke value: `(scopes: string[]) => Promise` - ScopesRevokeResponse: export interface ScopesRevokeResponse { /** * The scopes that have been revoked on the shop for this app */ revoked: Scope[]; } Revokes the provided scopes from this app on this shop Warning: This method throws an [error](https://shopify.dev/docs/api/admin-graphql/unstable/objects/AppRevokeAccessScopesAppRevokeScopeError) if the provided optional scopes contains a required scope. ### ScopesDetail ### granted value: `string[]` The scopes that have been granted on the shop for this app ### optional value: `string[]` The optional scopes that the app has declared in its configuration ### required value: `string[]` The required scopes that the app has declared in its configuration ### ScopesRevokeResponse ### revoked value: `string[]` The scopes that have been revoked on the shop for this app ## Related - [Admin context](https://shopify.dev/docs/api/shopify-app-remix/authenticate/admin) ## Examples Contains functions used to manage scopes for your app. This object is returned on authenticated Admin requests. ### query Call `scopes.query` to get scope details.```typescript import type { LoaderFunctionArgs } from "@remix-run/node"; import { useLoaderData } from "@remix-run/react"; import { authenticate } from "../shopify.server"; import { json } from "@remix-run/node"; export const loader = async ({ request }: LoaderFunctionArgs) => { const { scopes } = await authenticate.admin(request); const scopesDetail = await scopes.query(); return json({ hasWriteProducts: scopesDetail.granted.includes('write_products'), }); }; export default function Index() { const {hasWriteProducts} = useLoaderData(); ... } ``` ### request Call `scopes.request` to request optional scopes.```typescript import type { ActionFunctionArgs } from "@remix-run/node"; import { useFetcher } from "@remix-run/react"; import { authenticate } from "../shopify.server"; import { json } from "@remix-run/node"; // Example of an action to POST a request to for optional scopes export const action = async ({ request }: ActionFunctionArgs) => { const { scopes } = await authenticate.admin(request); const body = await request.formData(); const scopesToRequest = body.getAll("scopes") as string[]; // If the scopes are not already granted, a full page redirect to the request URL occurs await scopes.request(scopesToRequest); // otherwise return an empty response return json({}); }; export default function Index() { const fetcher = useFetcher(); const handleRequest = () => { fetcher.submit({scopes: ["write_products"]}, { method: "POST", }); }; ... } ``` ### revoke Call `scopes.revoke` to revoke optional scopes.```typescript import type { ActionFunctionArgs } from "@remix-run/node"; import { useFetcher } from "@remix-run/react"; import { authenticate } from "../shopify.server"; import { json } from "@remix-run/node"; // Example of an action to POST optional scopes to revoke export const action = async ({ request }: ActionFunctionArgs) => { const { scopes } = await authenticate.admin(request); const body = await request.formData(); const scopesToRevoke = body.getAll("scopes") as string[]; const revokedResponse = await scopes.revoke(scopesToRevoke); return json(revokedResponse); }; export default function Index() { const fetcher = useFetcher(); const handleRevoke = () => { fetcher.submit({scopes: ["write_products"]}, { method: "POST", }); }; ... } ``` ## Examples Contains functions used to manage scopes for your app. This object is returned on authenticated Admin requests. ### query Call `scopes.query` to get scope details.```typescript import type { LoaderFunctionArgs } from "@remix-run/node"; import { useLoaderData } from "@remix-run/react"; import { authenticate } from "../shopify.server"; import { json } from "@remix-run/node"; export const loader = async ({ request }: LoaderFunctionArgs) => { const { scopes } = await authenticate.admin(request); const scopesDetail = await scopes.query(); return json({ hasWriteProducts: scopesDetail.granted.includes('write_products'), }); }; export default function Index() { const {hasWriteProducts} = useLoaderData(); ... } ``` ### request Call `scopes.request` to request optional scopes.```typescript import type { ActionFunctionArgs } from "@remix-run/node"; import { useFetcher } from "@remix-run/react"; import { authenticate } from "../shopify.server"; import { json } from "@remix-run/node"; // Example of an action to POST a request to for optional scopes export const action = async ({ request }: ActionFunctionArgs) => { const { scopes } = await authenticate.admin(request); const body = await request.formData(); const scopesToRequest = body.getAll("scopes") as string[]; // If the scopes are not already granted, a full page redirect to the request URL occurs await scopes.request(scopesToRequest); // otherwise return an empty response return json({}); }; export default function Index() { const fetcher = useFetcher(); const handleRequest = () => { fetcher.submit({scopes: ["write_products"]}, { method: "POST", }); }; ... } ``` ### revoke Call `scopes.revoke` to revoke optional scopes.```typescript import type { ActionFunctionArgs } from "@remix-run/node"; import { useFetcher } from "@remix-run/react"; import { authenticate } from "../shopify.server"; import { json } from "@remix-run/node"; // Example of an action to POST optional scopes to revoke export const action = async ({ request }: ActionFunctionArgs) => { const { scopes } = await authenticate.admin(request); const body = await request.formData(); const scopesToRevoke = body.getAll("scopes") as string[]; const revokedResponse = await scopes.revoke(scopesToRevoke); return json(revokedResponse); }; export default function Index() { const fetcher = useFetcher(); const handleRevoke = () => { fetcher.submit({scopes: ["write_products"]}, { method: "POST", }); }; ... } ```