--- title: Storefront API description: |- Contains objects used to interact with the Storefront API. This object is returned as part of different contexts, such as [`appProxy`](/docs/api/shopify-app-react-router/authenticate/public/app-proxy), and [`unauthenticated.storefront`](/docs/api/shopify-app-react-router/unauthenticated/unauthenticated-storefront). api_version: v1 latest api_name: shopify-app-react-router source_url: html: https://shopify.dev/docs/api/shopify-app-react-router/latest/apis/storefront-api md: https://shopify.dev/docs/api/shopify-app-react-router/latest/apis/storefront-api.md --- # Storefront APIobject Contains objects used to interact with the Storefront API. This object is returned as part of different contexts, such as [`appProxy`](https://shopify.dev/docs/api/shopify-app-react-router/authenticate/public/app-proxy), and [`unauthenticated.storefront`](https://shopify.dev/docs/api/shopify-app-react-router/unauthenticated/unauthenticated-storefront). ## storefront Provides utilities that apps can use to make requests to the Storefront API. * graphql GraphQLClient\ required Method for interacting with the Shopify Storefront GraphQL API If you're getting incorrect type hints in the Shopify template, follow [these instructions](https://github.com/Shopify/shopify-app-template-react-router/tree/main#incorrect-graphql-hints). ### GraphQLClient * query ```ts Operation extends keyof Operations ``` * options ```ts GraphQLQueryOptions ``` interface Promise\ { /\*\* \* Attaches callbacks for the resolution and/or rejection of the Promise. \* @param onfulfilled The callback to execute when the Promise is resolved. \* @param onrejected The callback to execute when the Promise is rejected. \* @returns A Promise for the completion of which ever callback is executed. \*/ then\(onfulfilled?: ((value: T) => TResult1 | PromiseLike\) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike\) | undefined | null): Promise\; /\*\* \* Attaches a callback for only the rejection of the Promise. \* @param onrejected The callback to execute when the Promise is rejected. \* @returns A Promise for the completion of the callback. \*/ catch\(onrejected?: ((reason: any) => TResult | PromiseLike\) | undefined | null): Promise\; }, interface Promise\ {}, Promise: PromiseConstructor, interface Promise\ { readonly \[Symbol.toStringTag]: string; }, interface Promise\ { /\*\* \* Attaches a callback that is invoked when the Promise is settled (fulfilled or rejected). The \* resolved value cannot be modified from the callback. \* @param onfinally The callback to execute when the Promise is settled (fulfilled or rejected). \* @returns A Promise for the completion of the callback. \*/ finally(onfinally?: (() => void) | undefined | null): Promise\; } ```ts interface Promise { /** * Attaches callbacks for the resolution and/or rejection of the Promise. * @param onfulfilled The callback to execute when the Promise is resolved. * @param onrejected The callback to execute when the Promise is rejected. * @returns A Promise for the completion of which ever callback is executed. */ then(onfulfilled?: ((value: T) => TResult1 | PromiseLike) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike) | undefined | null): Promise; /** * Attaches a callback for only the rejection of the Promise. * @param onrejected The callback to execute when the Promise is rejected. * @returns A Promise for the completion of the callback. */ catch(onrejected?: ((reason: any) => TResult | PromiseLike) | undefined | null): Promise; }, interface Promise {}, Promise: PromiseConstructor, interface Promise { readonly [Symbol.toStringTag]: string; }, interface Promise { /** * Attaches a callback that is invoked when the Promise is settled (fulfilled or rejected). The * resolved value cannot be modified from the callback. * @param onfinally The callback to execute when the Promise is settled (fulfilled or rejected). * @returns A Promise for the completion of the callback. */ finally(onfinally?: (() => void) | undefined | null): Promise; } ``` ```ts < Operation extends keyof Operations, >( query: Operation, options?: GraphQLQueryOptions, ) => Promise> ``` ### GraphQLQueryOptions * apiVersion The version of the API to use for the request. ```ts ApiVersion ``` * headers Additional headers to include in the request. ```ts Record ``` * signal An optional AbortSignal to cancel the request. ```ts AbortSignal ``` * tries The total number of times to try the request if it fails. ```ts number ``` * variables The variables to pass to the operation. ```ts ApiClientRequestOptions["variables"] ``` ```ts export interface GraphQLQueryOptions< Operation extends keyof Operations, Operations extends AllOperations, > { /** * The variables to pass to the operation. */ variables?: ApiClientRequestOptions['variables']; /** * The version of the API to use for the request. */ apiVersion?: ApiVersion; /** * Additional headers to include in the request. */ headers?: Record; /** * The total number of times to try the request if it fails. */ tries?: number; /** * An optional AbortSignal to cancel the request. */ signal?: AbortSignal; } ``` ## Examples ### graphql Querying the GraphQL API Use `storefront.graphql` to make query / mutation requests. Handling GraphQL errors Catch `GraphqlQueryError` errors to see error messages from the API. ### Examples * #### Querying the GraphQL API ##### Description Use \`storefront.graphql\` to make query / mutation requests. ##### app/routes/\*\*\\/.ts ```typescript import { json } from "react-router"; import { authenticate } from "../shopify.server"; export async function action({ request }: ActionFunctionArgs) { const { storefront } = await authenticate.public.appProxy(request); const response = await storefront.graphql(`{blogs(first: 10) { edges { node { id } } } }`); return (await response.json()); } ``` * #### Handling GraphQL errors ##### Description Catch \`GraphqlQueryError\` errors to see error messages from the API. ##### /app/routes/\*\*\\/\*.ts ```typescript import { ActionFunctionArgs } from "react-router"; import { authenticate } from "../shopify.server"; export const action = async ({ request }: ActionFunctionArgs) => { const { storefront } = await authenticate.public.appProxy(request); try { const response = await storefront.graphql( `#graphql query incorrectQuery { products(first: 10) { nodes { not_a_field } } }`, ); return ({ data: await response.json() }); } catch (error) { if (error instanceof GraphqlQueryError) { // { errors: { graphQLErrors: [ // { message: "Field 'not_a_field' doesn't exist on type 'Product'" } // ] } } return ({ errors: error.body?.errors }, { status: 500 }); } return ({ message: "An error occurred" }, { status: 500 }); } } ``` ##### /app/shopify.server.ts ```typescript import { shopifyApp } from "@shopify/shopify-app-react-router/server"; const shopify = shopifyApp({ // ... }); export default shopify; export const authenticate = shopify.authenticate; ``` ## Related [![](https://shopify.dev/images/icons/32/pickaxe-1.png)![](https://shopify.dev/images/icons/32/pickaxe-1-dark.png)](https://shopify.dev/docs/api/shopify-app-react-router/authenticate/public/app-proxy) [Authenticate requests from Shopify app proxies.App proxy context](https://shopify.dev/docs/api/shopify-app-react-router/authenticate/public/app-proxy) [![](https://shopify.dev/images/icons/32/pickaxe-1.png)![](https://shopify.dev/images/icons/32/pickaxe-1-dark.png)](https://shopify.dev/docs/api/shopify-app-react-router/unauthenticated/unauthenticated-storefront) [Interact with the Storefront API on non-Shopify requests.Unauthenticated context](https://shopify.dev/docs/api/shopify-app-react-router/unauthenticated/unauthenticated-storefront)