Skip to main content

Scopes
object

Contains functions used to manage scopes for your app.

This object is returned on authenticated Admin requests.

Provides utilities that apps can use to manage scopes for the app using the Admin API.

() => Promise<>
required

Queries Shopify for the scopes for this app on this shop

(scopes: string[]) => Promise<void>
required

Requests the merchant to grant the provided scopes for this app on this shop

Warning: This method performs a server-side redirect.

(scopes: string[]) => Promise<>
required

Revokes the provided scopes from this app on this shop

Warning: This method throws an error if the provided optional scopes contains a required scope.

Was this section helpful?

Call scopes.query to get scope details.

Was this section helpful?

Query for granted scopes

/app._index.tsx

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<typeof loader>();

...
}

Was this section helpful?

Request consent from the merchant to grant the provided scopes for this app

/app/routes/app.request.tsx

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<typeof action>();

const handleRequest = () => {
fetcher.submit({scopes: ["write_products"]}, {
method: "POST",
});
};

...
}

Call scopes.revoke to revoke optional scopes.

Was this section helpful?

Revoke optional scopes

/app._index.tsx

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<typeof action>();

const handleRevoke = () => {
fetcher.submit({scopes: ["write_products"]}, {
method: "POST",
});
};

...
}