---
title: Storefront API
description: Contains objects used to interact with the Storefront API.
api_version: v1
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 API

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/latest/authenticate/public/app-proxy), and [`unauthenticated.storefront`](https://shopify.dev/docs/api/shopify-app-react-router/latest/unauthenticated/unauthenticated-storefront).

#### storefront

Provides utilities that apps can use to make requests to the Storefront API.

* **graphql**

  **GraphQLClient\<StorefrontOperations>**

  **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<Operation, Operations>
  ```

returns

```ts
interface Promise<T> {
    /**
     * 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<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<TResult1 | TResult2>;

    /**
     * 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<TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null): Promise<T | TResult>;
}, interface Promise<T> {}, Promise: PromiseConstructor, interface Promise<T> {
    readonly [Symbol.toStringTag]: string;
}, interface Promise<T> {
    /**
     * 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<T>;
}
```

### GraphQLQueryOptions

* apiVersion

  The version of the API to use for the request.

  ```ts
  unknown
  ```

* headers

  Additional headers to include in the request.

  ```ts
  Record<string, any>
  ```

* 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<Operation, Operations>
  ```

Examples

### Examples

* ####

  ##### Description

  Use \`storefront.graphql\` to make query / mutation requests.

  ##### app/routes/\*\*\\/.ts

  ```ts
  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

  ```ts
  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

  ```ts
  import { shopifyApp } from "@shopify/shopify-app-react-router/server";

  const shopify = shopifyApp({
    // ...
  });
  export default shopify;
  export const authenticate = shopify.authenticate;
  ```

***

## Related

[Authenticate requests from Shopify app proxies. - App proxy context](https://shopify.dev/docs/api/shopify-app-react-router/v1/authenticate/public/app-proxy)

[Interact with the Storefront API on non-Shopify requests. - Unauthenticated context](https://shopify.dev/docs/api/shopify-app-react-router/v1/unauthenticated/unauthenticated-storefront)

***
