Skip to main content
CRM data decays. People change jobs, emails start to bounce, and the same person ends up in the database twice. This workflow imports a CRM export into Fuse, merges duplicate contacts, re-verifies the emails you already have, finds missing emails and phones, keeps your CRM-only fields alongside, and pushes the result back to HubSpot, Salesforce, Zoho, Attio or Pipedrive without overwriting fields your team has already filled in.

Before you start

Step by step

1

Upload the export

Send files up to 10 MB as multipart. Parsing is free and writes nothing to a list yet:
For files up to 50 MB, call POST /business/imports/presign with the filename and contentType, PUT the raw bytes to the returned uploadUrl with the same Content-Type within 10 minutes, then call POST /business/imports with { "importId": "…" }.
2

Commit it into a list

Confirm the mapping and choose the destination. Leave enrichment off for now, so you never pay to enrich the same person twice before duplicates are merged:
Mapping values are fixed labels: Full Name, First Name, Last Name, LinkedIn URL, Company, Company Domain, Job Title, Job Level, Department, Industry, Country, State, City, Email and Phone. Headers you leave out fall back to the suggestion. Anything that maps to none of them comes back in ignoredHeaders; step 5 brings those values back.onDuplicate: "merge" fills the empty fields of a contact already on the list instead of adding the row twice. Poll GET /business/lists/{listId} until completionStatus is complete. The jobId is a reference only and cannot be polled.
3

Merge duplicate contacts

The import only checks the destination list, so the same person can still exist elsewhere in your workspace. Scan the whole workspace for contacts that share an email:
Poll GET /business/contacts/dedupe-jobs/{jobId} until status is completed, then page through scanResult.groups with pageNum and limit. Each group shows a mergePreview of the surviving contact and the lists its members belong to. Merge the groups you approve:
Losing contacts are archived and their list memberships move to the survivor, so your import list still holds each person once. A second scan on ["linkedinUrl"] catches people stored under two different emails.
Merges cannot be undone. Review mergePreview for every group before you submit it. The full flow is in Deduplicate contacts.
4

Re-verify emails, then fill the gaps

First re-verify the emails your CRM already holds, at 10 credits per address:
validate_emails covers at most 5,000 contacts per call, so import larger exports as several lists. When the list is complete again, find what is missing:
Contacts that already carry an email or phone are not charged for it again. To spend only where it matters, add filters, for example { "country": ["united states"] } for phone numbers you will dial. This call answers with a jobId: poll GET /business/jobs/{jobId} until status is completed, then read metrics on GET /business/lists/{listId}. Before it starts, the balance must cover 250 credits for every contact it takes, the most an email and a phone can cost together.
5

Keep your CRM fields on the rows

Imports keep the standard fields only, so CRM fields such as the contact owner arrive in ignoredHeaders. Bring them back as custom columns:
Page through GET /business/lists/{listId}/rows, match each row to your file by primaryEmail, and write the values in batches of up to 500:
These columns appear in exports, and campaigns can use them as tokens such as {Column: CRM owner}. A url column with a label and value makes a clickable link back to the CRM record.
6

Push the clean list back to your CRM

Check which CRMs are connected, then push the list:
Pushing the whole list creates the people your CRM is missing and, on records it already has, fills only fields that are empty, so your team’s edits stand. The push runs in the background with no job to poll, using the field mapping saved in the app. People with no email or phone are not pushed; see Contacts and companies.
Sending contactIds pushes only those contacts and overwrites fields on records that already exist in the CRM. Use it when you mean to refresh specific records, not for a routine sync.

Run it on a schedule

Repeat the workflow monthly on a fresh export of recently changed records. Commit it into the same list with listId and onDuplicate: "merge", scan for duplicates again, then re-run enrichment and the push. Enrichment never charges twice for data a contact already has, so each run pays only for what is new.

What it costs

Troubleshooting

Run the whole workflow

Do it from Claude

Deduplication and file imports are not available over the Fuse MCP server yet, so run steps 1 to 3 with the API. After that, one request covers the rest:
Find missing work emails and phone numbers for the contacts on my list “HubSpot contacts - Oct 2026”, then push the list to HubSpot.
The assistant uses its list and enrichment tools, then pushes the list to HubSpot. The push writes to your CRM as soon as it runs, so keep your client’s approval prompt on for it.

Deduplicate contacts

Match fields, merge rules and how scans page their groups.

Working with lists

Imports, enrichment modes and pushing to a CRM.

CRM sync

What Fuse writes to each CRM, and how matching works.

Custom columns

Column types, writing values and using them in campaigns.