Content Lake (Datastore)

GraphQL

Content Releases APIs and new perspective defaults

v2025-02-19

This release introduces new features and changes to support Content Releases. For more details on Content Releases, see the Studio release notes.

Breaking changes

The following items may break behavior in your applications. See the details below for further explanations and migration paths.

  • The default perspective has changed to only display published content.
  • Raw perspective requests now include versions. prefixed documents in addition to drafts. and published documents.
  • A bug in GROQ queries that caused empty keys to expand has been fixed. If you are relying on this behavior, see the details below.

versions.** documents are not returned in API versions prior to 2025-02-19. You must opt-in to this version to query versions-prefixed documents.

Highlights

Perspective changes

The default perspective has changed from raw to published. This includes:

  • /query now uses perspective=published by default.
  • GraphQL now uses perspective=published by default.

To return to the previous behavior, set perspective to raw.

New query perspectives

In addition to the existing named perspective values, you can also pass one or more release IDs to the query endpoint's perspective parameter. For example: perspective=release-a,release-b,release-c. This will give you a view on your dataset as if release-c had been published, followed by release-b and finally release-a. This is generalisation of the existing previewDrafts functionality to support Content Releases.

Learn more in the Content Releases API documentation.

New includeAllVersions parameter

The following endpoints now include a boolean includeAllVersions parameter. Set it to true and use an authenticated request to include all versions.

New path prefix for versions

Prior to 2025-02-19, queries on /query and similar APIs returned published documents and drafts.** documents when using the raw or previewDrafts perspectives. In 2025-02-19 and later, a versions.** path is introduced for Content Release document versions.

Gotcha

If you rely on path prefixes alone, you'll want to use perspectives instead to control which documents are returned by queries.

Additional Actions

The Actions API now includes actions for managing Content Releases. Along with this, actions such as sanity.action.document.discard and sanity.action.document.replaceDraft have been deprecated in favor of sanity.action.document.version.discard and sanity.action.document.version.replace.

See the Actions API reference for more details.

New GROQ functions

  • sanity::versionOf(documentID): Checks for versions of a provided document ID. Use inside a filter to return matching documents. For example: *[sanity::versionOf("abc123")].
  • sanity::partOfRelease(releaseID): Checks whether a document is part of a given release. For example, fetch all the version documents in release rel-summer using *[sanity::partOfReleases("rel-summer").
  • releases::all(): Returns all releases.

Learn more about these in the GROQ functions reference documentation.

New lastRevision parameter

The document history API now accepts a lastRevision parameter, which returns the current data for an existing document, or the last state before deletion for a deleted document.

Fix for empty key projection bug

This version also introduces a fix to a GROQ bug whereby empty keys in projections would expand into the object.

For example:

Input

{
  "": {
    "a": "b"
  }
}

response

{
  "a": "b"
}

This is corrected in 2025-02-19, and instead the query will return the following:

{
  "": {
    "a": "b"
  }
}

To replicate the older behavior in the new API version, update the empty string with the ellipsis operator (...). For example:

{
  ... {
    "a": "b"
  }
}

Deprecation Support for Documents and Fields, Comment Reactions ++

v3.26.0

Installation and upgrading

To initiate a new Studio without installing the CLI globally:

npm create sanity@latest

To upgrade a v3 Studio, run this command in its folder:

npm install sanity@latest

✨ Highlights

Deprecation support for Documents and Fields

This release introduces the option to mark document and field types as deprecated. This can be used to gently steer Studio users towards updated schemas or to phase out legacy fields without abrupt changes.

export const deprecatedDocument = defineType({
  name: 'deprecatedDocument',
  title: 'Deprecated Document',
  type: 'document',
  deprecated: {
    reason: 'Use the Author document type instead',
  },
  fields: [
    defineField({
      name: 'title',
      type: 'string',
      deprecated: {
        reason: 'This field was used in a legacy system and is no longer used.',
      },
    }),
  ],
})
 The image displays a user interface from Sanity Studio with a notification at the top. The notification is a warning message that reads, "This document type has been deprecated. Use the Author document type instead." Below the notification, there is a section titled "My Document" with a field labeled "Title," which contains the word "deprecated" highlighted in yellow. The subtitle under the field states "This field was used in a legacy system and is no longer used." The main content area has a text box with the placeholder text "My Document" in it.

When a field or document is deprecated, an informative message will appear in the Studio, clearly indicating the recommended action to take. This aids in maintaining a clean and up-to-date content structure.

Bonus: Deprecation messages now appear in the GraphQL schema, providing clarity during transitions. Deprecated document types and fields should be appropriately treated in documentation and tooling.

Reactions to Comments

This release also introduces a new layer of interactivity in the Studio with the ability for users to react to comments! 🎉

Far be it from us to speak ill of verbose and precise communication using full sentences, but sometimes you just want to express a sentiment quickly with a 🚀 or a 👍 and Sanity Studio now has you covered for those occasions. Streamline feedback processes and consensus building, and make your Studio a more vibrant collaborative space in one fell swoop with comment reactions. 🎩

Shows a comment section in Sanity Studio with a single comment. There are emoji reactions below the comment indicating that one person found the comment surprising (with an astonished face emoji), another found it funny (with a laughing face emoji), and one reacted with a rocket emoji. Next to the emojis, there is a button with a plus sign, possibly for adding more reactions. A small pop-up message is also visible saying, "You reacted with :rocket:" accompanied by the rocket emoji.

🐛 Notable bugfixes

  • Enhances user experience in the Studio by adding localized browser document titles and correcting unlocalized strings, accommodating users who prefer languages other than English.
  • Fixes an issue where number-like string flags passed to CLI commands were parsed as numbers by the option parser, leading to truncation of large integer-only document IDs and similar.
  • Resolves a restoration issue with the token login method ensuring the active session is retained post webpage reloads when cookieless auth is in effect.
  • Enhances UI components consistency in tooltips and delay groups for better UX.
  • Fixes a performance issue by re-applying useMemo on DocumentPaneContext values, reducing unnecessary re-renders and improving document pane performances.
  • Ensures that errors in the useFeatureEnabled hook result in an empty features list rather than disruptive error toasts; this minimizes user interruption when feature availability checks fail.
  • Fixes multiple bugs in the sanity documents validate CLI command relating to visibility, unnecessary validation reports, reference checks batch processing, and unknown field validation for images and file types.
  • Improves spacing between the published date and the last updated date in the document status bar for better readability.

Improvements and bugfixes

v3.15.0

Installation and upgrading

To initiate a new Studio without installing the CLI globally:

npm create sanity@latest

To upgrade a v3 Studio, run this command in its folder:

npm install sanity@latest

✨ Highlights

  • Adds new token login method for rare cases when the more secure cookie approach is not viable/wanted
  • Enables specifying authentication options using an object instead of createAuthStore()
  • Adds new is_defined filter to GraphQL APIs, mirroring the defined() function in GROQ. GraphQL APIs will have to be re-deployed to enable the new filter.

🐛 Notable bugfixes

  • Improves performance when fetching projects list as part of the sanity init CLI command
  • Fixes an issue that would give intermittent validation errors for valid string values when using a regex with global flag
  • Fixes an issue where references to undeclared document types would never load
  • Improves error UIs for reference values
  • Improves the changes pane to show path line and change indicator correctly for the following field types:
    • Array of strings (array of type string)
    • Array of tags (array of type string with layout: 'tags')
    • Array of strings (array of type string with options.list)
    • Array of emails (array of type email)

GraphQL API v2023-08-01

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.

Removing warning for new fields in GraphQL schemas

v2.17.2

Removing warning for new fields in GraphQL schemas

If you add schema fields and run sanity graphql deploy you will no longer be warned about “dangerous changes.” Previously, our GraphQL validation followed the behavior of graphql.js, which treats added fields as “dangerous.” We have had a lot of feedback, that in practice, it has been more bothersome than useful.

🐛 Notable bugfixes

  • Since v2.16.0, (inline) references in Portable Text would not be saved properly and left an arbitrary attribute. This version fixes that.

GraphQL generation 3 schema

v2020-12-07

Breaking changes between gen2 and gen3

The third generation of the GraphQL API adds support for querying all documents through the new allDocument type. However, with a new generation comes breaking changes.

We had to rename a type to avoid conflicts. DocumentFilter has been renamed to Sanity_DocumentFilter. In other words, if you for example have a query like this:

query GetAllUser($docFilter: Sanity_DocumentFilter) {
  allUser(_: $docFilter) {
    _id
  }
}

It should now look like this in gen3:

query GetAllUser($docFilter: DocumentFilter) {
  allUser(_: $docFilter) {
    _id
    
  }
}

GraphQL Generation 2 schema

v2020-02-27

Deploying generation 1

In order to use the old beta version of the GraphQL API, you can specify it when running the GraphQL command from the CLI. We call these older versions generations. The beta generation is named gen1, and the current generation is named gen2.

To deploy the old generation (beta), you can use the --generation flag in the CLI like this:

sanity graphql deploy --generation gen1

Breaking changes between gen1 and gen2

The second generation of the GraphQL API has more features, and does not pluralize the top-level collection types:

  • Generation 1: post, allPosts
  • Generation 2: post, allPost

The CLI will warn you if there are breaking changes to the schema you deploy and show you where they are. The breaking changes prompt can be disabled by running the deploy command with the --force flag.