Content Releases and versions with @sanity/client
Learn how to create releases, manage document versions, and schedule publishing using the Sanity JavaScript client.
Content Releases let you group document changes and publish them together. The @sanity/client library provides helper methods on the client.releases namespace for managing releases, along with top-level methods for working with document versions.
These methods require an authenticated client with a write token. See Getting started with @sanity/client for setup instructions. The examples on this page assume a configured client and require @sanity/client 7.8.0 or later.
For a conceptual overview of how Content Releases work, see the Content Releases user guide. For the underlying HTTP endpoints, see the Content Releases API.
Create a release
Use client.releases.create() to create a new release. The method returns an object containing the releaseId, which you use to add document versions to the release.
const {releaseId} = await client.releases.create({
metadata: {
title: 'Spring product launch',
releaseType: 'scheduled',
},
})
console.log('Created release:', releaseId)The releaseType can be scheduled, asap, or undecided, and defaults to undecided when omitted. Sanity generates the releaseId for you unless you pass one explicitly.
Add document versions to a release
Use client.createVersion() to add a document version to a release. The most common case is versioning an existing published document. The example below uses baseId, which tells Sanity to copy the current published content into the version for you. To set the version's content explicitly instead, for example for a document that doesn't exist in published form yet, pass an inline document. See Choosing between baseId and inline document.
await client.createVersion({
releaseId,
publishedId: 'product-123',
baseId: 'product-123',
})This snapshots the current published product-123 into the release as a versioned document with the ID versions.<releaseId>.product-123. The published document remains unchanged until the release is published.
Choosing between baseId and inline document
When you create a version of an existing published document, prefer baseId. Sanity copies the current published content into the version for you, so you don't have to fetch and repackage it client-side. baseId is the source of the version's content; publishedId is the logical document the version refers to. In the common case where you are versioning a document's own published edition, both values are the same. You can also pass ifBaseRevisionId to make the action fail if the base document has changed since you read it.
Pass an inline document when there is no published edition to copy from, for example a product you are introducing in this release:
await client.createVersion({
releaseId,
publishedId: 'product-new-summer-hat',
document: {
_type: 'product',
title: 'Summer sun hat',
price: 24.99,
},
})_type is required. The version's _id is derived from the release and published IDs, so you don't need to set it. Calling createVersion() with an inline document logs a console warning recommending baseId, which you can disregard when the document has no published edition to copy from.
Mark a document for unpublishing
Use client.unpublishVersion() to mark a document for removal when the release runs. The document stays published until the release is executed.
await client.unpublishVersion({
releaseId,
publishedId: 'product-456',
})Get a release and its documents
Retrieve a release's metadata with client.releases.get(), and list its documents with client.releases.fetchDocuments().
// Get the release metadata
const release = await client.releases.get({releaseId})
if (!release) {
throw new Error(`Release ${releaseId} not found`)
}
console.log(release.metadata.title) // 'Spring product launch'
console.log(release.state) // 'active'
// List all documents in the release
const {result: documents} = await client.releases.fetchDocuments({releaseId})
console.log(`Release contains ${documents.length} documents`)get() returns undefined when no release matches the ID, so guard the result before reading from it. The release's state is one of active, scheduling, scheduled, publishing, published, archiving, archived, or unarchiving.
Schedule a release
Schedule a release to publish at a specific time with client.releases.schedule(). Pass an ISO 8601 date string as the publishAt value.
// Schedule the release for one hour from now
const publishAt = new Date(Date.now() + 60 * 60 * 1000).toISOString()
await client.releases.schedule({
releaseId,
publishAt,
})
console.log(`Release scheduled for ${publishAt}`)Publish a release
To publish a release immediately instead of scheduling it, use client.releases.publish(). This is how you run a release created with the asap release type.
await client.releases.publish({releaseId})
console.log('Release published')The new content is queryable as soon as the action returns. For larger releases, replacing the versions.<releaseId>.* documents with their published counterparts can take longer, and both the version and published documents are locked until that finishes.
Delete a release after publishing
After a release has been published, you can clean it up with client.releases.delete(). Delete accepts releases in the published or archived state, so check the release state first. To remove a release that is still active, use client.releases.archive(), which also deletes its document versions.
const release = await client.releases.get({releaseId})
if (release?.state === 'published' && !release.error) {
await client.releases.delete({releaseId})
console.log('Release deleted')
}Full example: create and schedule a release
Here's a complete workflow that creates a release, adds document versions, and schedules it to publish:
import {createClient} from '@sanity/client'
const client = createClient({
projectId: 'YOUR_PROJECT_ID',
dataset: 'YOUR_DATASET',
apiVersion: '2026-03-01',
useCdn: false,
token: process.env.SANITY_TOKEN,
})
// 1. Create a release
const {releaseId} = await client.releases.create({
metadata: {
title: 'Spring product launch',
releaseType: 'scheduled',
},
})
// 2. Snapshot an existing product into the release
await client.createVersion({
releaseId,
publishedId: 'product-123',
baseId: 'product-123',
})
// 3. Mark an old product for removal
await client.unpublishVersion({
releaseId,
publishedId: 'product-old-winter-coat',
})
// 4. Verify the release contents
const {result: documents} = await client.releases.fetchDocuments({releaseId})
console.log(`Release contains ${documents.length} document(s)`)
// 5. Schedule the release
await client.releases.schedule({
releaseId,
publishAt: '2026-04-01T09:00:00.000Z',
})
console.log('Release scheduled for April 1')Release actions with the Actions API
The mutating helper methods shown above use the client.action() method under the hood. If you need more control, you can dispatch release actions directly. This lets you archive, unarchive, and unschedule releases, as well as create, discard, replace, and unpublish individual document versions, among other operations.
For example, to archive and then unarchive a release:
// Archive a release
await client.action({
actionType: 'sanity.action.release.archive',
releaseId: 'spring-launch',
})
// Unarchive it later
await client.action({
actionType: 'sanity.action.release.unarchive',
releaseId: 'spring-launch',
})You can also manage individual document versions through actions:
// Create a version of a document in a release
await client.action({
actionType: 'sanity.action.document.version.create',
publishedId: 'product-123',
document: {
_id: 'versions.spring-launch.product-123',
_type: 'product',
},
})
// Discard a version
await client.action({
actionType: 'sanity.action.document.version.discard',
versionId: 'versions.spring-launch.product-123',
})
// Replace a version's contents
await client.action({
actionType: 'sanity.action.document.version.replace',
document: {
_id: 'versions.spring-launch.product-123',
_type: 'product',
title: 'Revised spring jacket',
price: 79.99,
},
})For the full list of available action types and their options, see Mutate documents with actions.
Next steps
- Content Releases user guide: Learn how releases work in Sanity Studio.
- Content Releases API: HTTP endpoint reference for the releases API.
- Mutate documents with actions: Dispatch release and version actions directly through the Actions API.
- Release Actions: Add custom release actions to the Studio.