Freshdesk to HubSpot Service Hub Migration: The Technical Guide
A technical guide to migrating Freshdesk to HubSpot Service Hub — covering API limits, data mapping, inline image handling, and every migration method.
Migrating from Freshdesk to HubSpot Service Hub is a data-model translation problem, not a sync toggle. You are moving from a flat, ticket-centric system into a deeply interconnected CRM architecture. The challenge is not moving tickets — it is preserving the full context behind each ticket: threaded conversations, private agent notes, inline images, attachments, and the associations that tie every record to the right contact and company.
HubSpot's native Freshdesk integration will not get you there. It was designed for ongoing sync, not one-time migration — and it leaves behind the majority of what your support team actually needs.
This guide breaks down the API constraints on both sides, the complete data-mapping table, the structural mismatches that cause silent data loss, and every migration method available — so you can pick the approach that matches your volume, timeline, and risk tolerance.
For a deeper look at HubSpot Service Hub's architecture, pipelines, and help desk configuration, see The Ultimate 2026 Guide to HubSpot Service Hub. If you are preparing your HubSpot instance before importing data, follow the HubSpot Service Hub Migration Checklist.
Why the Native Freshdesk–HubSpot Sync Isn't Enough
Syncing is not migrating. A sync keeps two live systems aligned going forward. A migration is a one-time, complete transfer of historical data into a new system. If you are fully decommissioning Freshdesk, a sync will always leave gaps.
There are three native tools in this stack, and they are not equivalent:
Freshdesk's HubSpot CRM Connector (published by Freshworks) syncs only contact and account data, supports one-way data flow, and explicitly states that two-way sync is unavailable. It is useful for CRM context inside Freshdesk, but it is not a ticket migration path. (support.freshdesk.com)
HubSpot's Freshdesk Data Sync marketplace app is broader. HubSpot says it supports two-way, real-time sync, default field mappings, historical syncing, and shared objects for companies, contacts, and tickets. That makes it a viable coexistence or forward-sync tool — but it comes with hard limits. (ecosystem.hubspot.com)
The native integration only syncs tickets from the last 120 days — anything older is left behind. It doesn't transfer full conversations, excludes private and public notes, and important internal documentation is lost. It also loses authorship, timestamps, and metadata, and breaks threaded email chains.
Freshdesk stores a complete history of conversations with each ticket, but the native integration doesn't transfer conversations at all — it only moves the ticket title and basic metadata.
HubSpot's Smart Transfer, launched on January 13, 2026, is closer to a migration workflow. It can audit the source system, configure properties and pipelines, sync selected records, and run one-time post-sync transfers for data that data sync does not handle. For Freshdesk specifically, Smart Transfer documents one-way transfer into HubSpot, maps Contacts → Contacts, Companies → Companies, and Tickets → Tickets, and lists Attachments as the only one-time post-sync transfer type. It does not explicitly list Freshdesk ticket conversations or comments as supported transfer types. It requires Data Hub if you want custom field mappings. (knowledge.hubspot.com)
Here is what each native option actually handles:
| Capability | Freshdesk Data Sync | Smart Transfer | Full API Migration |
|---|---|---|---|
| Tickets created in last 120 days | ✅ Basic metadata | ✅ All synced tickets | ✅ All tickets, any age |
| Tickets older than 120 days | ❌ Not synced | ❌ Not documented | ✅ Full history |
| Full conversation threads | ❌ Not transferred | ❌ Not listed for Freshdesk | ✅ Emails, replies, forwards |
| Private and public notes | ❌ Excluded | ❌ Not listed | ✅ Preserved with authorship |
| Inline images | ❌ Lost | ❌ Not handled | ✅ Re-hosted and linked |
| Attachments | ❌ Partial at best | ✅ One-time transfer | ✅ Uploaded to File Manager |
| Timestamps & authorship | ❌ Overwritten | ❌ Not preserved | ✅ Preserved via hs_timestamp |
| Contacts & companies | ✅ Supported | ✅ Supported | ✅ Full field mapping |
If your team needs historical context — and for any regulated or customer-facing team, you do — native tooling is a starting point for ongoing sync at best, not a migration solution.
Do not confuse HubSpot's Operations Hub data sync with a migration. Ops Hub is designed to keep two active systems in sync going forward. It will not backfill years of Freshdesk ticket history. And do not treat historical syncing as proof of full conversation fidelity — HubSpot's marketplace app for Freshdesk advertises historical syncing for existing records, but Smart Transfer currently does not explicitly list Freshdesk ticket comments or conversations.
Data Mapping: Translating Freshdesk Objects to HubSpot
Freshdesk and HubSpot organize support data differently. Freshdesk is ticket-centric with a flat conversation model: a contact creates a ticket, the ticket contains conversations (replies, notes, forwards), and each conversation can have attachments. Companies exist but are loosely coupled.
HubSpot Service Hub is CRM-centric and association-driven: a ticket is a CRM object associated to contacts, companies, and engagement objects (notes, emails, calls, meetings). Conversations don't live inside the ticket record — they are separate engagement objects linked via associations.
This structural difference is where data silently disappears if the migration script doesn't account for it.
Object Mapping Table
| Freshdesk Object | HubSpot Object | Migration Notes |
|---|---|---|
| Contact | Contact | Map email as unique identifier. Freshdesk contacts can carry other_emails and other_companies — deduping only on primary email is risky on older or merged accounts. Custom fields → custom properties. |
| Company | Company | Map by domain or company name. Freshdesk loosely couples companies; HubSpot strongly enforces company-to-contact associations. Create the Company first, the Contact second, then associate them via the Associations API. HubSpot has distinct default association types for company-to-ticket, primary-company-to-ticket, contact-to-company, and contact-to-primary-company. |
| Ticket | Ticket | Map to hs_pipeline + hs_pipeline_stage. Subject → subject. Preserve the Freshdesk ticket ID in a custom HubSpot property for reconciliation. Never rely on subject lines or requester email alone for matching. |
| Conversation (reply) | Note or Email engagement | Each reply becomes a separate engagement associated to the ticket. Freshdesk public replies and private notes live in the same conversation family but carry different meaning — flattening everything into notes preserves history but loses the customer-visible vs. internal distinction. |
| Private Note | Note engagement | Use hs_note_body with HTML. Mark internal via naming convention. |
| Public Note | Note engagement | Preserved as timeline entry on the ticket. |
| Attachment | File (File Manager) → Note | Upload via /files/v3/files, then link file ID in hs_attachment_ids on the note. |
| Agent | Owner | Map Freshdesk agent IDs to HubSpot owner IDs. |
| Group | Team or Pipeline | Freshdesk groups often map to separate HubSpot pipelines or team assignments. |
| Tags | Custom multi-select property | No native tag object on HubSpot tickets. Create a multi-select property. |
| Custom Fields | Custom Ticket Properties | Create properties in HubSpot before import. Match data types exactly. |
| Satisfaction Ratings | Custom property | No 1:1 mapping. Migrate as a custom property on the ticket. |
In HubSpot, activities are also called engagements. You must associate existing tickets with other CRM records or activities — calls, emails, meetings, notes — to reconstruct the full conversation history.
When you add a file to a record in HubSpot, it creates a note with the file attached and adds it to the record timeline. To add a file to a record via API, you create a note associated with a record and attach the file to the note.
The practical consequence: migrating a single Freshdesk ticket with 5 conversation replies and 3 attachments requires at minimum 10 HubSpot API calls — create the ticket, upload 3 files, create 5 note engagements with associations, and associate the ticket to the contact and company. For 50,000 tickets, you are looking at hundreds of thousands of API calls before accounting for retries.
Custom Fields and Statuses
Freshdesk allows agents to create custom ticket fields on the fly. HubSpot requires all custom properties to be defined in the CRM settings before data can be ingested. If a Freshdesk ticket contains a value for a custom field that doesn't exist in HubSpot, the field value is silently dropped — no error, just missing data.
Freshdesk's default statuses (Open, Pending, Resolved, Closed) must be mapped to HubSpot's Ticket Pipeline stages. If you use custom statuses in Freshdesk (e.g., "Waiting on Third Party"), create a corresponding pipeline stage in HubSpot before initiating the transfer.
Custom drop-downs in Freshdesk must exactly match the internal values of the corresponding HubSpot property. A mismatch on internal value names will cause the entire API payload to be rejected.
The Crosswalk Table
Maintain a source-to-target ID map for contacts, companies, tickets, conversations, and attachments throughout the migration. This is what lets you run deltas, repair failed batches, and prove that a HubSpot record came from a specific Freshdesk record.
freshdesk_ticket_id -> hubspot_ticket_id
freshdesk_contact_id -> hubspot_contact_id
migration_batch -> 2026-04-15-bulk-01
status -> migratedAlways create your custom ticket properties in HubSpot before starting the migration. If a property doesn't exist when the API call hits, the field value is silently dropped — no error, just missing data.
API Rate Limits and Technical Bottlenecks
Both Freshdesk and HubSpot enforce rate limits that will throttle any migration script. Understanding these constraints before you write a line of code determines whether your migration takes hours or weeks.
Freshdesk API Limits
Freshdesk's v2 REST API uses Basic Auth, page-based pagination capped at 100 records, and per-minute rate limits (200–700 calls/min by plan).
| Freshdesk Plan | Rate Limit |
|---|---|
| Trial | 50 requests/min |
| Growth | 200 requests/min |
| Pro | 400 requests/min |
| Enterprise | 700 requests/min |
This limit is applied to your account irrespective of the number of agents you have or IP addresses used to make the calls. Every marketplace app, webhook, and custom script shares the same pool. If your team runs Freshdesk integrations with Slack, Jira, or a chatbot while the migration script is running, they all compete for the same quota.
Trial accounts are capped at 50 requests per minute. If you are testing your migration script against a Freshdesk trial instance, you will hit a hard wall almost immediately. Always test against your production-tier plan with a controlled subset of data.
Freshdesk also enforces endpoint-level sublimits. On the Growth plan, the Tickets List and Contacts List endpoints are limited to just 20 requests per minute. The bottleneck is often not raw plan capacity — it is the read pattern of your extractor. A script that repeatedly re-queries tickets for pagination, requester lookups, and conversation expansion can hit source throttles long before the global limit. Invalid requests count toward the limit, and marketplace apps consume API calls from the same pool. (support.freshdesk.com)
Pagination ceiling: Using Freshdesk REST API v2 you can load a maximum of 30,000 tickets (max page number: 300 and max 100 items per page). If your Freshdesk instance has more than 30,000 tickets, you must segment your export using the updated_since parameter with date-range slicing.
The Filter Tickets API is even more restrictive. That is a hard ceiling of 300 results (30 per page × 10 pages) from a single filter query. The created_at parameter is strictly a date datatype (YYYY-MM-DD), so you cannot partition the data according to hours.
Freshdesk stores up to ten conversations embedded within a ticket response when you use the include=conversations parameter, but this consumes extra API credits. If a ticket has more than ten conversations, you must page through the dedicated conversations endpoint separately. (developers.freshdesk.com)
HubSpot API Limits
For private apps, the burst limit is 190 requests per 10 seconds. For enterprise subscriptions, the daily limit is 1 million requests per day.
For public apps, the burst limit is 110 requests per 10 seconds.
| HubSpot Auth Type | Burst Limit | Daily Limit |
|---|---|---|
| Private App (Pro/Enterprise) | 190 / 10 seconds | 500K–1M / day |
| Public OAuth App | 110 / 10 seconds per account | Varies |
| CRM Search API | 5 requests / second (shared) | Part of daily quota |
HubSpot's certification guidance recommends throttling to 100 requests per 10 seconds per connected account to avoid bursting into 429 errors. (developers.hubspot.com)
The CRM search API is capped at 4 requests per second across all search endpoints. That's not per endpoint — it's shared across contacts, deals, companies, and every other object type. If you are using search for deduplication during import, this becomes your primary bottleneck.
Batch endpoints count as one request. HubSpot's batch create/update endpoints let you process up to 100 records in a single API call. Use batch endpoints aggressively — they are the single biggest throughput multiplier on the HubSpot side. Instead of creating contacts one by one, the /crm/v3/objects/contacts/batch/create endpoint lets you pass an array of up to 100 records in a single network request.
Standard Promise.all() loops in Node.js will immediately blow past the burst limit. Your script must implement exponential backoff with jitter, and you should use a queuing system (like BullMQ backed by Redis) to manage the flow of data within the 10-second rolling window.
Some APIs also behave with eventual consistency, meaning a request may succeed, but immediate follow-up calls (such as reads after writes) may fail or return incomplete data. If your script creates a ticket and immediately tries to associate a note to it, the association can fail silently. Build in a delay or use a write-then-verify pattern.
What Breaks: Inline Images, Attachments, and Threaded Replies
The data-mapping table tells you where things go. This section covers what goes wrong when you actually try to move them.
Inline Images
Freshdesk conversation bodies frequently contain inline images — screenshots pasted into replies, embedded logos in signatures. These images are hosted on Freshdesk's CDN (typically *.freshdesk.com URLs embedded in the HTML body).
Standard migrations simply copy the HTML body and paste it into HubSpot. As long as your Freshdesk account is active, the images render fine. The moment you decommission Freshdesk, those CDN URLs die. Every inline image in every migrated conversation becomes a broken link — permanently destroying the visual context of the support request.
The fix: During migration, parse each conversation body for <img> tags with Freshdesk-hosted src attributes. Download each image, upload it to HubSpot's File Manager via /files/v3/files, and rewrite the src URL in the HTML body to point to the new HubSpot-hosted URL before creating the note engagement. This is tedious, slow (one API call per image upload), and most automated tools skip it entirely.
Attachments
Multiple files cannot be uploaded with a single request. Each attachment requires its own upload call. For a migration with 100,000 attachments, that alone is 100,000 API calls — at 190 requests per 10 seconds, roughly 1.5 hours of sustained calls just for file uploads, assuming zero retries.
File size limits depend on where the file lives in HubSpot:
- File Manager: Up to 2 GB on paid plans, up to 20 MB on free tools. (knowledge.hubspot.com)
- Customer portal attachments: Capped at 50 MB.
- Conversations inbox / one-to-one email: Capped at 20 MB.
Files up to 20 MB for accounts with only access to HubSpot's free tools. Files up to 2 GB for accounts with paid subscriptions.
An attachment may migrate successfully into HubSpot's File Manager and still not behave the way agents expect when they later expose it through a portal or resend it through email. Freshdesk's own conversation attachment model caps the total size of a ticket's attachments at 20 MB, so some source accounts are already constrained before migration begins.
Each HubSpot record can have up to 10,000 engagements of any kind. Attachments, notes, meetings, and call notes are all types of engagements. For most accounts this is not a practical limit, but if you have tickets with hundreds of notes plus attachments, it is worth checking.
The safest pattern for attachments: upload first, create note second, associate note to ticket third. Store both source attachment IDs and target file IDs in your crosswalk table for replay or rollback.
Threaded Replies and Conversation Order
Freshdesk conversations are naturally threaded — a ticket has a description, followed by replies in chronological order, with private notes interspersed. In HubSpot, each of these becomes a separate note engagement on the ticket timeline.
Timeline ordering in HubSpot is controlled by the hs_timestamp property on each engagement. The API insists on an ISO formatted date string — and it can take a while to get that right for imported data. If your script uses the import time instead of the original Freshdesk timestamp, conversations appear out of order on the ticket timeline — or worse, every message shows the same date.
You must also map Freshdesk Agent IDs to HubSpot Owner IDs so that historical replies show the correct author. Without this, HubSpot stamps every imported message with the API user (e.g., "Super Admin"), destroying your audit trail.
Best practice: Extract created_at from each Freshdesk conversation, convert to ISO 8601, and set it as hs_timestamp on the corresponding HubSpot note. Map agent IDs to owner IDs so historical replies look as if they were typed natively in HubSpot.
Long Ticket Descriptions
Freshdesk allows ticket descriptions and notes over 65,000 characters. HubSpot, however, has a hard limit. Without proper handling, long messages may get cut off or fail to transfer completely.
If your Freshdesk instance contains tickets with very long description bodies (common in technical support or legal contexts), your migration script must detect oversized bodies and split them into multiple linked notes to avoid silent truncation.
What Can Be Migrated and What Cannot
Not everything in Freshdesk has a home in HubSpot Service Hub.
Fully Migratable
- Tickets with all standard fields (subject, description, status, priority, type)
- Contacts and Companies including custom fields
- Conversations (replies, forwards, public notes, private notes) — as engagement objects
- Attachments — re-hosted in HubSpot's File Manager
- Agent assignments — mapped to HubSpot owners
- Tags — as custom multi-select properties
- Custom fields — as custom ticket/contact/company properties
- Satisfaction ratings — as custom properties
Requires Workarounds
- Inline images — must be re-hosted (see above)
- Time tracking entries — no native equivalent; store as custom properties or notes
- Ticket watchers/CCs — HubSpot has no watcher concept; log as a note or custom field
- Forum topics — HubSpot has no forum; migrate to Knowledge Base articles if applicable
- Knowledge base articles — HubSpot supports import from Freshdesk via Smart Copy or CSV, but each import is capped at 400 articles and tables are not supported. Plan this as a staged project with post-import QA, not as an afterthought. (knowledge.hubspot.com)
Cannot Be Migrated — Rebuild Instead
- Automations, Dispatch Rules, SLA policies — these are configuration, not data. Rebuild in HubSpot workflows. HubSpot Smart Transfer itself creates HubSpot workflows to manage differences between source and target data models, which signals that platform behavior is translated, not copied.
- Canned responses / Macros — rebuild as HubSpot snippets or templates.
- Freddy AI models — no equivalent. HubSpot has its own AI stack.
- Freshdesk Marketplace app configurations — not transferable.
For a deeper dive into why macros and automations need to be rebuilt rather than migrated, see Your Helpdesk Migration's Secret Saboteur: Automations, Macros, and Workflows.
Evaluating Your Migration Options
There are four realistic paths. Each has clear trade-offs.
1. CSV Export + HubSpot Import
Export tickets, contacts, and companies from Freshdesk as CSV files. Import into HubSpot using the native CSV import tool.
Pros: Zero API cost. Simple for small datasets. HubSpot's import tool supports files up to 512 MB, up to 1,048,576 rows per file, and up to 10,000,000 rows per day through the UI. (knowledge.hubspot.com)
Cons: CSV exports from Freshdesk flatten conversations — you lose threaded replies, notes, and attachments entirely. HubSpot's CSV import does not support creating engagements (notes) associated to tickets. You get ticket shells with no history.
Verdict: Only suitable if you have fewer than ~500 tickets and don't care about conversation history. For the full breakdown of CSV limitations, see Using CSVs for SaaS Data Migrations: Pros and Cons.
2. Self-Serve SaaS Tools (Help Desk Migration, MigrateMyCRM)
Help Desk Migration (Relokia) offers a visual mapping interface for Freshdesk-to-HubSpot migrations. The Migration Wizard migrates tickets and all connected records, preserving the data structure on the target. They support delta migration for importing updated records after the initial batch. Help Desk Migration also positions an option to move inline images as attachments.
MigrateMyCRM by SyncMatters provides tiered options from a DIY automated platform to expert-guided migrations.
Pros: Pre-built connectors for both platforms. Visual mapping UI reduces setup time. Delta migration for catching recent changes.
Cons: Limited control over edge cases (inline image re-hosting, long-body splitting, custom association logic). Pricing is volume-based and can escalate quickly for large datasets. If you need custom transformation logic (e.g., merging Freshdesk groups into a single HubSpot pipeline with custom routing), you will hit the tool's limits. Generic adapters tend to normalize data to the common denominator of both APIs — which is exactly where conversation fidelity gets lost.
Verdict: A reasonable middle-ground for mid-sized teams (5,000–50,000 tickets) with standard data structures and moderate customization needs.
3. In-House DIY Scripts
Your engineering team writes Python or Node.js scripts that call the Freshdesk v2 API to extract data and the HubSpot CRM v3 API to write it.
Pros: Full control over every transformation. No per-record pricing.
Cons: You must build and maintain rate-limit handling (exponential backoff with jitter for both APIs), pagination logic that handles the 30,000-ticket ceiling, inline image re-hosting, attachment upload workflows, association management, idempotency for reruns, error logging, and a delta sync mechanism for cutover.
The rate-limit math alone is revealing: at 400 Freshdesk API calls/min (Pro plan) and 190 HubSpot calls/10s, extracting and writing 50,000 tickets with an average of 4 conversations and 1 attachment each requires roughly 500,000+ API calls on each side. That is multiple days of sustained processing.
What looks like a two-week project often turns into a two-month debugging effort. Most teams underestimate edge-case handling by 3–5x.
Verdict: Viable if you have an available engineer with API migration experience and a tolerance for 4–8 weeks of development and debugging.
4. Engineer-Led Migration Service (ClonePartner)
We handle the full pipeline: extraction from Freshdesk, transformation (field mapping, inline image re-hosting, body splitting, deduplication), and loading into HubSpot — with built-in rate-limit management, retry logic, and verification on both sides.
We have pre-built handling for every edge case in this guide: the Freshdesk pagination ceiling, the HubSpot search API bottleneck, inline image re-hosting, attachment upload sequencing, and timestamp-accurate conversation ordering.
Our delta sync approach lets your support team keep working in Freshdesk until the exact moment of cutover. We run the initial bulk migration, then execute a delta pass that picks up every ticket created or updated since the first pass began — so nothing falls through the gap.
Verdict: Best fit when you need guaranteed data integrity, zero downtime, and a fixed timeline — without pulling your own engineers off product work.
The Cutover Strategy: Achieving Zero Downtime
The biggest operational risk in any migration is the gap between "last record exported from source" and "first ticket handled in target." During that gap, new tickets arrive in Freshdesk. If you don't account for them, they are lost.
1. Freeze configuration, not operations. Stop schema changes in Freshdesk first: no new custom fields, no workflow edits, no channel reshuffling. Your team keeps handling tickets normally.
2. Bulk migration (T–7 to T–3 days before cutover) Migrate all historical data: contacts, companies, tickets, conversations, attachments. This is the heaviest phase and runs in the background. Move closed tickets and older attachments before the volatile open-ticket set.
3. Pre-cutover QA (T–2 to T–1) Validate a statistical sample in HubSpot. Check conversation ordering, attachment integrity, custom field values, and contact/company associations. Use the Post-Migration QA Checklist to structure this.
4. Delta sync (T–0, cutover day) Re-export all tickets created or updated since the bulk migration started. Push only the delta into HubSpot. This pass is fast — typically minutes to a few hours depending on volume.
5. DNS and routing switch Point incoming email channels, chat widgets, and form submissions to HubSpot. Deactivate Freshdesk's inbound channels. Your agents start working in HubSpot immediately.
6. Post-cutover monitoring (T+1 to T+3) Monitor for orphaned records, missing associations, or broken attachments. Run a final delta pass if needed.
The most common cutover mistake is treating open tickets and historical tickets the same. They are not. Open tickets need operational continuity — they are actively being worked. Historical tickets need fidelity and searchability. Separate those goals and the migration gets simpler.
The delta sync is the key to zero downtime. Without it, you are forced to either freeze ticket creation in Freshdesk (disrupting your customers) or accept data loss. There is no third option.
How This Migration Typically Goes Wrong
After hundreds of helpdesk migrations, the same failure patterns repeat:
Testing on a trial account. Freshdesk trial accounts are hard-capped at 50 API calls/minute. Your script will appear broken when it's actually just throttled. Always test against your production-tier plan with a controlled subset.
Ignoring inline images. The migration "works" — until someone opens a 2-year-old ticket and sees nothing but broken image icons. By that point, Freshdesk is decommissioned and the CDN URLs are permanently dead.
Flat CSV export. The team exports tickets as CSV, imports into HubSpot, and declares success. Three weeks later, an agent can't find the email thread for an escalated ticket because conversations were never imported.
Rate-limit storms. A DIY script with naive retry logic (retry immediately on 429) burns through the daily quota and stalls for 24 hours. HubSpot's daily quota resets at midnight UTC. If you exhaust it at 2 PM, your migration is frozen until midnight.
Skipping the association step. Notes are created, files are uploaded, but neither is associated to the correct ticket. The data exists in HubSpot but is invisible on the ticket timeline. The note has been created with association to ticket, but when checking the ticket in HubSpot UI, no note or file is attached. This is one of the most common HubSpot API gotchas.
Treating open and historical tickets the same. Open tickets need operational continuity. Historical tickets need fidelity and searchability. Conflating the two leads to a migration plan that does neither well.
Making the Right Choice
The right migration method depends on three variables: volume (how many tickets), complexity (how many custom fields, inline images, and attachments), and risk tolerance (can you afford to lose historical context).
| Scenario | Recommended Approach |
|---|---|
| < 500 tickets, no conversation history needed | CSV export |
| 1,000–50,000 tickets, standard fields | SaaS tool (Help Desk Migration / MigrateMyCRM) |
| 50,000+ tickets, inline images, custom fields | Engineer-led service |
| Regulated industry, audit trail required | Engineer-led service with verification |
| Engineering team available, 6+ weeks runway | DIY scripts |
No matter which path you choose, do not skip the pre-migration audit. Delete obsolete data in Freshdesk first — inactive agents, test tickets, deprecated custom fields. Every unnecessary record you migrate is a record you'll have to clean up later in HubSpot.
For a pre-migration readiness framework, see our Helpdesk Migration Checklist.
Use the simplest method that meets your fidelity requirement. But define that requirement before anyone connects APIs.
Frequently Asked Questions
- Does the native HubSpot Freshdesk integration migrate all historical tickets?
- No. The Freshdesk Data Sync integration only syncs tickets created within the last 120 days. HubSpot's Smart Transfer supports contacts, companies, tickets, and one-time attachment transfer for Freshdesk, but does not explicitly list ticket conversations or comments. Older tickets, full conversation threads, and private notes require a custom API-based migration.
- What are the Freshdesk API rate limits for migration?
- Freshdesk enforces per-minute rate limits by plan: Growth (200/min), Pro (400/min), Enterprise (700/min). Trial accounts are capped at 50/min. These limits are account-wide and shared across all apps and scripts. Endpoint-level sublimits (e.g., Tickets List at 20/min on Growth) are often the real bottleneck. The List Tickets endpoint has a hard pagination ceiling of 30,000 tickets (300 pages × 100 per page).
- How do Freshdesk conversations map to HubSpot?
- Each Freshdesk conversation (reply, note, forward) becomes a separate note engagement in HubSpot, associated to the ticket via the CRM associations API. Attachments must be uploaded to HubSpot's File Manager first, then linked to the note via the hs_attachment_ids property. Original timestamps must be preserved using hs_timestamp to maintain correct timeline ordering.
- How do I prevent broken inline images when moving to HubSpot?
- Parse the HTML body of every Freshdesk conversation, identify img tags with Freshdesk-hosted src attributes, download each image, upload it to HubSpot's File Manager, and rewrite the src URL to point to the new HubSpot-hosted location before creating the note engagement. If you skip this step and later decommission Freshdesk, all inline images become permanently broken.
- Can I use CSV to migrate Freshdesk tickets to HubSpot?
- Only for very small, simple datasets. CSV exports from Freshdesk flatten conversations — you lose threaded replies, private notes, inline images, and attachments entirely. HubSpot's CSV import does not support creating note engagements on tickets. CSV is viable for fewer than ~500 tickets where conversation history is not important.
