> ## Documentation Index
> Fetch the complete documentation index at: https://docs.clustr-ai.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Scans, history and revert

> When CRM Cleaning scans, what a run records, and how to revert or retry a change

## Scans

A scan reads your connected CRM, runs every [check](https://docs.clustr-ai.com/crm-cleaning/checks.md) that is not
Off, and sorts what it finds:

* changes your rules say to make are written straight away;
* changes that need a decision go to the [queue](https://docs.clustr-ai.com/crm-cleaning/queue-and-findings.md);
* problems Clustr cannot fix go to the [findings report](https://docs.clustr-ai.com/crm-cleaning/queue-and-findings.md#findings).

Your rule settings apply the same way to every scan, whether you started it, the
schedule did, or your AI assistant did. **A scan writes the changes of every check on
Do it to your CRM**, a manual scan included.

### Start a scan by hand

Click **Scan now** in the **Runs** view or in Settings, call `POST /api/crm/cleaning/scan`,
or ask your assistant (`start_crm_cleaning_scan`). Only one scan runs at a time: asking for another while one
is running gives you the running one.

### Scheduled scans

Turn on **Run on a schedule** in CRM Cleaning settings, or the **On / Off** pill in the
**Runs** header, to scan automatically. Until it is on,
nothing runs by itself: no scheduled scan, no automatic clean-up when a record changes,
and no [weekly email](https://docs.clustr-ai.com/crm-cleaning/health-and-summary.md#the-weekly-summary-email).

| Cadence | When it runs |
| - | - |
| Hourly | Every hour, at the minute you pick |
| Daily | Every day, at the time you pick |
| Weekly | On the day and time you pick. This is the default. |
| Monthly | On the day of the month and at the time you pick. Day 31 runs on the last day of shorter months. |

Times are in the time zone you choose, and follow daylight saving time. The app
suggests Monday at 09:00 in your browser's time zone.

While the schedule is on, Clustr also checks a single contact or company soon after it
changes in your CRM, with the same settings: it fixes formatting and, when enrichment
is on, fills blank fields. A new record is also
[checked for duplicates](https://docs.clustr-ai.com/crm-cleaning/checks.md#new-records). Every other check waits
for the next scan.

### Runs

Every scan is a run. The **Runs** view lists them newest first, scheduled runs
included, with when it ran, its status, the changes it found, how long it took and what
started it.

| Status in the app | API status | Meaning |
| - | - | - |
| Queued | `pending` | Waiting to start |
| Scanning | `scanning` | Reading your CRM and running the checks |
| Ready | `ready` | Done. Everything was examined. |
| Partial | `partial` | Done, but it stopped before examining everything. What it found is kept, and the Overview says "Your last scan stopped early". |
| Applying | `applying` | Writing accepted changes |
| Success | `completed` | Finished writing its accepted changes |
| Failed | `failed` | Stopped with an error. A scan that makes no progress for 30 minutes is marked failed. |

A run is **full** when it reads the whole CRM, or **incremental** when it only looks at
records that changed.

## History

**History** lists every change cleaning made or proposed, across all runs, newest
first, with who decided it. Filter it by outcome:

| Outcome | Meaning |
| - | - |
| Applied | Written to your CRM |
| Reverted | Written, then put back |
| Dismissed | Someone said no. Nothing was written. |
| Failed | Your CRM refused it |
| Conflict | Not written, because the record changed in your CRM since the scan |
| Resolved before review | A change waiting in Review closed without a decision: a later scan no longer found the problem, or no scan found it again for 45 days |
| No longer found | The same, for a finding |
| Superseded | Another, more specific change now covers it, for example the merges made from a duplicate group |
| Pending, Accepted | Still waiting for a decision, or accepted and about to be written |

You can also narrow it by:

| Filter | Shows |
| - | - |
| Date | Changes applied in a date range, or found in it if they were never applied. Presets for the last 7, 30 and 90 days. |
| Rule | Changes made by one or more rules, for example Normalize formatting |
| Decided by | **People**: changes someone on your team accepted or dismissed. **Clustr**: changes Clustr applied or closed on its own, under Do it or because the problem went away, and changes nobody has decided yet. |
| Record type | Contacts, companies or deals |

### Export the history

**Export CSV** at the top of History downloads every change that matches the filters
and search you picked, not only the rows on screen. The file has one row per change:

| Column | What it holds |
| - | - |
| Date applied | When the change was written to your CRM, in UTC. Empty if it never was. |
| Rule | The rule in words, for example "Normalize formatting" |
| Object type, Record ID, Record name | The record the change is about |
| Field | The field it changed |
| Before, After | The value before and after |
| State | The outcome, as in the table above |
| Decided by | Who decided. "Automatic" is a rule on Do it, "System" is Clustr closing it on its own. |
| CRM link | A link to the record in HubSpot. Empty on other CRMs. |
| Clustr ID | The Clustr id of the person (`per_...`) or company (`acc_...`) the record is, when Clustr has it. Empty for deals and for records Clustr cannot place. |

A file holds at most 50,000 rows, newest first. It opens in Excel with accents intact.
A value that starts with `=`, `+`, `-` or `@` gets a leading `'` so a spreadsheet never
runs it as a formula. Over the API, use
[`GET /api/crm/cleaning/history/export`](https://docs.clustr-ai.com/crm-cleaning/api#export-the-history).

## Revert

Most applied changes can be reverted for **30 days**. Revert writes the old value back
to your CRM. Linking a contact to a company is reverted by removing the link.

Revert reads the field in your CRM first:

* If it still holds the value Clustr wrote, the old value is written back.
* If someone edited it in your CRM since, nothing is written: their edit stays, and
  the revert is refused as a conflict (`409 REVERT_CONFLICT` over the API).
* If it already holds the old value, the change is marked reverted without a write.

What cannot be reverted:

* **After 30 days**, nothing can.
* **Phone repairs.** A small number of changes repaired phone numbers a past clean-up
  had damaged. Reverting one would write the damaged number back, so they cannot be
  reverted.
* **Deal merges.** Your CRM cannot unmerge deals, and a recreated deal would lose its
  stage history, so a deal merge has no Revert.
* **A contact or company merge has no true undo.** Your CRM cannot unmerge records.
  Within 30 days, revert recreates the archived record as a **new record with a new
  id** and restores both records' values, links and activity as far as your CRM allows. It may not clear a
  field the merge had filled, and a recreated contact can be refused if its email now
  sits on the surviving record. Treat a merge as permanent.

**Revert** is shown on applied changes, with the days left in its tooltip. It is
greyed out once the window has closed, on phone repairs and on deal merges. Reverting a merge first
asks you to confirm, in a **Revert this merge?** dialog.

### Revert a whole rule

To undo everything one rule did, for example every phone format fix, use **Revert all**
on that rule in History, then confirm. Each change goes through the same checks as a
single revert:

* Merges and phone repairs are never reverted in a batch. Revert a merge on its own.
* Changes past their 30 days are skipped.
* A field someone edited in your CRM since is left as it is, and counted as a conflict.

When it finishes, a message says how many changes were reverted and how many were left,
and why.

Over the API, `POST /api/crm/cleaning/revert-batch` takes the rule and can narrow it to
one run, one object type, one field or a time window. One call reverts at most 1,000
changes, or stops after about 20 seconds, and then says there is more to do. See
[the API](https://docs.clustr-ai.com/crm-cleaning/api.md#revert-a-batch). Your AI assistant does the same with
`revert_crm_cleaning_batch`.

## Failed and conflict

A change is written by a background worker. Before writing, it reads the record again
from your CRM.

**Conflict** means the value in your CRM is no longer the one the scan saw: someone
edited it, or filled a field that was blank. Clustr does not overwrite their edit, and
**nothing is written**. A difference in formatting alone is not a conflict.

**Failed** means your CRM refused the write. Clustr tries again a few times for a
passing error. It stops at once when retrying cannot help: the property does not exist,
the connection lacks a permission, or the value does not fit the property (for example
a dropdown option that does not exist). The reason your CRM gave is shown on the change.

**Retry** puts a failed or conflict change back in line for the worker. In the app it
is on the "changes need attention" banner in **Review**, for the latest scan; over the
API and MCP it works on any failed or conflict change.

* On a failed change, fix the cause first, then retry.
* On a conflict, retry reads the value in your CRM again and **writes the proposed value
  over it**. The app asks you to confirm first. Only retry a conflict when you want
  Clustr's value to win. Formatting fixes
  are the exception: they still stop if the value in your CRM is no longer the same
  value.

If failures keep happening, an alert email goes out. See
[Failure alerts](https://docs.clustr-ai.com/crm-cleaning/health-and-summary.md#failure-alerts).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.