Differentiate unpublished vs published draft in Sanity API

7 replies
Last updated: Jan 27, 2026
Is there a way to differentiate between an
unpublished
document and a
published draft
from the sanity api?
AI Update

Yes! You can differentiate between an unpublished document and a published draft using perspectives and document IDs.

The key distinction is:

  • Unpublished document: Only exists as a draft with ID like drafts.post-123 (no published version exists)
  • Published draft: Both versions exist - post-123 (published) and drafts.post-123 (draft with changes)

Using Perspectives

The most straightforward approach is to use the published perspective when querying. This returns only published documents:

const client = createClient({
  // ... config
  perspective: 'published'
})

With this perspective:

  • Unpublished documents won't appear at all
  • Published documents appear even if they have drafts

Checking in Your Query Results

You can also check programmatically by looking at the _id:

  • If _id starts with drafts., it's a draft version
  • If the same document ID exists both with and without the drafts. prefix, it's a published document with draft changes
  • If only drafts.{id} exists (no corresponding published version), it's unpublished

GROQ Queries for Detection

To find only unpublished documents (never been published):

*[_id in path("drafts.**") && count(*[^._id == "drafts." + _id]) == 0]

To find published documents with draft changes:

*[count(*[_id in [^._id, "drafts." + ^._id]]) > 1]

To exclude all drafts from production queries:

*[_type == 'post' && !(_id in path("drafts.**"))]

The previewDrafts perspective is also useful for preview environments - it automatically prioritizes drafts over published versions when both exist, which is perfect for showing the latest changes before they go live.

Show original thread
7 replies

Sanity – Build the way you think, not the way your CMS thinks

Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.

Was this answer helpful?