Storefront GraphQL API

With Nacelle's Storefront API headless composable merchants can request commerce and content data from a single, performant GraphQL API. This is possible because Nacelle ingests, normalizes, and stores data from the composable perspective.

Note: in the following, replace <YOUR_SPACE_ID> with the corresponding value from the API settings.

Sending Queries

Queries are sent via a POST request to: https://storefront.api.nacelle.com/graphql/v1/spaces/<YOUR_SPACE_ID>

Schema

Load the GraphQL in your preferred API client or use this cURL:

curl -X "POST" "https://storefront.api.nacelle.com/graphql/v1/spaces/<YOUR_SPACE_ID>" \
     -H 'Content-Type: application/json; charset=utf-8' \
     -d $'{
	"query": "fragment FullType on __Type{kind name fields(includeDeprecated:true){name args{...InputValue}type{...TypeRef}isDeprecated deprecationReason}inputFields{...InputValue}interfaces{...TypeRef}enumValues(includeDeprecated:true){name isDeprecated deprecationReason}possibleTypes{...TypeRef}}fragment InputValue on __InputValue{name type{...TypeRef}defaultValue}fragment TypeRef on __Type{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name}}}}}}}}query IntrospectionQuery{__schema{queryType{name}mutationType{name}types{...FullType}directives{name locations args{...InputValue}}}}"}'

Queries

  • allContent
    Query a list of content entries with Relay-style pagination

  • allProductCollections
    Query a list of ProductCollection entries with Relay-style pagination

  • allProducts
    Query a list of products entries with Relay-style pagination

  • navigation
    Get navigation groups for a space

  • spaceProperties: SpaceProperties!
    Space properties data for a space

These queries use our canonical commerce data model and input filters.

Note: querying for both nodes and edges in the same connection is not supported.

Example query

Query

query allContent($filter: ContentFilterInput) {
	allContent(filter: $filter) {
		totalCount
		pageInfo {
			endCursor
			hasNextPage
		}
		edges {
			node {
				nacelleEntryId
				handle
				fields
			}
		}
	}
}

Input filter

{
	"filter": {
		"first": 500,
		"entryDepth": 0,
		"locale": "en-US"
	}
}

Note that if duplicate handles or duplicate nacelleEntryIds are passed in the input filter, the Storefront GraphQL API will remove duplicates from the returned response and only return unique entities. So querying using the following two example input filters will return the same result:

Input filter with duplicate handles

{
	"filter": {
    "handles": ["apple", "apple", "banana", "apple"],
		"first": 500,
		"locale": "en-US"
	}
}

Input filter de-duplicated

{
	"filter": {
    "handles": ["apple", "banana"],
		"first": 500,
		"locale": "en-US"
	}
}

When constructing a request programmatically, it is advisable to avoid validating against an unguarded array of handles. Instead, it is recommended to dynamically generate the handles array from a set.

Automatic Persisted Queries (APQ)

Automatic Persisted Queries (APQ) is a request-level caching technique that relies on mutual cooperation between a GraphQL client, a GraphQL server, and (optionally) a Content Delivery Network (CDN). Nacelle's Storefront GraphQL API supports APQ with CDN caching. As a result, developers using an APQ-capable GraphQL client can enjoy data fetching in double-digit milliseconds for responses cached in Nacelle's CDN.

A diagram of the Automatic Persisted Queries (APQ) workflow between a GraphQL client and a GraphQL server

To enable APQ, the GraphQL client must be configured to support APQ requests with sha256 query hashing. If you're using the Nacelle Storefront SDK, version 2.x supports APQ out-of-the-box. If you're using a full-featured GraphQL client like urql, Apollo Client, or Relay, please follow the APQ docs specific to your GraphQL client:

Nacelle's CDN cache for APQ responses has a TTL of 60 seconds. After the TTL expires, the next request will be served directly from the Storefront GraphQL API, and the APQ + CDN cache will be repopulated.

Payload size limit

To improve the responsiveness of the Storefront GraphQL API experience, we enforce a payload size limit of 10 MB.

If a query would lead to a response above that limit, the request will fail with an error message indicating that the limit was exceeded.

It will also contain a suggestion on how to modify the query so that it can be retried by the client:

Maximum payload size exceeded.
Payload size must be less than 10 MB.
Reducing the number of entries queried could help (currently querying 500 entries per request).
Try re-requesting with 'filter.first: 250'.

Request timeout

We also enforce a request timeout after 20 seconds.

If a query exceeds this limit, the request will fail and the response will contain error messages indicating that the request timed out.

It will also contain a suggestion on how to modify the query so that it can be retried by the client:

Request timed out. Reducing the number of entries queried could help

Content resolution

Often, a piece of content references other pieces of content, eg a blog post overview page containing blog post titles and authors.

For allContent queries, you can define an entryDepth filter for your query that will govern how many levels of references will be resolved. The default value for entryDepth is 4 when not defined in the query filter.

Nested references

If a query would lead to a response above the payload size limit due to too many nested references, the request will fail with an error message indicating that the limit was exceeded.

It will also contain a suggestion on how to modify the query by reducing the entryDepth filter parameter.

Maximum payload size exceeded.
Payload size must be less than 10 MB.
Reached 10 MB at entry depth 6.
Reducing queried entry depth could help.
Try re-requesting with 'filter.entryDepth: 5’.

Informational messages when resolving Nacelle references

When querying for normalized content, the following messages might appear as part of the response for Nacelle references:

Cannot resolve circular structures

This will happen if the request would need to resolve a Nacelle reference as a circular reference.

Circular references can be found in content when a Nacelle reference points back to a previous reference in its path.

Resolution
  • Extract the nacelleEntryId or handle for circular references from the response and resolve them in a subsequent call using the nacelleEntryIds and/or handles filter for the GraphQL query.
  • Find the content of the reference in the response. By definition, the content of a circular reference is already present in the response and hence might be retrieved from it. If the schema for the content is readily available, this should be straightforward.
  • Change the content in the CMS. This can entail a lot of work and should be viewed as a possible long-term solution.

Cannot find Nacelle reference

For one reason or another, the requested Nacelle reference is not present in our system

Resolution
  • Check if the requested reference exists in the CMS.
  • If so, reindex the content.

Limit reached on how deep entries can be resolved

The reference cannot be resolved due to the entryDepth of the query.

Resolution
  • Increase the entryDepth in the filter for the GraphQL query. This is usually the fastest solution, but might lead to a payload size error.
  • Extract the nacelleEntryId or handle for the limited references from the response and resolve them in a subsequent call using the nacelleEntryIds and/or handles filter for the GraphQL query.
  • Restructure the content model in the CMS so that it does not require deeply nested references.

Troubleshooting

A request to the GraphQL API may respond with an error. Each error will provide a code and a message containing more details about the error.

Potential Error Codes:

BAD_USER_INPUT: The GraphQL variables are invalid. Make sure argument names and values match the query.

COMPLEXITY_ERROR: The complexity of your GraphQL query exceeds the specified limit.

GRAPHQL_PARSE_FAILED: The GraphQL query format is invalid. Make sure the query is structured correctly.

GRAPHQL_VALIDATION_FAILED: The GraphQL query contains a field that does not exist. Make sure the fields in the query exist for that object.

UNAUTHENTICATED:The request header is missing or contains incorrect space tokens. Make sure the headers are provided and correct.


What’s Next