👀 Our most exciting product launch yet 🚀 Join us May 8th for Sanity Connect
Back to changelog

GraphQL API v2023-08-01

v2023-08-01 is the first update to the Sanity GraphQL API to include breaking changes, and is released as an opt-in upgrade. Your existing projects that query the previous version – v1 – will continue to work as before, and you don’t need to take any action until you are ready to upgrade.

To start using the newest version, please ensure that you have read the section titled Breaking Changes below. Once you are ready, change your query endpoints as follows:

// Old endpoints
https://<yourProjectId>.api.sanity.io/v1/graphql/<dataset>/<tag>
https://<yourProjectId>.apicdn.sanity.io/v1/graphql/<dataset>/<tag>

// New endpoints 
https://<yourProjectId>.api.sanity.io/v2023-08-01/graphql/<dataset>/<tag>
https://<yourProjectId>.apicdn.sanity.io/v2023-08-01/graphql/<dataset>/<tag>

New features

This update adds GraphQL support for several recently added Content Lake features:

Perspectives

Content Source Maps

Visual Editing

Read the updated GraphQL docs to learn how to get started with these features!

Breaking changes

This update also introduces several adjustments to how queries are executed, which could potentially impact your query results. Before updating any of your existing v1 queries, make sure you have reviewed the following list of changes:

Change 1: Empty Match Operator

Previously, empty match patterns would evaluate as true and return all instances of the relevant type. Going forth, they will evaluate to false, resulting in no output.

v1 Behavior

Given the following query, v1 would return all posts:

query {
  allPost(where: {
    title: {
      matches: ""
    }
  }) {
    title
  }
}

v2023-08-01 Behavior:

In v2023-08-01, the same query now returns no results.

Replicate v1 Behavior:

To replicate the behavior of v1, remove the empty match filter.

Change 2: Processing of Match Patterns

The method for processing match patterns has changed. Match patterns are now tokenized into terms, and all terms must be present for a match.

v1 Behavior:

In v1, this query would return posts where any of the words “quick”, “brown”, or “dog” were found in the title:

query {
  allPost(where: {
    title: {
      matches: "quick brown dog"
    }
  }) {
    title
  }
}

v2023-08-01 Behavior:

In v2023-08-01, the same query will only return posts where the title contains all three words: “quick”, “brown”, and “dog”.

Replicate v1 Behavior:

The v1 behavior of matching individual words in a string cannot be replicated in v2023-08-01.

Change 3: Negative Limits

The handling of negative limits has been improved to better align with user expectations.

v1 Behavior:

In v1, negative values for the 'limit' parameter did not have the perhaps intuitive effect of reversing the direction of the limit. For example, one might expect that a 'limit' of -1 would exclude the last item from the result set. However, this was not the case, and the following query would return all results:

query {
  allPost(limit: -1, offset: 0, sort: { _createdAt: DESC }) {
    title
  }
}

v2023-08-01 Behavior:

In v2023-08-01, this query now operates as one might intuitively expect: a 'limit' of -1 effectively excludes the last item from the result set.

Change 4: Null Ordering

The handling of null values when sorting has changed.

v1 Behavior:

In v1, when sorting documents by a field, if that field contained a null value, the document would not be returned in the query result. For example, consider this query sorting by _createdAt:

query {
  allPost(limit: 3, sort: { _createdAt: DESC }) {
    title
  }
}

If _createdAt is null, the document will not be returned.

v2023-08-01 Behavior:

In v2023-08-01, matching documents that have _createdAt set to null are placed first in the returned results.

Replicate v1 Behavior:

With this release we have also added a new filter called is_defined you can use this to remove null values from responses.

query {
  allPost(
    where: { _createdAt: { is_defined: true } }
    limit: 3
    sort: { _createdAt: DESC }
  ) {
    title
  }
}

Custom Role Impact

Custom roles that use custom content resources defined as a GROQ filter will be impacted by the move to the new GraphQL API version.

With the new GraphQL API version it now uses GROQ version v2021-03-25 to apply the custom content resource GROQ filter as opposed to v1. As such you must inspect the breaking changes to understand if your GROQ filter will continue to work as expected and update it if needed.

For example, one example is this custom content resource GROQ filter:

foo[].bar == 'something'

In v1 this would have returned documents where any foo.bar equals “something"

This behaves differently in v2021-03-21. Using an equality operator with an array traversal is not supported and will return empty results. Instead, these should be rewritten to use the in operator:

'something' in foo[].bar

A negation of an array traversal expression, e.g., !(foo[].bar == 'something'), is also impacted in version v2021-03-25. In this version, an equality operation on an array traversal will result in false, so the negation will evaluate to true. Therefore, in v2021-03-21, negating the original expression will return all documents.

Documentation affected by this release

Published August 08, 2023