Short answer
A connector decides which HubSpot record to update from an external ID. When two companies carry the same ID, it has two targets and no rule, so contacts, deals, and activity split across twins. Group companies by the ID, then sort the groups: identical name and no conflicting data is safe to merge, same name but different data needs a human decision, and same ID on genuinely different organizations must not be merged at all. Merge keeps the record that holds the activity.
1. What goes wrong
I worked on an IT services client whose CRM synced company IDs from their service management system into a HubSpot property. About 160 of those IDs were on two or more company records in a portal of roughly 32,000 companies. The sync uses the ID to decide which record to update. With two matches it has no tie-break, so contacts, deals, and activity were splitting across the twins. Whoever opened the wrong record saw half the account. Many of the empty twins were old spreadsheet imports with no contacts, deals, or website.
2. Group first, merge later
Export companies with the connector ID property, then group by that value and keep any group with more than one record. Sort every group into one of three buckets before you touch anything:
- Bucket A, safe: identical company name, same ID, no conflicting information. In my case about 100 groups. Keep the record that holds the real activity and merge the empty twin into it.
- Bucket B, needs a decision: same name and ID but two different websites on file. Merging is probably right, but someone has to say which website is correct. In about 30 of 47 cases the answer was obvious from the activity. The rest needed an account owner, because the active record sometimes had what looked like the wrong website.
- Bucket C, leave alone: the same ID on genuinely different organizations. Nine groups were separate chapters of a charity, separate hospital sites, and three unrelated banks. Merging would combine different organizations.
Those are not duplicates. The ID is not unique in the source system, or the source tracks a parent while HubSpot tracks locations. Fix that decision, or the sync will keep feeding bad matches.
3. Merge the safe bucket
Open a company, choose Actions, then Merge, or call the merge endpoint if you have many. HubSpot combines the associations from both records on a merge, so deals and contacts carry over. In my case a company kept its 145 deals and another kept 233 after merging. The old record URLs also redirected to the merged record, so saved links kept working.
POST https://api.hubapi.com/crm/v3/objects/companies/merge
{ "primaryObjectId": "ID_TO_KEEP", "objectIdToMerge": "ID_TO_FOLD_IN" }- Merges are permanent. Merge only the bucket you are sure about, and write every pair you merged to a file first.
- Take the primary from the record with activity, not the oldest or newest by default.
- Check the company count before and after. Mine dropped by about 100.
4. Send the rest back as a short table
For bucket B, a table the client can answer in a few minutes works: company, website on the active record, other website on file. Mark the pairs that look like different businesses so nobody merges them by reflex. A hint here: two organizations that were separate before a merger or rebrand may legitimately have two records.
This article has no HubSpot screenshots because the portal belongs to a client. The merge screen itself is shown in the duplicates article.