---
title: Storefront API
description: How the template calls Shopify's Storefront GraphQL API - the fetch client, query patterns, caching, and error handling.
type: reference
prerequisites:
  - /docs/getting-started
---

# Storefront API



The template uses [Shopify Hydrogen](https://www.npmjs.com/package/@shopify/hydrogen) for Storefront GraphQL API queries and mutations. Configure its domain, public token, and API version with the variables in [Environment Variables](/docs/reference/env-vars). Grant the scopes in [Storefront API Permissions](/docs/reference/storefront-api-permissions).

The Customer Account API uses a separate endpoint, schema, client ID, and session secret. Storefront API codegen does not validate Customer Account API operations.

## Write and validate operations

Define each operation as a static `#graphql` document and pass dynamic values as GraphQL variables. Do not interpolate runtime values or conditional fields into the document.

Include Shopify's `@inContext` directive when localized pricing or content depends on country and language:

```ts
const GET_PRODUCT_QUERY = `#graphql
  query getProduct(
    $handle: String!
    $country: CountryCode
    $language: LanguageCode
  ) @inContext(country: $country, language: $language) {
    productByHandle(handle: $handle) {
      id
      title
    }
  }
` as const;
```

Validate current field names, arguments, and types with Shopify AI Toolkit. Then use the [`shopify-graphql-reference` skill](/docs/skills/shopify-graphql-reference) for template integration conventions. The skill is not a schema source.

## Codegen

Use this [codegen](#codegen) contract while editing an operation. The template runs [`@shopify/api-codegen-preset`](https://www.npmjs.com/package/@shopify/api-codegen-preset):

```bash
pnpm --filter template codegen
```

Codegen reads `SHOPIFY_API_VERSION` and fails when an operation does not match Shopify's live schema. Development runs codegen without blocking startup, while the production build treats failure as a hard error. Generated validation files are gitignored.

## Caching

Choose caching by data sensitivity and behavior:

| Data or operation                                          | Cache contract                                                |
| ---------------------------------------------------------- | ------------------------------------------------------------- |
| Public product, collection, menu, or content data          | Cache and invalidate when Shopify changes                     |
| Public results that vary by filters, search, or pagination | Share only when the cache key includes every varying input    |
| Cart, session, authorization, or customer data             | Keep request-scoped or private; never place in a public cache |
| Mutations                                                  | Do not cache                                                  |

Webhook-driven invalidation keeps cached Shopify content current. Configure `POST /api/webhooks/shopify` as described in [Webhooks](/docs/anatomy/webhooks).

## Mutations

Cart mutations are uncached and return the updated cart. Use the returned cart instead of issuing a follow-up read.

Never cache cart IDs, customer data, session data, or authenticated responses in a shared public cache.

## Errors and missing resources

Storefront requests throw on transport failures, timeouts, and GraphQL failures without usable data. A response with both data and GraphQL errors logs a warning and allows the operation to use the partial data.

A missing resource is not an API failure. Read operations return `undefined`, `null`, or an empty list when the requested resource does not exist.

Set `DEBUG_SHOPIFY=true` to include structured Storefront and Customer Account API operation timings in server logs. Warnings and errors remain enabled when debug logging is off.


---

For a semantic overview of all documentation, see [/sitemap.md](/sitemap.md)

For an index of all available documentation, see [/llms.txt](/llms.txt)

For agent-facing discovery, including API and MCP surfaces, see [/agents.md](/agents.md)