GuideDeveloperSmart CRMDeveloper

Your script created duplicate HubSpot records? Merge them, don't delete them

A bulk write through the API does not dedupe for you. When it goes wrong, the cleanup choice matters more than the bug.

Subscription
Any tier with a private app
Permissions
Private app with CRM write scopes
Time
15 min · Advanced
Last verified

Short answer

The CRM API creates whatever you send. Companies are not deduplicated by domain on API create, so a script that retries or runs twice produces duplicates. Clean up with HubSpot's merge endpoint, not delete, because merge keeps the associations, activities, and history from both records. Then change the script to search first or to upsert on a unique property.

1. How the duplicates happen

While loading company lists into a portal for a project of mine, a bulk write I ran created duplicate companies. Two things combined: the script was run in more than one phase, and the API does not enforce uniqueness on company domain. HubSpot's own guidance says the same about imports: only a unique identifier matches records. See import created duplicates for that side.

You can merge a pair by hand in the portal. Open a record and the same Actions menu that offers Opt out of email also offers Merge.

Contact record Actions menu with Merge highlighted
Actions menu with Merge on a record. Details are blurred.

2. Merge, do not delete

When the duplicates number in the dozens or more, merge from the script. I chose merge over delete because merging keeps associations from both records. Deleting the extra loses whatever was attached to it. The endpoint takes the record to keep and the record to fold in:

POST https://api.hubapi.com/crm/v3/objects/companies/merge
{
  "primaryObjectId": "PRIMARY_ID",
  "objectIdToMerge": "DUPLICATE_ID"
}

Contacts use the same shape at /crm/v3/objects/contacts/merge. Merging is permanent, so dry-run first: write the pairs to a file, review a sample, then run.

3. Stop it recurring

  • Search before create. Query by domain (companies) or email (contacts) and create only on zero hits.
  • Upsert on a unique property. Where an object has a unique property, batch upsert with idProperty updates instead of creating.
  • Make runs idempotent. Log the IDs your script creates so a re-run reads them instead of creating again.
  • Check counts after every batch. I verify the total against what I expected, which is how the duplicate defect showed up.

Sources

New field notes by email

One email when a new article publishes.

Still stuck?

If this did not fix it, the problem is probably specific to your setup. Book a call and we will look at it together.

Book a call with Sam