> ## 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.

# Review, Findings and merges

> How to work the queue of waiting changes, the findings report, and duplicate merges

CRM Cleaning keeps two lists, and they never mix:

* **Review** holds changes Clustr can write to your CRM and is waiting for you to
  decide on. Everything in it has an Apply button.
* **Findings** holds problems Clustr cannot fix by itself. You fix them in your CRM.

## Review

Review shows every waiting change from every scan, grouped by kind, for example
"Safe · Format & casing · contact · phone". Each group shows its count and a few
examples, with the value before and after.

A change waits in Review when:

* its check is set to **Ask me**; or
* its check is on **Do it**, but the check was not sure, for example a merge between two
  records with near-identical names, or a company association.

Each group is marked:

| Mark | Meaning |
| - | - |
| **Safe** | The check is certain. Safe to apply in bulk. |
| **Your call** | It needs a person to look: it replaces a value someone entered, or the match is a judgement. |

### Apply and dismiss

| Action | What happens |
| - | - |
| **Apply all** on a group | Every change in the group is written to your CRM by a background worker, usually within minutes. |
| **Apply certain merges** on a merge group | Only the Certain pairs are merged. Likely pairs stay until you merge or dismiss each one. |
| **Apply** on one change | That change is written. Select several to apply them from the bottom bar. |
| **Dismiss all ▸ Dismiss these** | The group is cleared and nothing is written. These changes are not suggested again for these records. The same fix on other records still is. |
| **Dismiss all ▸ Dismiss & stop suggesting this** | The group is cleared and Clustr stops suggesting this kind of change. It is listed under **Settings ▸ Advanced ▸ Suppressed**, where you can bring it back. |
| **Dismiss** on one change | That change is cleared and not suggested again for that record. Nothing is written. |

Over the API and MCP, dismissing a group stops the suggestion by default
(`suppress: true`). Send `suppress: false` to only clear it.

Every bulk apply, in the app or over the API and MCP, takes only Certain merges. A
Likely merge is accepted one at a time.

Before writing, Clustr reads each record again. If someone changed the value in your
CRM since the scan, Clustr does not write over it: the change becomes a
[conflict](https://docs.clustr-ai.com/crm-cleaning/history.md#failed-and-conflict).

### When changes leave Review on their own

* **Fixed in your CRM.** When a scan looks at a record again and no longer finds the
  problem, the change closes. History shows it as **Resolved before review** or **No
  longer found**.
* **Not seen for 45 days.** A waiting change that no scan has found again in 45 days
  closes the same way. A change that every scan still finds stays until you decide.

A closed change is never counted as dismissed: if the problem comes back, the next scan
suggests it again.

### Changes that failed

When changes could not be saved to your CRM, Review shows a "changes need attention"
banner with a **Retry** button on each. See
[Failed and conflict](https://docs.clustr-ai.com/crm-cleaning/history.md#failed-and-conflict).

## Findings

Findings counts open problems by kind, and lists each one with a reason and, on
HubSpot, an **Open in HubSpot** link to the record. Expand a duplicate group to see
every record in it, each with its own **Open** link. Each full scan refreshes the list.

| Label | What to do |
| - | - |
| Ownerless record | Assign an owner in your CRM, or change what counts with **Configure** on Ownerless records |
| Incomplete record | Fill the field in your CRM, or turn on [enrichment](https://docs.clustr-ai.com/crm-cleaning/enrichment.md) for it. One row per field, with a count and examples. |
| Lifecycle anomaly | Fix the stage, close date or links in your CRM. The reason says which rule fired, for example "deal is won but not marked closed". |
| Deal has no contacts | Link a contact to the deal in your CRM |
| Duplicate contacts, Duplicate companies | **Merge** them (HubSpot), or dismiss them |
| Duplicate deals | Open each deal, then **Merge** them (HubSpot, deals that share a company) or dismiss them |
| Possible subsidiary | Check them. They look like a parent and a subsidiary, so Clustr never merges them. |
| Identifier shared by unrelated records | Correct the shared value in your CRM, then scan again to see the duplicates it was hiding |
| Unusable values | Fix the value in your CRM: a name that is not a name, a phone number that cannot be read, or a throwaway email address. One finding per record. It closes on its own once a scan sees the fix. |
| Deals that moved back a stage | Check why the deal went back, and correct the stage in your CRM if it was a mistake |
| Normalize domain | The website points at a different company than the domain. Fix the website or the domain in your CRM. |

### Export findings

**Export CSV** next to the search downloads every open finding that matches the kind
and search you picked. Each row has the kind, the object type, the record id and name,
the reason, when it was first and last seen, and a link to the record in HubSpot. A
file holds at most 50,000 rows. Over the API, use
[`GET /api/crm/cleaning/findings/export`](https://docs.clustr-ai.com/crm-cleaning/api#export-findings).

### Dismiss findings

* **Dismiss** on one finding clears it.
* **Dismiss all ▸ Dismiss these** clears the kind. The findings you dismissed are not
  reported again, but the same problem on other records still is.
* **Dismiss all ▸ Dismiss and stop reporting this** clears the kind and stops reporting
  it.

Dismissing a finding changes nothing in your CRM. Over the API and MCP, dismissing
findings does not stop reporting by default (`suppress: false`).

## Duplicates and merges

Clustr groups records that look like the same contact or company. Deals follow their
own, stricter rules: see [Duplicate deals](#duplicate-deals).

| Match | Companies | Contacts | Certainty |
| - | - | - | - |
| Same identifier | Website domain, LinkedIn URL | Email, LinkedIn URL | Certain, when the names agree |
| Same phone number | Phone, with a similar name | Phone or mobile phone | Likely. Contacts are Certain when both full names agree |
| Same or near-identical names | Company name | First and last name, and company | Certain when the names are exactly the same, otherwise Likely |
| One name inside the other | "First" and "Nova First" | | Likely: always asks |
| Your match rule | The fields you choose | The fields you choose | Likely: always asks |

* Personal email domains and link shorteners never count as a shared identifier.
* A role mailbox such as `info@`, `sales@` or `contact@` never counts as the same
  person: two people can share one.
* Person names are compared without accents, so `Hélène` and `Helene` match.
* Phone numbers are compared in international form, so `+33 6 48 27 19 53` and
  `06 48 27 19 53` on a French record match, and a contact's phone can match another
  contact's mobile. Numbers need at least 8 digits.
* A phone number alone is never Certain. Two contacts on one number whose names
  disagree are not matched at all, and companies need a similar name as well as the
  number.
* A number shared by more than 3 records, such as a switchboard or an office line,
  is ignored. So are placeholders such as `0000000` or `123456789`.
* When one company name sits inside the other, the websites must agree: if both
  records have a website, it must be the same one, and if only one has a website, the
  other's name must appear in it. Two companies with different websites never match.
* Two contacts that share an email or LinkedIn URL but whose names disagree are shown
  with **Names differ**. They are Likely, never Certain.

### Your own match rules

Under **Settings ▸ CRM Cleaning ▸ Match rules** you can add up to 5 rules for contacts
and 5 for companies. A rule is a list of fields, for example contacts with the same
**First name**, **Last name** and **Company**, or companies with the same **Name** and
**City**. Two records match a rule when every field in it is filled and the same on
both.

* Values are compared ignoring case, accents and extra spaces, so `Saint-Étienne` and
  `saint-etienne` match. Phone numbers are compared as numbers, emails in lower case,
  domains and LinkedIn URLs the way the built-in matching reads them.
* A blank field never matches.
* A rule only adds pairs. The built-in matching still runs, and a pair it already
  found keeps its own reason.
* A pair found only by your rule is always Likely: it waits for you and never merges on
  its own. It shows the rule's fields in alphabetical order, as "Your rule: company +
  first\_name + last\_name".
* Two contacts whose names disagree are not matched by a rule either.
* A value many records share, such as a common job title, is ignored, the same way an
  office phone number is.

Contacts can use first name, last name, email, phone, mobile phone, job title, company,
LinkedIn URL, city, state, postal code and country. Companies can use name, domain,
phone, industry, LinkedIn URL, city, state, postal code and country.

### Two ways to merge

* **From Review.** With Contact duplicates or Company duplicates on **Do it**, certain
  matches merge on their own and the rest wait in Review as pairs, marked **Certain** or
  **Likely**. Each pair shows why it matched, for example "Same LinkedIn: in/ana-silva"
  or "Same email: [ana.silva@northwind.example](mailto:ana.silva@northwind.example)", the record to **Keep**, the one to
  **Merge into it**, and the value each field would keep. **Apply certain merges**
  applies only the Certain pairs. Merge each Likely pair on its own with **Merge**, or
  **Dismiss** it.
* **From Findings.** Click **Merge** on a duplicate group, then confirm. Clustr reads
  the records again from your CRM, picks the record to keep, and queues one merge per
  other record. The button only shows on a CRM that can merge.

Merging needs **HubSpot**. Salesforce and Attio have no merge API, so their duplicates
are reported but cannot be merged. See [capabilities by provider](https://docs.clustr-ai.com/crm-cleaning-capabilities.md).

### Which record is kept

By default Clustr keeps, in this order:

1. the record that has an owner, because that is the one a rep works;
2. then the most complete record;
3. then the most recently updated one;
4. then the one created first.

To choose differently, add rules under **Settings ▸ CRM Cleaning ▸ Record to keep**.
They are checked in order, before the default: the first rule that tells two records
apart decides, and when none does, the default above decides.

| Rule | Keeps |
| - | - |
| Has an owner | The record with an owner |
| Furthest lifecycle stage | The record further along subscriber, lead, MQL, SQL, opportunity, customer, evangelist. A blank or other stage counts as the lowest. |
| Oldest record | The record created first |
| Most recently updated | The record changed last |
| Most fields filled | The record with the most filled fields |
| Field has a value | The record whose field, such as `lead_status` or a CRM property like `hs_analytics_source`, has the value you set. Case and accents are ignored. |

Up to 10 rules. They apply to the pairs a scan proposes and to a merge started from
Findings, so run a scan after changing them to refresh the pairs already waiting.

For each field, the kept record keeps its own value, and a blank is filled from the
other record. The **Kept** column of a pair shows exactly that: what your CRM will hold
after the merge. For a name field, the kept record gets the richer spelling of the
same name: `O'Connor` over `Oconnor`, `Hélène` over `Helene`.

To keep a different value for a field, pick it when you accept the merge. Over the API,
send `field_overrides` when you [accept the change](https://docs.clustr-ai.com/crm-cleaning/api.md#one-change).

Over the API, `survivorship` in the settings changes the policy:

| Setting | Options |
| - | - |
| `strategy` | `most_complete` (default: owner first, then the order above), `most_recent`, `system_of_record` (needs `source_priority`), `custom` (with `custom_survivor_id`) |
| `default_field_rule` | `non_empty` (default: keep the kept record's value, or else the most recent value that is not blank), `most_recent`, `source_of_truth` |
| `field_rules` | A rule per field, for example `{ "phone": "most_recent" }` |
| `primary_rules` | The Record to keep rules, in order: `[{ "kind": "lifecycle_stage_rank" }, { "kind": "property_equals", "property": "lead_status", "value": "Qualified" }]`. Kinds: `has_owner`, `lifecycle_stage_rank`, `oldest_created`, `newest_updated`, `most_complete`, `property_equals`. A pinned `custom_survivor_id` still wins. |

Custom match rules are `match_rules` in the settings:
`{ "contact": [{ "fields": ["first_name", "last_name", "company"] }], "company": [{ "fields": ["name", "city"] }] }`.
A rule holds at most 6 fields. An unknown field, a field named twice, an empty rule, the
same rule twice or more than 5 rules for one object type is refused.

### Duplicate deals

Two open deals are reported as duplicates only when all of these hold:

* they are in the same pipeline;
* they are linked to the same company;
* their names match. Case, accents, punctuation and spacing are ignored, and so is a
  trailing `(copy)`, `- copy` or `[clone]`, or the company's own name, so
  `Website redesign - Northwind` matches `Website redesign`. A number is kept:
  `Seats #1` and `Seats #2` never match, because they are usually two deals;
* their amounts are the same, or neither has an amount, and when both have a
  currency it is the same;
* they were created within 90 days of each other.

Duplicate deals are looked for on full scans only. Closed deals, won or lost, are never
reported. Deals that match on everything but have
no company are still listed, but only as a report: Clustr cannot tell them from two
real deals, so it never offers to merge them. A deal with a company never matches a deal
without one.

On HubSpot, **Merge** on a group of deals that share a company merges them into one,
one group at a time and only when you click it. Clustr reads the deals again first and
stops if they no longer match: one has closed, or its pipeline, company, name or
amount changed. It keeps the deal with more contacts, or else the one created first. A deal merge **cannot be
reverted**. Salesforce and Attio report duplicate deals but cannot merge them.

To stop reporting duplicate deals, set **Duplicate deals** to **Off** in
[Checks](https://docs.clustr-ai.com/crm-cleaning/checks.md#findings).

### Merges are permanent

Your CRM has no unmerge. History offers **Revert** on a merge for 30 days, but it
recreates the archived record as a **new record with a new id**. See
[Revert](https://docs.clustr-ai.com/crm-cleaning/history.md#revert). A deal merge has no Revert.

To stop every merge at once, set `merge_enabled` to `false` in the
[settings](https://docs.clustr-ai.com/crm-cleaning/settings.md#settings-only-the-api-sets). Everything else keeps
running.


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