---
{
  "id": "platform.form.versions-and-restore",
  "topic": "form",
  "title": "Form versions and unpublished restore",
  "locale": "en",
  "version": "2026-08-25",
  "summary": "Restoring a Form creates a new unpublished draft with optimistic concurrency and a pre-restore checkpoint; it never republishes or rewrites responses.",
  "content": "Form exposes five private version Actions: `list_versions`, `get_version`, `create_named_version`, `restore_version`, and `copy_version`. History needs edit-grade user access plus an Agent write grant; archived or frozen-space Forms cannot mutate it. Every version Action has `allow_in_public: false`.\n\nUser-visible checkpoint kinds are `baseline`, `automatic`, `named`, `published`, `pre_restore`, `restored`, and `legacy_response`. Ordinary edits create automatic checkpoints. `create_named_version` needs no confirmation but should be used only when explicitly requested; it supports dry-run and an idempotency key, and an idempotent retry returns the same version.\n\n`restore_version` requires UserConfirm plus `formId`, `versionId`, and `expectedHeadVersionId`. Obtain the current head with `list_versions`; if it changed, runtime returns `HISTORY_CONFLICT` and the caller must reload before retrying. Restore first creates a `pre_restore` checkpoint, then writes the selected definition as a new `restored` unpublished draft. It leaves `published_revision_id` and the public Form unchanged and never rewrites responses. A successful result includes `publishRequired: true`; only a separate confirmed `publish_form` can expose the restored definition.\n\nConflicting field IDs may be remapped in `fieldIdMap`; later Actions must use mapped IDs. `legacy_response` cannot be restored and returns `VERSION_PAYLOAD_INVALID`; follow list-result `canRestore` and `canCopy`. Restore is idempotent. Dry-run reports `wouldCreateUnpublishedDraft` and `wouldRequireConfirmation`. Runtime errors are authoritative.\n\n`copy_version` recovers history without changing the source. It needs `formId` and `versionId`, creates a separate Form with fresh history, needs no confirmation, and uses Strict drift. Publishing the copy remains separate and confirmed.\n",
  "aliases": [
    "form version history",
    "restore form",
    "expectedHeadVersionId",
    "HISTORY_CONFLICT",
    "pre restore checkpoint",
    "fieldIdMap",
    "publishRequired"
  ],
  "tags": [
    "form",
    "versions",
    "restore",
    "concurrency",
    "publish"
  ],
  "relatedActions": [
    "arinova.form.list_versions",
    "arinova.form.get_version",
    "arinova.form.create_named_version",
    "arinova.form.restore_version",
    "arinova.form.copy_version",
    "arinova.form.publish_form"
  ],
  "relatedActionPrefixes": [],
  "url": "https://docs.arinova.ai/en/kb/form/versions-and-restore/"
}
---

Form exposes five private version Actions: `list_versions`, `get_version`, `create_named_version`, `restore_version`, and `copy_version`. History needs edit-grade user access plus an Agent write grant; archived or frozen-space Forms cannot mutate it. Every version Action has `allow_in_public: false`.

User-visible checkpoint kinds are `baseline`, `automatic`, `named`, `published`, `pre_restore`, `restored`, and `legacy_response`. Ordinary edits create automatic checkpoints. `create_named_version` needs no confirmation but should be used only when explicitly requested; it supports dry-run and an idempotency key, and an idempotent retry returns the same version.

`restore_version` requires UserConfirm plus `formId`, `versionId`, and `expectedHeadVersionId`. Obtain the current head with `list_versions`; if it changed, runtime returns `HISTORY_CONFLICT` and the caller must reload before retrying. Restore first creates a `pre_restore` checkpoint, then writes the selected definition as a new `restored` unpublished draft. It leaves `published_revision_id` and the public Form unchanged and never rewrites responses. A successful result includes `publishRequired: true`; only a separate confirmed `publish_form` can expose the restored definition.

Conflicting field IDs may be remapped in `fieldIdMap`; later Actions must use mapped IDs. `legacy_response` cannot be restored and returns `VERSION_PAYLOAD_INVALID`; follow list-result `canRestore` and `canCopy`. Restore is idempotent. Dry-run reports `wouldCreateUnpublishedDraft` and `wouldRequireConfirmation`. Runtime errors are authoritative.

`copy_version` recovers history without changing the source. It needs `formId` and `versionId`, creates a separate Form with fresh history, needs no confirmation, and uses Strict drift. Publishing the copy remains separate and confirmed.
