---
title: "Roll back to an archived policy version"
method: POST
path: "/api/policy_version/{version}/rollback"
tags: ["Policy Versions"]
---

# Roll back to an archived policy version

`POST /api/policy_version/{version}/rollback`

## Request

- Base URL: `https://app.herondata.io`
- URL: `https://app.herondata.io/api/policy_version/{version}/rollback`
- Auth: API key in header `x-api-key`

Clone an archived version's policy_definition into a new draft. Pass publish=true to publish the new version immediately.

## Path parameters

- `version` integer, required

## Query parameters

- `publish` boolean
- `overwrite_draft` boolean
- `user_id` integer

## Response `201`

OK

- object
  - `issues` PublishIssueSchema[]: With publish=true, warnings that did not stop the publish
    - `attribute_label` string, nullable: The variable the check reads
    - `available_after` string, nullable: Customer-facing name of the step after which every deal has the variable
    - `blocks_publish` boolean, required: Publishing is refused while this is true; saving never is
    - `check_name` string, nullable: The top-level check, even when a condition in it reads the variable
    - `code` 'data_on_no_path' | 'data_not_in_workflow' | 'data_on_some_paths_only' | 'data_unverified' | 'policy_node_left_without_sections' | 'unknown_attribute' | 'invalid_attribute_parameters' | 'incompatible_compared_variable' | 'unreadable_lookup_threshold' | 'email_address_compared_with_domain', required
    - `message` string, required
    - `path` unknown[], required: The check that reads the variable, as a save error would point at it, down to a condition inside a group; empty for a workflow node
      - unknown
    - `policy_node_id` string, nullable: Workflow node left with no sections
    - `section_heron_id` string, nullable
    - `section_name` string, nullable
  - `policy_version` PolicyVersionSchema
    - `author_email` string: Email of whoever last acted on this version: the drafter while it is a draft, the publisher once published
    - `backtest_status` PolicyVersionBacktestStatus
      - `backtest_heron_id` string, nullable
      - `deal_count` integer, nullable: Deals the backtest covered
      - `finished_at` string, date-time, nullable
      - `flipped_deal_count` integer, nullable: Deals whose outcome changed, null unless the run completed
      - `run_status` unknown
      - `stale` boolean: The version was edited after that backtest was asked for, so re-run before publishing
    - `change_description` string, nullable: What changed in this version
    - `created` string, date-time
    - `last_edited_at` string, date-time, nullable
    - `policy_definition` PolicyDefinition
      - `policy_sections` PolicyVersionSection[], required
        - `branches` PolicyBranch[]: Ordered routes through the section; the section's own checks run on every route
          - `checks` Check[]
            - `attribute_description` string, nullable: What the attribute measures. Present only for accounts on policy versions
            - `attribute_display_name` string, nullable: The attribute's human-readable name. Present only for accounts on policy versions
            - `attribute_label` string, nullable
            - `attribute_unit` unknown
            - `attribute_validators` object[], nullable: The validity operators `attribute_label` offers, as in the catalogue's `check_options[].validators`, so a saved `is_valid` / `is_invalid` check can be worded. Empty for a check without an attribute or an attribute with no validity rule
              - …
            - `attribute_value_set` unknown
            - `boolean_check` BooleanCheck
              - …
            - `composite_check` CompositeCheck
              - …
            - `date_check` DateCheck
              - …
            - `date_delta_to_now_check` DateDeltaToNowCheck
              - …
            - `enhanced_sql_check` EnhancedSQLCheck
              - …
            - `group` string, nullable
            - `heron_id` string, nullable: Stable across edits; omit for a new check and one is minted. Policy versions only
            - `identity` string, nullable: Stable kind:key identity used to match stored check evaluations
            - `name` string, nullable
            - `numeric_check` NumericCheck
              - …
            - `parameters` object, nullable
            - `sql_check` SQLCheck
              - …
            - `string_check` StringCheck
              - …
          - `condition` Check, required
            - `attribute_description` string, nullable: What the attribute measures. Present only for accounts on policy versions
            - `attribute_display_name` string, nullable: The attribute's human-readable name. Present only for accounts on policy versions
            - `attribute_label` string, nullable
            - `attribute_unit` unknown
            - `attribute_validators` object[], nullable: The validity operators `attribute_label` offers, as in the catalogue's `check_options[].validators`, so a saved `is_valid` / `is_invalid` check can be worded. Empty for a check without an attribute or an attribute with no validity rule
              - …
            - `attribute_value_set` unknown
            - `boolean_check` BooleanCheck
              - …
            - `composite_check` CompositeCheck
              - …
            - `date_check` DateCheck
              - …
            - `date_delta_to_now_check` DateDeltaToNowCheck
              - …
            - `enhanced_sql_check` EnhancedSQLCheck
              - …
            - `group` string, nullable
            - `heron_id` string, nullable: Stable across edits; omit for a new check and one is minted. Policy versions only
            - `identity` string, nullable: Stable kind:key identity used to match stored check evaluations
            - `name` string, nullable
            - `numeric_check` NumericCheck
              - …
            - `parameters` object, nullable
            - `sql_check` SQLCheck
              - …
            - `string_check` StringCheck
              - …
          - `heron_id` string, nullable: Stable across renames; omit for a new branch and one is minted
          - `name` string, required
        - `checks` Check[]
          - `attribute_description` string, nullable: What the attribute measures. Present only for accounts on policy versions
          - `attribute_display_name` string, nullable: The attribute's human-readable name. Present only for accounts on policy versions
          - `attribute_label` string, nullable
          - `attribute_unit` unknown
          - `attribute_validators` object[], nullable: The validity operators `attribute_label` offers, as in the catalogue's `check_options[].validators`, so a saved `is_valid` / `is_invalid` check can be worded. Empty for a check without an attribute or an attribute with no validity rule
          - `attribute_value_set` unknown
          - `boolean_check` BooleanCheck
            - `auto_decline` boolean
            - `decline_code` string, nullable: The CRM's identifier for this decline reason, e.g. a LendSaas reason id. Left unset, the CRM sync falls back to this check's decline_description.
            - `decline_description` string, nullable
            - `email_template_name` string, nullable
            - `ignore_metric_availability` boolean
            - `is_mandatory` boolean
            - `on_failure` 'fail' | 'review_required'
            - `on_missing` 'missing_data' | 'fail' | 'pass': What the check reports when it would report missing data: `missing_data` (the default), `fail` or `pass`. A check saved with an older flag (`pass_if_value_missing` on a date-delta check) reads as the setting it stands for. With `ignore_metric_availability` or `pass_if_value_missing` set, only that setting is accepted
            - `pass_description` string, nullable
            - `transaction_scope` TransactionScope
              - …
            - `value` boolean
          - `composite_check` CompositeCheck
            - `auto_decline` boolean
            - `checks` Check[]
            - `decline_code` string, nullable: The CRM's identifier for this decline reason, e.g. a LendSaas reason id. Left unset, the CRM sync falls back to this check's decline_description.
            - `decline_description` string, nullable
            - `email_template_name` string, nullable
            - `ignore_metric_availability` boolean
            - `is_mandatory` boolean
            - `max_failing` integer, nullable
            - `on_failure` 'fail' | 'review_required'
            - `on_missing` 'missing_data' | 'fail' | 'pass': What the check reports when it would report missing data: `missing_data` (the default), `fail` or `pass`. A check saved with an older flag (`pass_if_value_missing` on a date-delta check) reads as the setting it stands for. With `ignore_metric_availability` or `pass_if_value_missing` set, only that setting is accepted
            - `pass_description` string, nullable
            - `transaction_scope` TransactionScope
              - …
            - `type` 'AND' | 'OR' | 'AT_MOST_FAILING'
          - `date_check` DateCheck
            - `auto_decline` boolean
            - `decline_code` string, nullable: The CRM's identifier for this decline reason, e.g. a LendSaas reason id. Left unset, the CRM sync falls back to this check's decline_description.
            - `decline_description` string, nullable
            - `email_template_name` string, nullable
            - `ignore_metric_availability` boolean
            - `is_mandatory` boolean
            - `on_failure` 'fail' | 'review_required'
            - `on_missing` 'missing_data' | 'fail' | 'pass': What the check reports when it would report missing data: `missing_data` (the default), `fail` or `pass`. A check saved with an older flag (`pass_if_value_missing` on a date-delta check) reads as the setting it stands for. With `ignore_metric_availability` or `pass_if_value_missing` set, only that setting is accepted
            - `pass_description` string, nullable
            - `transaction_scope` TransactionScope
              - …
            - `type` 'equal' | 'not_equal' | 'before' | 'before_or_on' | 'after' | 'after_or_on'
            - `value` string, date, nullable
          - `date_delta_to_now_check` DateDeltaToNowCheck
            - `auto_decline` boolean
            - `decline_code` string, nullable: The CRM's identifier for this decline reason, e.g. a LendSaas reason id. Left unset, the CRM sync falls back to this check's decline_description.
            - `decline_description` string, nullable
            - `email_template_name` string, nullable
            - `ignore_metric_availability` boolean
            - `is_mandatory` boolean
            - `on_failure` 'fail' | 'review_required'
            - `on_missing` 'missing_data' | 'fail' | 'pass': What the check reports when it would report missing data: `missing_data` (the default), `fail` or `pass`. A check saved with an older flag (`pass_if_value_missing` on a date-delta check) reads as the setting it stands for. With `ignore_metric_availability` or `pass_if_value_missing` set, only that setting is accepted
            - `pass_description` string, nullable
            - `pass_if_value_missing` boolean
            - `transaction_scope` TransactionScope
              - …
            - `type` 'greater_than' | 'greater_than_or_equal' | 'less_than' | 'less_than_or_equal'
            - `value` object, nullable
          - `enhanced_sql_check` EnhancedSQLCheck
            - `auto_decline` boolean
            - `check_type` 'equal' | 'not_equal' | 'greater_than' | 'greater_than_or_equal' | 'less_than' | 'less_than_or_equal' | 'before' | 'before_or_on' | 'after' | 'after_or_on' | 'is_in' | 'is_not_in', required
            - `column_name` string, required
            - `comparison_value` unknown, required
            - `data_type` 'numeric' | 'date' | 'string', required
            - `decline_code` string, nullable: The CRM's identifier for this decline reason, e.g. a LendSaas reason id. Left unset, the CRM sync falls back to this check's decline_description.
            - `decline_description` string, nullable
            - `email_template_name` string, nullable
            - `ignore_metric_availability` boolean
            - `is_mandatory` boolean
            - `on_failure` 'fail' | 'review_required'
            - `on_missing` 'missing_data' | 'fail' | 'pass': What the check reports when it would report missing data: `missing_data` (the default), `fail` or `pass`. A check saved with an older flag (`pass_if_value_missing` on a date-delta check) reads as the setting it stands for. With `ignore_metric_availability` or `pass_if_value_missing` set, only that setting is accepted
            - `pass_description` string, nullable
            - `query_name` string, required
            - `transaction_scope` TransactionScope
              - …
          - `group` string, nullable
          - `heron_id` string, nullable: Stable across edits; omit for a new check and one is minted. Policy versions only
          - `identity` string, nullable: Stable kind:key identity used to match stored check evaluations
          - `name` string, nullable
          - `numeric_check` NumericCheck
            - `auto_decline` boolean
            - `decline_code` string, nullable: The CRM's identifier for this decline reason, e.g. a LendSaas reason id. Left unset, the CRM sync falls back to this check's decline_description.
            - `decline_description` string, nullable
            - `email_template_name` string, nullable
            - `ignore_metric_availability` boolean
            - `is_mandatory` boolean
            - `on_failure` 'fail' | 'review_required'
            - `on_missing` 'missing_data' | 'fail' | 'pass': What the check reports when it would report missing data: `missing_data` (the default), `fail` or `pass`. A check saved with an older flag (`pass_if_value_missing` on a date-delta check) reads as the setting it stands for. With `ignore_metric_availability` or `pass_if_value_missing` set, only that setting is accepted
            - `pass_description` string, nullable
            - `transaction_scope` TransactionScope
              - …
            - `type` 'equal' | 'not_equal' | 'greater_than' | 'greater_than_or_equal' | 'less_than' | 'less_than_or_equal'
            - `value` union: The threshold: a number as a string, {"variable": {...}} to compare with another variable (with an optional "factor" that scales it), or {"lookup": {"table_heron_id", "column_id"}} to read it from a lookup table column
              - …
          - `parameters` object, nullable
          - `sql_check` SQLCheck
            - `auto_decline` boolean
            - `column_name` string, required
            - `decline_code` string, nullable: The CRM's identifier for this decline reason, e.g. a LendSaas reason id. Left unset, the CRM sync falls back to this check's decline_description.
            - `decline_description` string, nullable
            - `email_template_name` string, nullable
            - `ignore_metric_availability` boolean
            - `is_mandatory` boolean
            - `on_failure` 'fail' | 'review_required'
            - `on_missing` 'missing_data' | 'fail' | 'pass': What the check reports when it would report missing data: `missing_data` (the default), `fail` or `pass`. A check saved with an older flag (`pass_if_value_missing` on a date-delta check) reads as the setting it stands for. With `ignore_metric_availability` or `pass_if_value_missing` set, only that setting is accepted
            - `pass_description` string, nullable
            - `query_name` string, required
            - `transaction_scope` TransactionScope
              - …
          - `string_check` StringCheck
            - `auto_decline` boolean
            - `decline_code` string, nullable: The CRM's identifier for this decline reason, e.g. a LendSaas reason id. Left unset, the CRM sync falls back to this check's decline_description.
            - `decline_description` string, nullable
            - `email_template_name` string, nullable
            - `ignore_metric_availability` boolean
            - `is_mandatory` boolean
            - `match_count` integer, nullable
            - `on_failure` 'fail' | 'review_required'
            - `on_missing` 'missing_data' | 'fail' | 'pass': What the check reports when it would report missing data: `missing_data` (the default), `fail` or `pass`. A check saved with an older flag (`pass_if_value_missing` on a date-delta check) reads as the setting it stands for. With `ignore_metric_availability` or `pass_if_value_missing` set, only that setting is accepted
            - `pass_description` string, nullable
            - `transaction_scope` TransactionScope
              - …
            - `type` 'equal' | 'not_equal' | 'starts_with' | 'starts_with_any_of' | 'does_not_start_with_any_of' | 'contains' | 'does_not_start_with' | 'does_not_contain' | 'is_in' | 'is_not_in' | 'has_none_of' | 'has_any_of' | 'has_only' | 'has_fewer_than_n_matches' | 'has_more_than_n_matches' | 'is_valid' | 'is_invalid'
            - `value` union: The value as a string, or {"lookup": {"table_heron_id"}} for is_in, is_not_in, has_any_of, has_none_of or has_only to read the list from a lookup table's rows
              - …
        - `default_branch` DefaultPolicyBranch
          - `checks` Check[]
            - `attribute_description` string, nullable: What the attribute measures. Present only for accounts on policy versions
            - `attribute_display_name` string, nullable: The attribute's human-readable name. Present only for accounts on policy versions
            - `attribute_label` string, nullable
            - `attribute_unit` unknown
            - `attribute_validators` object[], nullable: The validity operators `attribute_label` offers, as in the catalogue's `check_options[].validators`, so a saved `is_valid` / `is_invalid` check can be worded. Empty for a check without an attribute or an attribute with no validity rule
              - …
            - `attribute_value_set` unknown
            - `boolean_check` BooleanCheck
              - …
            - `composite_check` CompositeCheck
              - …
            - `date_check` DateCheck
              - …
            - `date_delta_to_now_check` DateDeltaToNowCheck
              - …
            - `enhanced_sql_check` EnhancedSQLCheck
              - …
            - `group` string, nullable
            - `heron_id` string, nullable: Stable across edits; omit for a new check and one is minted. Policy versions only
            - `identity` string, nullable: Stable kind:key identity used to match stored check evaluations
            - `name` string, nullable
            - `numeric_check` NumericCheck
              - …
            - `parameters` object, nullable
            - `sql_check` SQLCheck
              - …
            - `string_check` StringCheck
              - …
          - `condition` unknown
          - `decline_code` string, nullable: Optional code sent with a failed or review_required result
          - `decline_description` string, nullable: Required when result is failed or review_required
          - `heron_id` string, nullable
          - `name` string
          - `result` unknown
        - `display_order` integer, nullable
        - `heron_id` string, nullable
        - `name` string, required
        - `use_case` 'background_check' | 'cashflow'
    - `published_at` string, date-time, nullable
    - `status` 'draft' | 'active' | 'archived'
    - `version` integer: Version number, unique per account

## Other responses

- `404`: Policy version not found
- `422`: Version is not archived, a draft already exists and overwrite_draft is not set, a concurrent publish won the race, the version reads a variable the account no longer has, or with publish=true the version has issues that block publishing. Issues are listed in `errors`; a refused rollback leaves any existing draft in place.

## Changes

- **2026-11-03** `1ec936e17fef`: 4 warning
  - added the new `industry_category` enum value to the `policy_version/policy_definition/allOf[#/components/schemas/PolicyDefinition]/policy_sections/items/branches/items/checks/items/attribute_value_set` response property for the response status `201`
  - added the new `industry_category` enum value to the `policy_version/policy_definition/allOf[#/components/schemas/PolicyDefinition]/policy_sections/items/branches/items/condition/allOf[#/components/schemas/Check]/attribute_value_set` response property for the response status `201`
  - added the new `industry_category` enum value to the `policy_version/policy_definition/allOf[#/components/schemas/PolicyDefinition]/policy_sections/items/checks/items/attribute_value_set` response property for the response status `201`
  - added the new `industry_category` enum value to the `policy_version/policy_definition/allOf[#/components/schemas/PolicyDefinition]/policy_sections/items/default_branch/allOf[#/components/schemas/DefaultPolicyBranch]/checks/items/attribute_value_set` response property for the response status `201`
- **2026-11-03** `bd8008e49534`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/herondata/apis/heron-data-api/changes/api/policy_version/:version/rollback/post.md)

---

[API](https://skmtc.dev/herondata/apis/heron-data-api.md) - [All operations](https://skmtc.dev/herondata/apis/heron-data-api/llms.txt) - [OpenAPI document](https://skmtc.dev/herondata/apis/heron-data-api/revisions/36168f46a500?raw)
