Drafts & Saving
Content edits don’t apply straight to your site. Every write — from the AI agent, from the portal editor, from the REST API — lands in a working copy: a per-document draft layer that sits on top of the saved content.
Think of it like a text editor. The working copy is the buffer, the saved document is the file on disk, and deploying is publishing that file.
The loop
Section titled “The loop”-
The AI agent edits. Changes go into the working copy. Your live site is untouched. So is the saved version.
-
You review. Ask for a preview link that includes drafts, or open the page in the portal editor — it shows the same draft layer with an “Unsaved changes” marker.
-
You save. Say “save it” (the AI agent calls
commit_working_copy), or click Save in the portal’s Publish menu. The draft is written into the real document and a revision snapshot is taken. -
You deploy. Saved content reaches visitors on the next deploy.
Steps 3 and 4 are separate on purpose: saving makes a change permanent, deploying makes it public.
What this means in practice
Section titled “What this means in practice”Chained edits compose. When the AI agent reads a page it gets the draft view, not
the saved one, along with a has_unsaved_changes flag. So “add a section” then
“now make its heading shorter” works exactly as you’d expect — the second edit
sees the first.
Deploys never carry unsaved work. A deploy builds from saved content only. If you deploy with a draft outstanding, the draft stays behind, waiting. This is deliberate: an unreviewed edit can never ride along with an unrelated publish.
Plain preview links show saved content too. To see your drafts you need a preview that explicitly includes them — just ask (“show me a preview with the unsaved changes”), and the AI agent will request one.
Discarding
Section titled “Discarding”Changed your mind? “Discard the unsaved changes” throws the working copy away and leaves the saved document untouched. Nothing is lost that had been saved.
What isn’t drafted
Section titled “What isn’t drafted”A few things apply immediately, because they’re not content edits:
| Applies immediately | Why |
|---|---|
Page status (draft / published) and date_published |
These are the publish decision — drafting them would be circular |
| Creating and deleting pages, partials, Pages | There’s no prior version to buffer against |
| Switching a page between block and HTML mode | Structural, not a content edit |
| Site settings, redirects, block types, media, content type schemas | Configuration, not page content |
| Page templates and Page templates | These have no working-copy layer at all |
Everything else — page content, blocks, partials, custom Page fields — goes through the draft layer.
For API and MCP users
Section titled “For API and MCP users”- Writes (
update_page, block mutations,update_partial, batch and bulk tools) stage a draft. - Reads return the draft view plus
has_unsaved_changes. - Block write tools in MCP answer with the changed block and
has_unsaved_changes, true while the draft differs from the saved content (see compact write answers). - Commit with
commit_working_copy, or passsave: trueon the write call to write and commit in one step. discard_working_copydrops the draft;read_working_copyinspects it.get_change_summarydescribes a page draft before you save it: the changed page fields (meta_changed) and the block changes (block_changes: added, removed, changed and moved blocks, with the changed field names). Use it to tell the owner what you edited, or to see what another editor left in the draft. Pair it withget_preview_linkandinclude_working_copyfor the visual check.
Commit always runs through one code path, so every surface behaves identically: revision snapshot, SEO transform, HTML sanitisation, and redirect hygiene (including an automatic 301 when a page’s URL changes).
History and restore
Section titled “History and restore”Every save keeps the page as it was before the save, up to 100 saved states per page on each version. The HTML page editor shows them under History; agents and scripts use:
list_page_revisions— the saved states, newest first (GET /api/v1/sites/{siteId}/pages/{pageId}/revisions).read_page_revision— one saved state with its full content (GET …/revisions/{revisionId}).preview_page_revision— render that saved state as the full preview document, with the current header, footer and settings, exactly as the History panel shows it (GET …/revisions/{revisionId}/preview, returnsrendered_html).restore_page_revision— put that content back as a draft, or save it at once withsave: true(POST …/revisions/{revisionId}/restore).
The header, footer and global blocks keep the same history:
list_partial_revisions(GET /api/v1/sites/{siteId}/partials/{partialId}/revisions).read_partial_revision(GET …/revisions/{revisionId}).restore_partial_revision— restore the name and HTML or block content as a draft, or save it withsave: true(POST …/revisions/{revisionId}/restore).
A restore keeps publication status (and, for pages, the schedule). Saving it snapshots the current state first, so a restore can be undone the same way. A state saved in the other content mode (blocks or HTML) is refused until the page or partial is switched to that mode. Reading history needs read access; restoring needs write access, as in the editor.