# Publishing and scheduling (/docs/guides/publishing)

Every entry has a **draft**, which is all editing changes, and once published a **published** copy, which is all the [delivery API](/docs/api/delivery) serves to delivery tokens. An entry has unpublished changes while its draft is ahead of what's published. Preview tokens and the [canvas](/docs/guides/canvas) see drafts.

## What publishing checks [#what-publishing-checks]

Saving only checks that values have the right shape. Publishing also needs:

- every **required** field filled in for the default locale, and `min` blocks in a blocks field;
- every entry the content **references** or embeds to be published itself, so published content never points at a draft;
- every [improve block](/docs/guides/ab-tests) to name a test or flag that exists in the environment.

The other way round, an entry can't be unpublished or deleted while published content still uses it.

## Publishing some languages [#publishing-some-languages]

In a space with several [locales](/docs/guides/locales), **Publish languages…** (under **Now** in the publish options) publishes the changes of only the languages you pick: say the English text is ready and the Dutch translation isn't.

- The picked languages' values go live from the draft. The others keep what was published before, block by block; where nothing was published in a language, the delivery API falls back along the [locale chain](/docs/guides/locales#fallbacks), as for any empty value.
- What isn't per language (the order of blocks, a new block, a shared field) is the draft's, since every language shares it.
- An entry is first published in its default locale; after that any language can go on its own.
- While some of the draft is unpublished, the entry's status is **Changed**. Publishing the remaining languages (or everything) makes it **Published** again.

Agents send `{ "locales": ["en"] }` with `POST …/entries/{id}/publish`. Scheduled publishing, bulk publishing and approving a review publish every language.

## Shared blocks [#shared-blocks]

Publishing a [shared block](/docs/guides/content-model#shared-blocks) updates every live page that shows it, without republishing each page. Its publish options list them: untick a page to keep it on the version it shows now, which gets the new one the next time that page is published (or **Detach** on its card to opt out for good). The reverse warning names the blocks a held page catches up on when it is published.

Approving a shared block in a [reviewed environment](#review-before-publishing) shows the same list. A schedule keeps the pages picked when it was set. The publish sends one `block.published` [webhook](/docs/guides/webhooks) with the pages it updated.

## Scheduling [#scheduling]

**Publish** in the entry bar opens its options: **Now**, or **Later** with a date and a time in your own time zone (**Schedule for Thu 09:00**). **Schedule publish** under Status beside the form sets both when the draft goes live and when it comes off your site, or clears them. Agents use `POST …/entries/{id}/schedule` with ISO 8601 times (the `scheduleEntry` MCP tool).

- At the publish time, the draft **as it is then** is published, not as it was when you scheduled it. Edits until then go live with it.
- Where publishing is [reviewed](#review-before-publishing), only the draft as it was when the admin scheduled it goes live. If anyone saves it after that, the run is refused; schedule it again once the new draft is reviewed.
- It runs as the person who scheduled it, with their role at that moment, and checks everything a publish does. It sends the same [webhooks](/docs/guides/webhooks).
- If it is refused (a required field is empty, or the person lost their role), nothing changes and the reason shows under Status beside the entry's form.
- Schedules are checked every minute, so allow up to a minute.
- An unpublish time has to be after the publish time. Leave a time empty, or send `null`, to clear it.

A schedule belongs to one environment. Promoting an entry doesn't carry its schedule along.

## History [#history]

Every save, every publish and every draft a [promotion](/docs/guides/environments#promoting) brings (**Promoted**) is kept as a version: **History** beside the entry's form, or `GET …/entries/{id}/versions`. Restoring a version makes it the draft again; publish to roll back. An entry keeps its newest 100 versions.

## Deleting and the trash [#deleting-and-the-trash]

Deleting an entry (once nothing uses it) moves it to the **Trash**, linked under the entries list, for 30 days. **Restore** brings it back as a draft with its version history, at its old place when that is still free (at the root when its folder is gone); publish it again when ready. **Delete for good** removes it straight away. Agents use `GET …/trash`, `POST …/trash/{id}/restore` and `DELETE …/trash/{id}`.

Deleting a published entry takes it off the delivery API at once and sends `entry.deleted`; restoring doesn't publish it.

## Moving and redirects [#moving-and-redirects]

**Edit** under URL beside the entry's form gives a page or folder a new slug (per locale) or another folder. Its old path, and those of the pages below it, keep pointing at it as **redirects**: the delivery API answers an old path with where the page is now, so your site can answer with a `301` instead of a 404. Moving sends `entry.moved` with the previous paths. See [Redirects](/docs/guides/redirects) for how they behave, adding one by hand, and answering them on your site.

## Duplicating [#duplicating]

**Duplicate** beside the entry's form (or `POST …/entries/{id}/duplicate`) makes a new draft next to the entry, with the same content type, folder and saved draft, " (copy)" after the name and, for a page, the first free `<slug>-copy`. Nothing is published.

## Review before publishing [#review-before-publishing]

An admin can make an environment's publishing **reviewed** under **Settings → Publishing**, typically production only. There, only admins publish, unpublish, schedule, delete published entries, and promote or import published content. Everyone else who edits sees **Ask for review** where Publish was:

1. **Ask for review** saves the draft and asks an admin to publish that revision, with an optional note. The entry shows "In review", the content list can filter on it, and an `entry.review_requested` [webhook](/docs/guides/webhooks) goes out, for a Slack message or an email from your own tooling.
2. Editing goes on as usual. If the draft changes after the ask, the request says so, and it can't be approved until it is asked for again: nobody publishes text they haven't seen.
3. An admin opens the entry and either **approves**, which publishes exactly the revision that was asked about, or **sends it back** with a reason, which the editor sees on the entry. Either way `entry.review_closed` goes out, and the [activity](/docs/guides/activity) log has it.

The person who asked can withdraw the request. An admin publishing an entry with an open request also closes it. Bulk actions, the canvas, editing on the site, the agent API, MCP and management tokens all follow the setting: whoever may not publish there asks for review (`POST …/entries/{id}/review`, and `request_review` in bulk), and publishing answers `403 review_required`.

## Several entries at once [#several-entries-at-once]

Tick entries in the **Content** list to publish, unpublish, move, delete or promote them together (**Promote** opens [promoting](/docs/guides/environments#promoting) with them picked), up to 100 at a time (the box in the header ticks the whole page). Each entry goes through exactly what it would on its own: the same checks, history, webhooks and redirects, and deleted entries go to the trash.

The order you tick them in doesn't matter. A page that references an author publishes once the author has, and a folder is deleted after what is in it. Entries that wait on each other (each only names the others) publish together in one transaction: drafts like two articles linking to each other go live as a set, or not at all. That set is the whole cycle, even when it is larger than the 100 a call may name — a ring of 137 articles split over two calls still publishes from the half the call names (up to 500; a larger cycle says so), and the cycle's other entries go live with it. Whatever still can't be done is listed with the reason and stays ticked; the rest is done.

Agents use `POST …/entries/bulk` with `{ "action": "publish" | "unpublish" | "move" | "delete", "entryIds": [...], "parentId"? }` (`parentId` for `move`, `null` for the root), which answers a result per entry.
