Content release document flow
How Content Releases store document versions, and the states a release moves through from creation to publish.
Content Releases let you organize and schedule updates across multiple documents. You can plan, preview, and validate significant changes in advance, then publish them together.
This document explores interacting with Content Releases using Sanity's APIs. For details on using Content Releases in Sanity Studio, or customizing the experience, follow these links:
This is a paid feature
This feature is available on certain Enterprise plans. Talk to sales to learn more.
Scheduled Drafts is also available
For teams on Growth or above plans, or that don’t need to schedule groups of documents to go out at once, the Scheduled Drafts feature is available.
APIs that interact with Content Releases require API version v2025-02-19 or later. A single release can contain a maximum of 1,000 documents, and the combined JSON of all documents in a release cannot exceed 100 MB. Asset files linked from those documents don't count toward the size limit.
Releases and document versions
Releases are Sanity documents with a type of system.release. The top-level state property holds the release state, and metadata holds the user-supplied fields such as metadata.title, metadata.description, metadata.releaseType, and metadata.intendedPublishAt.
Protip
If you use content resources and custom roles, you can restrict access for:
- Editing documents in releases by using a filter like
_id in path("versions.**")for any release or_id in path("versions.rA29bfjqa.**")for documents in a specific release. - Performing release actions such as creating, publishing and archiving releases by using a filter like
_id in path("_.releases.**")for any release or_id == "_.releases.rA29bfjqa"for a specific release.
Releases and documents are connected by a document ID system similar to the drafts. syntax. For releases, document IDs start with the versions. prefix. For example:
- The published version:
movie_70981 - A release version:
versions.RELEASE_NAME.movie_70981
Releases have a name, not to be confused with the user-supplied title. This name matches the end of the _id. When you create a release through the API, the releaseId you supply becomes the name; client.releases.create() generates one for you if you omit it. For example, a release name of rSC2jjcUJ results in an _id of _.releases.rSC2jjcUJ.
Release states
The current status of a release is known as the release state. Releases begin in the active state. This information is available on the state property in documents with a _type of system.release.
Diagram couldn't be rendered.
stateDiagram-v2
[*] --> active: release.create
active --> scheduling: release.schedule<br>release.publish
scheduling --> scheduled
scheduled --> unscheduling: release.unschedule
unscheduling --> active
scheduled --> publishing
publishing --> published
publishing --> active: publish failed
active --> archiving: release.archive
archiving --> archived
archiving --> active: archive failed
archived --> unarchiving: release.unarchive
unarchiving --> active
archived --> [*]: release.delete
published --> [*]: release.deleteA release may have the following states (state):
active: The general state of a release that is not within one of the other states. This is the default state of a new release.scheduled: A state resulting from calling thesanity.action.release.scheduleaction on the release or scheduling the release in Studio.published: A state resulting from either calling thesanity.action.release.publishaction, publishing the release in Studio, or when a scheduled release is published due to reaching itspublishAttime.archived: A state resulting from calling thesanity.action.release.archiveaction or archiving the release in Studio.
There is no deleted state. The sanity.action.release.delete action, or deleting the release in Studio, removes the release document. You can only delete a release that is published or archived.
Gotcha
When scheduled, any version documents that are part of the release are locked. To mutate these documents, either in Studio or programmatically, the release must have a state of active.
Additional transient states exist to indicate the asynchronous points when releases move between states:
scheduling/unscheduling: Intermediate states that exist when moving to or from thescheduledstate.archiving/unarchiving: Intermediate states that exist when moving to or from thearchivedstate.publishing: Intermediate state that exists before reaching thepublishedstate. A scheduled release also transitions throughpublishing.
State transitions
Releases begin in active. Every other state is reached through one of these transitions:
- Scheduling or publishing an
activerelease moves it toscheduling, thenscheduled. - Unscheduling a
scheduledrelease moves it tounscheduling, then back toactive. - A
scheduledrelease moves topublishingwhen its publish time arrives, then topublished. - Archiving an
activerelease moves it toarchiving, thenarchived. - Unarchiving an
archivedrelease moves it tounarchiving, then back toactive. - Deleting a
publishedorarchivedrelease removes the release document.
If publishing or archiving fails, the release returns to active and the error property holds the reason. Large releases publish, archive, and unarchive in batches, so they can stay in publishing, archiving, or unarchiving across several updates.
A scheduled release stores its publish time in the top-level publishAt property. This is distinct from metadata.intendedPublishAt, which records the time an editor picked in Studio. Where both are set, publishAt takes precedence.
Even releases set for immediate publishing move through the scheduling and scheduled states. They do not stay there; they immediately move on to publishing. Keep this in mind if you listen for state changes on release documents.
Query releases and versions
Releases are Sanity documents and respect the existing query and mutation APIs. The Content Releases API cheat sheet provides examples of querying and interacting with releases and their documents.
Additional resources
Actions API reference
Reference documentation for the Actions HTTP endpoint, including the release actions.
GROQ functions
GROQ queries can use the releases::all(), sanity::partOfRelease(), and sanity::versionOf() functions to retrieve release information.
@sanity/id-utils
This utility library helps parse and convert between the various ID formats.