# Content versioning & revisions

Source: https://docs.qiick.io/externa/content-versioning

Externa uses a **lean content versioning** model: one published bag of field values plus optional `draft_data`. It is **not** Directus-style named version trees.

> **Related**
> [Collection items](https://docs.qiick.io/externa/collection-items) · [Editorial approvals](https://docs.qiick.io/externa/approvals) · [Live Preview](https://docs.qiick.io/externa/live-preview) · [Project settings](https://docs.qiick.io/externa/project-settings)

> Renaming a field while items have pending drafts can lead to data loss when those drafts are published on older cores. From **1.2.1** renames preserve drafts; from **1.3.0** type / translatable flips with stored values are rejected. See [Schema changes](https://docs.qiick.io/externa/schema-changes).

## Enable

On the collection edit drawer, turn on **Versioning**. Editors then get Draft / Published workspaces on the item form.

## Draft vs published

| Workspace     | What you edit         | Save                                                      |
| ------------- | --------------------- | --------------------------------------------------------- |
| **Draft**     | `draft_data` JSON bag | Saves draft only; published values unchanged              |
| **Published** | Live field values     | Read-only when versioning is on — switch to Draft to edit |

Badges on the item form (and a **Draft** chip on the items list) show whether an unpublished draft exists.

### Publish (promote)

**Publish** copies `draft_data` into published field values, then clears the draft. Confirm before promote. Requires `can-edit-collections` and item write access.

When **Approvals required** is on, Publish is blocked until the item is **approved** — see [Editorial approvals](https://docs.qiick.io/externa/approvals).

### Discard draft

**Discard draft** drops `draft_data` without touching published values. Confirm before discard. Same permission gate as Publish.

Browser localStorage “unsaved draft” (autosave while typing) is separate — use **Discard browser draft** on that banner.

## List filter

On versioned collections, **Has draft** filters the items list to rows with unpublished `draft_data`.

## Revisions

Every save / draft save / publish / discard / hard restore can record a revision snapshot. Open **History** on the item toolbar (or the full revisions page). Soft-apply compares fields; **Hard** restore writes immediately and clears any draft.

Retention (count / days) is configured per collection or as a project default — it prunes old rows; it does not hide the History entry point.

## Scheduled publish / unpublish

On a versioned item form, set **Publish at** / **Unpublish at** (app timezone), then **Save schedule**. Badge shows **Scheduled** when a future `publish_at` is set. **Cancel schedule** clears both timestamps.

- Due drafts are promoted by `collections:process-schedules` (every minute via Laravel scheduler).
- Due `unpublish_at` soft-deletes the item (same as trash).
- Requires a running scheduler (`schedule:run` / Compose `scheduler`) — see [Operations](https://docs.qiick.io/externa/operations).
- Emit webhook `item.published` with `scheduled: true` on scheduled promote ([Outbound webhooks](https://docs.qiick.io/externa/webhooks)).
- **Failures (core 1.3.0+):** if promote fails (e.g. approvals required but draft no longer `approved`, or another promote error), the cron persists `schedule_error` + `schedule_failed_at` on the item, keeps a paired `unpublish_at`, notifies the last editor/submitter and users with `can-approve-collections`, and emits `item.publish_failed` ([core PR #303](https://github.com/qiick-io/externa-core/pull/303)). The item form shows a failure alert; the list shows a badge. Successful promote, reschedule, schedule clear, or discard draft clears the failure state.

## Ops note

Versioning is editorial only. Public CMS API returns published values unless you use [Live Preview](https://docs.qiick.io/externa/live-preview) with `version=draft`. Scheduled publish needs the scheduler process running.
