Content API

Document actions

The transactional form the Studio uses: create, edit, publish, discard, delete and unpublish — each expanding into a mutation set applied as one unit.

Actions are the higher-level API. Each expands into mutations, and the expansion is where the draft/published semantics live.

ActionWhat it does
document.createCreates the draft row for a new document.
document.editEnsures a draft exists — copying the published document if needed — then patches it.
document.publishReplaces the published document with the draft and deletes the draft. One transaction.
document.discardDeletes the draft, leaving the published document untouched.
document.unpublishCreates a draft from the published document, then deletes the published row.
document.deleteRemoves both rows.
bash
curl -X POST "$HOST/api/v2026-07-26/data/actions/production" \
  -H 'content-type: application/json' \
  -H "cookie: $SESSION" \
  -d '{"actions":[{"actionType":"sanity.action.document.publish","draftId":"drafts.post-1","publishedId":"post-1"}]}'

Why publish is a single transaction

Because the two halves must not be separable. If the replace succeeded and the draft delete failed, the Studio would show unpublished changes that are in fact published; if the reverse, the document would lose its draft without gaining a publish. Both are states an editor cannot reason about, so neither is allowed to exist.

The publish path is also where constraints bite hardest: a strong reference to something unpublished, or a slug another published document already holds, is refused here, which is the moment the collision becomes real.

Permissions

Publishing requires an editor or administrator role. A viewer may read drafts but not act on them; the default pending role may do neither.