Clarification on creating drafts from a published document in Sanity.io.

7 replies
Last updated: Dec 14, 2023
A couple questions on creating drafts from 3rd party.
I have a app where I want to change the state of a published document to draft so that someone has to go in and publish from the studio.

If I use
createIfNotExist
does that just create a new draft that is a new document unrelated to the published document I am trying to change to a draft state? As far as I am aware, I cannot
patch
and published document into a draft state.
Has anyone worked through something similar?
AI Update

Great question! Let me break down how drafts work and address your specific concerns about converting published documents to drafts.

Understanding Drafts vs Published Documents

In Sanity, drafts and published documents are separate entities in your dataset. A draft has an _id prefixed with drafts. (e.g., drafts.abc-123), while the published version has the plain ID (e.g., abc-123). When both exist, you have a published document with unpublished changes.

Using createIfNotExists to Create a Draft

Yes, using createIfNotExists with the drafts. prefix is the correct way to create a draft from an existing published document! It doesn't create an unrelated document—as long as you use the right ID format, Sanity recognizes the relationship.

Here's how to do it:

// To convert a published document to draft state
const publishedId = 'abc-123'; // your published document ID

client.createIfNotExists({
  _id: `drafts.${publishedId}`,
  ...publishedDocumentData // copy the published document's data
})

When you create a draft with _id: drafts.abc-123, Sanity understands this is the draft version of the published document abc-123. When someone publishes from the Studio, it will merge the draft with the published version.

You Cannot Patch a Published Document into a Draft

You're correct—you cannot use patch to convert a published document into a draft state. The draft/published relationship is based on having two separate documents with the proper ID convention, not a status field you can patch.

The Workflow

  1. Create the draft using createIfNotExists with the drafts. prefix
  2. The published document remains unchanged and live
  3. In the Studio, editors will see the draft indicator
  4. When they publish from the Studio, the draft overwrites the published version

Important Consideration

One thing to be aware of: if external systems update the published document while a draft exists, publishing the draft can overwrite those external changes. Make sure your workflow accounts for this—you might want to copy the latest published data when creating the draft to avoid losing recent updates.

So yes, createIfNotExists with the drafts. prefix is exactly the right approach for what you're trying to do!

A draft and a published document are actually two separate documents in your dataset. To unpublish something via the API, you need to create a draft version, which is done by creating a copy of the published document with the
_id
prefixed with
drafts.
) then delete the published document.
Perfect! It was a misunderstanding I had of what createIfNotExists does. Thanks!
You’re welcome!
I wonder if the documentation could have some more clarification around it? If I am understanding it correctly, something like this could be helpful:

Note: If you are wanting to change the state of a Published document to be "draft" then use the
createIfNotExists
function and set the id like so: `id: `drafts.previousDocId`` . This will create a draft document and leave a published Document. When published from the studio, the draft doc will merge with the published document and resolve changes
Yes! Something like that would be helpful. I’ll pass this along to the docs team. Thank you!
Here is an example function I have written that would do that if it can also be helpful

 import { merge } from 'lodash/fp' // not necessary just what I was using

const {
    docId,
    ...additionalProperties
  } = formData

const updateObject = {
    ...propertiesToUpdate
  }

const [published, draft] = await client.getDocuments([
    docId,
    `drafts.${docId}`,
  ])

  if (draft) {
    const res = await client.patch(docId).set(updateObject).commit()
  } else {
    const draftDoc = merge(
      { ...published, _id: `drafts.${docId}`, _type: 'card' },
      updateObject,
    )
    const res = await client.createIfNotExists(draftDoc)
  }
Also, shoutout to
user P
for the help and thoughts last week. Finally got it working!

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?