CRM Attachment Migration: Verify Files, Links, and Access

Published on
Last updated
Reading time8 min read
CRM Attachment Migration: Verify Files, Links, and Access

CRM attachment migration is complete when the required documents open from the correct destination records, contain the agreed versions, and remain available only to the intended people. Count files, but sign off against identities, contents, relationships, and access together.

This guide is for CRM administrators moving sales or service documents between systems. It adds destination acceptance checks to the broader CRM migration checklist. In our executed fictional exercise, all seven scenarios contain the expected four file rows. Six still fail reconciliation. The downloadable example lets you see exactly which defects a count misses.

CRM attachment migration: agree what must move

Write the scope before choosing an upload route. A current sales workspace might need only the latest signed agreement. A dispute archive might need drafts, previous versions, and their dates. Those are different delivery requirements, even if both teams describe the job as moving attachments.

For each document category, record:

  • which source objects and record filters are included
  • whether the requirement is latest version or full history
  • every business record from which the document must be reachable
  • who should be able to open it and who should be denied
  • whether the destination must retain authorship and original timestamps
  • how approved exclusions will remain discoverable

A file stored outside the CRM can be an intentional destination. Document the repository, ownership, access controls, and durable record reference. A copied link into an account page does not establish that the underlying document will survive cancellation of the old service.

Start with CRM export completeness to accept the source package. This article starts at the next boundary: verifying the destination after loading. Neither a good export nor a successful upload response proves that a salesperson can retrieve the right agreement from the right deal.

Keep file identity separate from record identity

Use a mapping ledger with source document ID, source version ID, destination file ID, source parent ID, and destination parent ID. Keep object types alongside record IDs when the source has several kinds of records. A contact, deal, and company can each need its own destination mapping.

Filenames are labels, not reliable identifiers. Our fixture contains two different documents named agreement.txt. Matching on that name alone cannot establish which customer owns either document. A checksum can reveal byte equality, but two records may legitimately share identical content. Preserve document identity and required relationships even when you deduplicate physical storage.

Store one row per required document-to-record relationship in the link ledger. One document linked to an account and a deal produces two expected relationships. The upload ledger may still contain one destination file. Reconcile each ledger against its own expected set rather than expecting their row counts to match.

LedgerMatch onReview separately
DocumentsSource and destination file IDsMissing or duplicate mappings
VersionsDocument ID and version identityRequired contents and current version
Record linksFile ID, object type, parent IDMissing or extra relationships
Access checksFile, test identity, observation timeAllowed and denied outcomes

Resolve duplicate and merged source records before generating destination links. The CRM merge survivorship decision can change which account or contact should retain a document. Keep the approved redirect in the mapping ledger instead of silently attaching the file to the first matching name.

Three vendor details that change the acceptance test

We checked the following public developer documentation on October 30, 2026. These are documented data-model observations. We did not migrate files through logged-in HubSpot or Salesforce accounts, measure their reliability, or compare subscription entitlements.

HubSpot's Notes API documentation describes attachment IDs in hs_attachment_ids, with note-to-record associations specified separately. For that documented route, inspect both the note's file references and its destination record associations. Finding a file in storage alone does not answer whether it appears on the intended timeline.

The HubSpot Files guide distinguishes public files from private files requiring signed URLs. It also says the ordinary URL returned for a private file produces a 404. Check the intended access path before classifying that response as missing content. Treat a signed link as temporary access, and avoid storing one as the permanent migration reference. Public non-indexable files remain publicly accessible to people with the URL; noindex is not an access control.

Salesforce's ContentDocumentLink reference describes sharing a file with records and other destinations. It lists ContentDocumentId, LinkedEntityId, ShareType, and Visibility separately. Include relationship and sharing evidence in the acceptance report rather than accepting a document inventory alone.

These details suggest different checks, not a universal import recipe. Ask the migration provider which supported route it uses, what objects it covers, and how it translates access. Confirm the current documentation and edition for your own accounts before scheduling the move.

CRM attachment migration checks: replay seven cases

We created and ran a Python reconciliation exercise on October 30, 2026. It defines four invented documents, six required record links, and two expected role outcomes per document. The scope is latest-version only. The contents are short text byte strings, not customer documents or realistic office files.

The baseline contains the expected version, bytes, mapped parents, and role outcomes. Each remaining scenario changes one category on the first document. The stale-version scenario changes both its version label and contents, representing a draft loaded instead of the agreed revision.

ScenarioFile countReconciliation
Baseline4 of 4Pass
Wrong deal linked4 of 4Record links fail
Second record link missing4 of 4Record links fail
Older version loaded4 of 4Version and bytes fail
Contents changed4 of 4Bytes fail
Other team gains access4 of 4Access fails
Intended owner loses access4 of 4Access fails

All seven pass the count check. One passes reconciliation; six fail. These counts describe deliberately constructed examples, not a migration failure rate or evidence that either vendor permits these defects.

Download the Python source and recorded JSON results. Run python3 reconcile.py with Python 3 and compare its output with the JSON. The script uses only the standard library and makes no network calls.

The checker compares source identities, unique destination IDs, required version labels, SHA-256 hashes, exact mapped parent lists, and the supplied role outcomes. It does not parse documents, inspect real permissions, establish that an ID belongs to a real record, or exercise a CRM. The role outcomes are fictional inputs. For a real acceptance run, collect those observations through supported interfaces and authorized test identities.

Use the result to write a test request

Ask a provider to demonstrate one document attached to two business records, another document with the same filename, and a document with a required prior version. Add one permitted reader and one restricted reader with known expected outcomes. Have the reviewer begin from each business record rather than a global administrator file search.

This small request exposes a mapping problem earlier than a large load of easy records. Expand the sample to cover your actual formats, object types, file sizes, external repositories, and sharing exceptions. Keep the test environment isolated using the CRM sandbox refresh checks.

Verify contents through the supported download path

Where unchanged bytes are required, hash the source reference and the downloaded destination content. Match the intended version before comparing. A different checksum identifies a byte difference; it does not explain the cause. Check for an approved conversion, a wrong version, or a download response containing an error page.

A matching checksum establishes equality against that reference. It does not establish authenticity, safe contents, legal sufficiency, or that a reader can open the format. Open a small authorized sample in its normal application as a separate check. Include required languages, document formats, and any encryption or password handling that affects your workflow.

If the destination converts documents, byte equality may be an unsuitable acceptance condition. Record the approved transformation, retain the source reference where required, and define content checks for the converted result. Do not turn every checksum difference into an automatic rejection without reviewing the agreed scope.

Keep this verification read-only. Separate upload credentials from ordinary reader access when planning CRM integration permissions. Budget repeated downloads and metadata lookups in your CRM API rate-limit plan, especially when the source has a narrow retirement window.

Check denied access as well as allowed access

An administrator opening a file proves little about a seller or support agent's permissions. Record a small access matrix: document category, named test role, expected open result, actual result, and observation time. Cover both the destination record and the file download path used by that role.

Test a permitted reader from the normal workflow. Then use an authorized restricted test identity to verify the expected denial. Where a file is intended to be private, inspect public-link settings and test an unsigned direct request without copying bearer links into shared logs. Keep signed URLs and credentials out of the evidence report.

Do not copy source sharing flags without checking their destination meaning. Group membership, ownership, record sharing, and file-level settings may interact differently. If translating an old access rule requires a broader destination audience, obtain an explicit scope decision before release. Record the affected documents and proposed control rather than calling the difference harmless.

Use the same ownership decisions as your CRM field-ownership policy and the same acceptance owner as your sales handoff SLA. The document's uploader may have no authority to decide who should read customer contracts.

Close the delta and keep a recoverable receipt

Files can change while the main migration runs. Record the source observation time and define a final delta covering new documents, new versions, changed links, and changed access. Reconcile that delta before accepting the destination. A timestamp alone will miss changes if the selected API or export does not expose them reliably, so confirm how the provider detects each change type.

Keep retries tied to stable source identity. After an uncertain upload response, inspect the destination mapping before submitting another copy. Reconcile extra destination files and extra links as well as missing items. A retry that creates duplicate documents can leave readers with competing versions of the agreement.

Retain a receipt containing the scope, mapping ledgers, source references or checksums, destination observations, exclusions, failures, reviewer, and sign-off time. Store useful evidence through the CRM audit-log retention plan. Agree who maintains files after the move in the CRM implementation checklist.

Keep the source or an approved archive available through the acceptance window. Retiring copies afterward belongs in the CRM deletion policy, with the destination and external repositories included in scope. Storage, migration tooling, and ongoing administration belong in the CRM total cost of ownership.

Actionable takeaways

  1. Approve document, version, relationship, and access scope before loading files.
  2. Preserve stable IDs and map every required business-record link.
  3. Verify downloaded contents and open a representative authorized sample.
  4. Record permitted and denied access through the normal user workflow.
  5. Reconcile the final delta and exceptions before retiring the source.

Frequently Asked Questions

What should a CRM attachment migration checklist include?

Include document scope, required versions, source-to-destination IDs, record links, downloaded contents, allowed and denied access, final changes, and exclusions. Keep the acceptance evidence with a named reviewer and sign-off time.

Is a matching file count enough to accept a migration?

No. Files can have the correct count while containing the wrong version, pointing to the wrong deal, or exposing content to the wrong audience. Compare identities, contents, relationships, and observed access against the approved scope.

Should every historical attachment version move?

Choose based on the business requirement and supported destination behavior. Latest-only and full-history moves have different expected counts. Record approved omissions and the location of any separately retained archive before signing off.

Does a private file returning 404 mean it was lost?

Not necessarily. HubSpot's documented private-file route requires a signed URL to view the content. Verify the intended authenticated or signed access path and the file's identity before treating the ordinary URL's response as evidence of loss.

Does the downloadable checker test HubSpot or Salesforce?

No. It reconciles invented records, byte strings, links, and supplied access outcomes locally. It demonstrates acceptance rules. Real CRM behavior requires observations from your own authorized accounts and supported migration route.

Bring an attachment example to the CRM evaluation

Use the CRM requirements checklist to turn document handling into a demonstration request. If file sharing across complex records is central to the move, bring the same sample to the HubSpot vs Salesforce comparison. If your shortlist includes Zoho, use Zoho CRM vs HubSpot to assess broader fit, then request evidence for the attachment workflow in each account.

Choose against the acceptance criteria you can verify. Keep unresolved file, version, link, or access exceptions visible until the business owner approves their disposition.