Kustomer to HubSpot Service Hub Migration: CTO Guide
How to migrate Kustomer to HubSpot Service Hub: object mapping, API rate limits, KObject translation, and step-by-step architecture. CTO-level guide.
Planning a migration?
Get a free 30-min call with our engineers. We'll review your setup and map out a custom migration plan — no obligation.
Schedule a free call- 1,500+ migrations completed
- Zero downtime guaranteed
- Transparent, fixed pricing
- Project success responsibility
- Post-migration support included
Kustomer to HubSpot Service Hub Migration: CTO Guide
TL;DR — Kustomer to HubSpot Service Hub Migration
A Kustomer to HubSpot Service Hub migration is a medium-to-high complexity data-model translation project. Kustomer's customer-centric timeline architecture — where Conversations, Messages, Notes, and KObjects all hang off a single Customer record — does not map 1:1 to HubSpot's relational ticket-to-engagement model. The realistic timeline is 2–4 weeks for under 100K conversations, 4–6 weeks for larger datasets with complex KObject schemas. The single biggest risk is losing full conversation transcript history: Kustomer CSV exports only include message previews, not full message bodies, so you must extract via the REST API. KObjects require HubSpot Enterprise (the only tier supporting Custom Objects), and Kustomer's Business Rules, Workflows, and Saved Searches cannot be exported — they must be rebuilt manually in HubSpot. HubSpot's native Kustomer Data Sync app syncs customers, not tickets, so it is not a migration tool. (ecosystem.hubspot.com) Teams with fewer than 10,000 conversations and no KObjects can self-serve with API scripts. Anything above that — especially with attachments, KObjects, and multi-threaded conversation history — benefits from a managed migration service.
What Is a Kustomer to HubSpot Service Hub Migration?
A Kustomer to HubSpot Service Hub migration is the process of extracting Customers, Companies, Conversations, Messages, Notes, KObjects, Tags, Users, Teams, and Knowledge Base articles from Kustomer and loading them into HubSpot as Contacts, Companies, Tickets, Engagements (emails and notes), Custom Objects, Tags, Owners, Teams, and Knowledge Base articles.
Strategic context: why teams are leaving Kustomer
Kustomer was acquired by Meta in 2023 and subsequently divested. The platform's roadmap uncertainty, combined with its quote-based annual pricing with an 8-seat minimum, has driven many mid-market and enterprise teams to consolidate onto HubSpot. Common motivations include:
- Go-to-market unification. When sales, marketing, and support all operate within HubSpot, teams eliminate data silos and reduce iPaaS licensing costs. Organizations running Kustomer alongside HubSpot CRM typically spend $5,000–$15,000/year on integration middleware (Zapier, Make, Workato) that becomes unnecessary after consolidation.
- Predictable pricing. HubSpot's published tiered pricing (Service Hub Professional starts at $100/seat/month, Enterprise at $150/seat/month as of early 2025) replaces Kustomer's opaque, negotiated contracts. For a 20-agent team, HubSpot Service Hub Professional runs approximately $24,000/year versus Kustomer's typical $30,000–$60,000/year range depending on negotiated rates.
- Ecosystem breadth. HubSpot's App Marketplace offers 1,700+ integrations compared to Kustomer's smaller third-party ecosystem.
What makes this migration non-trivial
The main mismatch is structural, not clerical. You are translating one help desk model into another, not renaming fields. (help.kustomer.com)
- Data model mismatch. A Kustomer Conversation is the operational unit of work, centered on a continuous customer timeline. HubSpot is object-relational: Tickets, Contacts, Companies, and Engagements are separate objects linked by associations. (developers.hubspot.com)
- KObject dependency. Kustomer organizations routinely store orders, subscriptions, and claims as KObjects. HubSpot Custom Objects require an Enterprise subscription and have a cap of 10 definitions per portal.
- No bulk export for full transcripts. Kustomer's native exports give you message previews only. Full message bodies require per-conversation API calls.
- No native migration tool. HubSpot's Kustomer Data Sync marketplace app syncs customer profiles, not tickets — its listing explicitly scopes the integration to customer data. (ecosystem.hubspot.com)
How Does Kustomer's Data Model Map to HubSpot Service Hub?
Use one HubSpot ticket per Kustomer conversation, then associate the history and context to that ticket. The mapping below preserves the most operational value without pretending the platforms are identical.
Important: HubSpot has been transitioning from its legacy Conversations Inbox to the newer Help Desk workspace (GA as of 2024). This migration guide targets the Help Desk workspace model, where tickets are the primary operational unit and conversations are threaded under tickets. If your HubSpot portal still uses the legacy Conversations Inbox, confirm which model you're targeting before schema setup.
| Kustomer Object | HubSpot Object | Notes / Caveats |
|---|---|---|
| Customer | Contact | Kustomer stores multiple emails/phones as JSON arrays; HubSpot uses a single primary email plus hs_additional_emails (semicolon-separated). Kustomer allows multiple customers with the same email if external IDs differ — HubSpot deduplicates by email, so you must merge before import. |
| Company | Company | HubSpot deduplicates by Company Domain Name. Association to Contacts must be rebuilt via the Associations API. |
| Conversation | Ticket | One ticket per conversation. Kustomer's status (open, snoozed, done) maps to HubSpot Ticket Pipeline stages. Conversation history lives in associated engagements. |
| Message (email) | Email Engagement | Map to POST /crm/v3/objects/emails with hs_email_direction, hs_email_text, hs_timestamp. |
| Message (chat/SMS/social) | Note Engagement | Default to notes unless you build a custom channel integration via HubSpot's custom channels API (/conversations/v3/custom-channels/{channelId}/messages). |
| Note (internal) | Note Engagement | Map to POST /crm/v3/objects/notes with hs_note_body (max 65,536 characters). |
| KObject (e.g., Order, Subscription) | Custom Object | Requires HubSpot Enterprise. Max 10 Custom Object definitions, 500K records each. If you're on Professional, flatten KObject data into custom properties on Contact or Ticket records. |
| Tag | Tag / Multi-select property | Tags flatten into a semicolon-delimited string or custom ticket properties. No global Kustomer-style tag model in HubSpot. |
| User (agent) | Owner | Users must be provisioned in HubSpot before the migration. Map Kustomer agent IDs to HubSpot Owner IDs for correct ticket assignment. |
| Team | Team | HubSpot Teams are configured in Settings; agents are assigned to teams via owner records. |
| Knowledge Base Article | Knowledge Base Article | HubSpot supports KB imports from CSV plus Freshdesk, Help Scout, Zendesk, and Intercom, with a limit of 400 articles per import. We did not find an officially documented public CRUD API for programmatic KB article creation. (knowledge.hubspot.com) |
| Business Rule / Workflow | Workflow | Cannot be exported from Kustomer. Must be rebuilt manually in HubSpot Workflows. |
| Saved Search | Active List / View | Cannot be exported from Kustomer. |
| Webhook configurations | Workflow + Custom Code / Operations Hub | Kustomer webhook endpoints and event subscriptions cannot be exported. Document each webhook's trigger, payload, and destination, then rebuild using HubSpot Workflows with webhook actions or Operations Hub custom code actions. |
Store every Kustomer record ID in a custom unique property on the HubSpot side (e.g., source_kustomer_customer_id). This lets you upsert, rerun, and reconcile without duplicate creation.
Field-level mapping: what transforms are needed
- Picklist / enum values. Kustomer uses free-text or custom attribute enums. HubSpot requires internal values to be pre-defined in property settings before import. Export all Kustomer enum values, create matching HubSpot dropdown options first, then map on import. (knowledge.hubspot.com)
- Date fields. Kustomer stores timestamps in ISO 8601 format. HubSpot's API accepts Unix timestamps in milliseconds for date properties. Every date field needs conversion.
- Multi-value fields. Kustomer Customer emails and phones are JSON arrays. HubSpot Contacts have a single
emailproperty plushs_additional_emails(semicolon-separated). - Conversation status → Pipeline stage. Kustomer statuses (
open,snoozed,done) must map to HubSpot ticket pipeline stage IDs. Retrieve your pipeline stages first viaGET /crm/v3/pipelines/ticketsand build a lookup table. - Note body length. HubSpot note engagements are capped at 65,536 characters. Long Kustomer notes must be split into sequential notes with preserved timestamp ordering.
- Multi-select tree fields. Kustomer's multi-select tree fields must be flattened into HubSpot dropdown select properties.
What has no clean equivalent in HubSpot
- Kustomer's unified timeline. In Kustomer, every event (messages, KObjects, notes, system events) appears on one chronological timeline per customer. HubSpot splits this across ticket timelines, contact activity, and separate engagement records.
- Kustomer Events / Audit Logs. System-level events (assignment changes, status transitions) have no bulk export path and no direct HubSpot equivalent. Flatten these into note engagements or discard after review.
- Callable Workflows. Kustomer's workflow automation that connects to external APIs must be redesigned using HubSpot Workflows with Custom Code actions or Operations Hub.
- Snippets and Shortcuts. These have no export path from Kustomer. Rebuild as HubSpot Snippets manually.
- Permission model granularity. Kustomer's role-based access control allows fine-grained permissions at the object and field level. HubSpot's permission model is coarser — roles control feature access (e.g., "edit contacts") rather than field-level visibility. If your Kustomer setup uses restricted field access for compliance (e.g., PII masking for certain agent roles), you'll need to evaluate HubSpot's field-level permissions (available on Enterprise) and potentially restructure your access control model.
Reporting migration
Kustomer dashboards, saved reports, and custom analytics do not export. Before decommissioning Kustomer:
- Export historical report data as CSVs for baseline comparison.
- Document every Kustomer report's filters, groupings, and metrics. Kustomer reports built on conversation attributes translate to HubSpot custom reports using ticket properties. KObject-based reports require Custom Object reporting (Enterprise only).
- Rebuild in HubSpot Custom Report Builder. HubSpot supports single-object and cross-object reports. Key metric mappings: Kustomer's "First Response Time" → HubSpot's
hs_time_to_first_response; Kustomer's "Resolution Time" → HubSpot'shs_resolution_time(available in Help Desk). CSAT in HubSpot uses native feedback surveys, not imported satisfaction ratings — store Kustomer CSAT scores as custom ticket properties for historical reference. - Budget 2–5 days for reporting rebuild depending on dashboard complexity.
Why Do Kustomer CSV Exports Fail for Conversation History?
The most common mistake engineering teams make is assuming they can rely on native CSV exports for ticket history.
Kustomer's native CSV exports include conversation-level attributes and message previews only — not full message bodies. The Reporting Export is limited to a 30-day window and caps at 25 attributes. Saved Search exports bypass the date limit but cap at 50,000 rows and still exclude full message content. Standard search and export paths also omit records updated more than two years ago unless you use Archive Search or the API. (help.kustomer.com)
To extract full conversation transcripts, you must use the Kustomer REST API. The relevant endpoints:
GET /v1/conversations/{conversationId}/messages— returns the complete message body, sender, channel, timestamps, and attachments for each messageGET /v1/conversations/{conversationId}/notes— captures internal notesPOST /v1/customers/searchwithqueryContext: "conversation"— paginates through conversationsPOST /v1/customers/archive/search— for history beyond the two-year Search API window
There is no bulk endpoint that returns all messages across all conversations in a single call. You must iterate conversation by conversation.
Kustomer API authentication setup
Before extraction, create a dedicated API key in Kustomer:
- Navigate to Settings → API Keys in Kustomer admin.
- Create a new key with
org.admin.reador scoped read permissions for customers, conversations, messages, and KObjects. - Store the key in a secrets manager (AWS Secrets Manager, HashiCorp Vault) — not in source code.
- API keys inherit the organization's rate limit ceiling. If you have multiple integration keys active, they all share the same RPM pool.
- For EU-hosted Kustomer instances, the base URL is
https://api.prod2.kustomerapp.com/v1instead ofhttps://api.kustomerapp.com/v1.
POST /v1/customers/search
{
"queryContext": "conversation",
"and": [
{ "conversation_created_at": { "gte": "2024-03-01T00:00:00.000Z" } },
{ "conversation_created_at": { "lte": "2024-03-31T23:59:59.999Z" } }
],
"timeZone": "GMT"
}Kustomer explicitly notes there is no supported /v1/conversations/search endpoint. At 100 records per page and a max of 100 pages per search query, each query window returns at most 10,000 conversations. For larger datasets, use cursor-based pagination by sorting on updated_at and using the last value as the starting filter for the next batch. (help.kustomer.com)
Bottom line: Native CSVs are only viable for basic Contact and Company lists. For a complete helpdesk migration, you must use an API-based approach. For a deeper source-side checklist, see How to Export Data from Kustomer.
How Do API Rate Limits Affect a Kustomer to HubSpot Migration?
Rate limits decide the architecture. You need to plan extraction and loading independently — a single global queue usually wastes capacity on one side or the other.
Kustomer extraction limits
Kustomer enforces organization-wide API rate limits that vary by plan:
| Kustomer Plan | Rate Limit (RPM) |
|---|---|
| Legacy Professional | 300 |
| Legacy Business | 500 |
| Enterprise | 1,000 |
| Ultimate | 2,000 |
All API keys in the organization share this ceiling. Searches have a separate 100 RPM machine-user limit. Object-specific limits also apply: a single conversation, company, or message can be updated 50 times in a 10-minute interval. Exceeding limits returns HTTP 429 with x-ratelimit-reset headers. (help.kustomer.com)
Throughput math (Enterprise tier at 1,000 RPM): If you have 50,000 conversations and average 8 messages per conversation, you need ~50,000 message-list calls + ~50,000 note-list calls + ~500 pagination calls for the conversation index ≈ 100,500 API calls. At 1,000 RPM with headroom for retries, that's roughly 2 hours of extraction time.
HubSpot load limits
HubSpot's API rate limits depend on your app type and subscription:
| HubSpot Configuration | Burst Limit (per 10 sec) | Daily Limit |
|---|---|---|
| Private app — Free/Starter | 100 requests | — |
| Private app — Professional | 190 requests | 650,000 |
| Private app — Enterprise | 190 requests | 1,000,000 |
| Public app (OAuth) | 110 requests | Varies |
| CRM Search API | 5 requests/sec | — |
Batch endpoints are essential. POST /crm/v3/objects/tickets/batch/create accepts up to 100 records per call and counts as a single request against burst limits. At 190 requests per 10 seconds using batch endpoints, you can theoretically create ~19,000 tickets per 10-second window — though based on our migration experience, real-world throughput drops to 40,000–60,000 records per minute once you factor in associations, error handling, and retry logic.
For the initial bulk load, consider HubSpot's Imports API, which supports files up to 1,048,576 rows or 512 MB and up to 80,000,000 rows per day. This is significantly faster than direct object API calls for historical data. Reserve the batch object endpoints for delta syncs and repair work. (developers.hubspot.com)
The CRM Search API is your bottleneck, not the batch create endpoint. If you deduplicate contacts or tickets during import by searching HubSpot first, the 5 requests/second limit across all search endpoints becomes the primary constraint. Build your deduplication logic in your staging layer, not inside the HubSpot API call chain.
Handling 429 errors
Both platforms return HTTP 429 when limits are exceeded. Your migration script must implement exponential backoff with jitter — not a fixed sleep() interval. Read x-ratelimit-remaining (Kustomer) and X-HubSpot-RateLimit-Secondly-Remaining (HubSpot) response headers to throttle proactively rather than reactively.
for (const job of queue) {
try {
await run(job)
} catch (e) {
if (e.status === 429) await sleep(withJitter(backoff(e)))
else if (e.status >= 500) retry(job)
else deadLetter(job, e)
}
}Standard iPaaS tools (Zapier, Make) often fail at bulk historical migrations because they lack the queueing and throttling logic shown above. For more on handling failures mid-migration, see our Help Desk Data Migration Failed? The Engineer's Rescue Guide.
What Data Cannot Be Migrated from Kustomer to HubSpot Service Hub?
Some gaps are structural and should be called out early.
| Data Type | Can It Be Migrated? | Detail |
|---|---|---|
| Full message transcripts | Yes, via API only | CSV exports truncate to previews |
| Attachments & inline images | Yes, with extra work | Download from Kustomer, re-upload to HubSpot Files API, link to engagements |
| Knowledge Base articles | Partially | HubSpot supports CSV import and vendor imports (Freshdesk, Help Scout, Zendesk, Intercom), 400 articles per import, no table support. No documented public CRUD API. |
| Business Rules | No | Exist only in Kustomer; must be rebuilt as HubSpot Workflows |
| Workflows | No | Cannot be exported; rebuild in HubSpot |
| Saved Searches | No | Rebuild as HubSpot active lists or saved views |
| Conversation satisfaction ratings | Partially | Map to custom ticket properties; native CSAT on HubSpot uses feedback surveys — different mechanism |
| KObjects (orders, subscriptions) | Yes, with Enterprise | Requires HubSpot Enterprise plan for Custom Objects |
| Agent availability / routing rules | No | Rebuild in HubSpot's routing and assignment settings |
| Snippets / Shortcuts | No | No export path; rebuild as HubSpot Snippets |
| Attachment creation timestamps | No | HubSpot files use HubSpot-side createdAt; original upload times are not preserved |
| Custom Klass schema definitions | No | Not exportable from Kustomer |
| Webhook configurations | No | Document and rebuild as HubSpot Workflows with webhook actions |
| Kustomer dashboards/reports | No | Export historical data as CSVs; rebuild in HubSpot Custom Report Builder |
| Permission/role configurations | No | HubSpot uses a different permission model; must be redesigned |
Knowledge Base migration deserves separate planning. For most teams, KB migration is a 2–5 day manual effort depending on article count. HubSpot's CSV import path supports up to 400 articles per import with no table import support. If your Kustomer KB has 200+ articles, budget the time explicitly. Kustomer can expose KB content through its API, which at least lets you automate the extraction side. (help.kustomer.com)
Step-by-Step Migration Architecture
A successful migration follows a strict order of operations. Reversing these steps results in orphaned records and broken associations.
Phase 1: Extract from Kustomer
import requests
import time
KUSTOMER_API = "https://api.kustomerapp.com/v1"
HEADERS = {"Authorization": "Bearer YOUR_API_KEY"} # Store in secrets manager
def extract_conversations(updated_since="2020-01-01T00:00:00Z"):
all_conversations = []
while True:
resp = requests.post(f"{KUSTOMER_API}/customers/search",
headers=HEADERS,
json={
"queryContext": "conversation",
"and": [{"updated_at": {"gte": updated_since}}],
"sort": [{"updated_at": "asc"}],
"page": {"size": 100}
})
if resp.status_code == 429:
reset = int(resp.headers.get("x-ratelimit-reset", 60))
time.sleep(reset)
continue
data = resp.json()
conversations = data.get("data", [])
if not conversations:
break
all_conversations.extend(conversations)
updated_since = conversations[-1]["attributes"]["updatedAt"]
return all_conversations
def extract_messages(conversation_id):
resp = requests.get(
f"{KUSTOMER_API}/conversations/{conversation_id}/messages",
headers=HEADERS)
return resp.json().get("data", [])Store extracted data in a secure staging database (PostgreSQL or a structured JSON data lake). Do not stream directly from Kustomer to HubSpot — you need the intermediate layer for transforms, deduplication, and reruns. For datasets with history older than two years, supplement with POST /v1/customers/archive/search to capture records the standard Search API omits.
Phase 2: Transform
- Convert Kustomer
Customer→ HubSpotContact(flatten email arrays, convert dates to Unix ms) - Map conversation status → HubSpot pipeline stage ID (retrieve stage IDs via
GET /crm/v3/pipelines/tickets) - Map KObject attributes → HubSpot Custom Object properties (create schema first via
POST /crm/v3/schemas) - Split note bodies exceeding 65,536 characters into sequential notes with preserved timestamps
- Download all attachments and stage in cloud storage (S3/GCS)
- Deduplicate contacts by email in the staging layer — not in HubSpot
- Parse inline image
srctags in HTML message bodies and prepare for re-upload - Build Kustomer-to-HubSpot ID lookup tables for all objects to enable correct associations in Phase 3
Phase 3: Load into HubSpot
Order of operations matters. Load in this sequence to prevent broken associations:
- Provision Users and Teams — Create all active and inactive agents in HubSpot to generate Owner IDs needed for ticket assignment
- Companies →
POST /crm/v3/objects/companies/batch/create - Contacts →
POST /crm/v3/objects/contacts/batch/create - Contact-to-Company associations →
POST /crm/v4/associations/contacts/companies/batch/create - Custom Object schemas (if KObjects exist) →
POST /crm/v3/schemas - Custom Object records →
POST /crm/v3/objects/{objectType}/batch/create - Tickets →
POST /crm/v3/objects/tickets/batch/create - Ticket-to-Contact associations →
POST /crm/v4/associations/tickets/contacts/batch/create - Engagements (emails, notes) →
POST /crm/v3/objects/emailsandPOST /crm/v3/objects/notes - Engagement-to-Ticket associations → link each engagement to its parent ticket
- Attachments → Upload via Files API, then associate with engagements using
hs_attachment_ids
Preserve historical timestamps. When creating email engagements, set hs_timestamp to the original Kustomer message createdAt value (converted to Unix ms). Without this, all migrated conversations appear as if they happened on the import date, destroying timeline chronology. The same applies to tickets — pass the original creation date in the API payload, otherwise HubSpot stamps every historical ticket with today's date.
POST /crm/v3/objects/notes
{
"properties": {
"hs_timestamp": "1736693302000",
"hs_note_body": "Migrated from Kustomer. Channel: chat",
"hubspot_owner_id": "14240720",
"hs_attachment_ids": "24332474034"
}
}Handling attachments and inline images
This is the most computationally expensive phase. For every Kustomer message with attachments:
- Download the file from Kustomer's storage
- Upload it to HubSpot using the Files API (accepts files up to 300MB)
- Associate the returned File ID with the Engagement via
hs_attachment_ids
For inline images embedded in HTML message bodies, your script must parse the HTML, identify src tags, download each image, upload to HubSpot's File Manager, and rewrite the src URLs in the HubSpot Engagement payload. Skipping this step leaves broken image references in migrated conversations.
To read certain hidden files or export attachments later from HubSpot, you need the files.ui_hidden.read scope configured on your private app.
How Long Does a Kustomer to HubSpot Service Hub Migration Take?
A standard migration takes 2–4 weeks for organizations with under 100,000 conversations. Larger datasets with complex KObject schemas can extend to 4–6 weeks.
| Phase | Duration | Dependencies |
|---|---|---|
| Discovery & data audit | 2–3 days | Access to Kustomer admin, HubSpot sandbox |
| Schema setup (Custom Objects, properties, pipelines) | 2–3 days | HubSpot Enterprise confirmed (if KObjects exist) |
| Script development & testing | 3–5 days | API keys provisioned, rate limits understood |
| Pilot migration (10% sample) | 1–2 days | Sandbox environment ready |
| UAT & validation | 2–3 days | CS team available to verify conversation history |
| Full migration run | 1–3 days | Depends on volume and API rate limits |
| Delta sync & cutover | 1 day | Kustomer frozen or delta window defined |
| Reporting & workflow rebuild | 2–5 days | Original Kustomer reports/workflows documented |
| Total | 14–25 business days |
HubSpot sandbox limitations to know
HubSpot development sandboxes (available on Professional and Enterprise) have constraints that affect migration testing:
- Sandbox portals have lower API rate limits than production — expect roughly half the throughput.
- Custom Objects created in sandbox do not transfer to production; you must recreate schemas.
- Sandbox data does not persist across portal resets.
- Not all Enterprise features are available in sandbox (e.g., some Operations Hub features).
- Use sandbox for schema validation and workflow testing, not for full-volume load testing. For load testing at scale, request a temporary test portal from HubSpot support.
Phased vs. big-bang cutover
- Big-bang works for organizations under 50K conversations with a clear cutover weekend. Freeze Kustomer Friday evening, run migration Saturday, validate Sunday, go live Monday.
- Phased/incremental is better for 100K+ conversations or teams that can't afford any downtime. Migrate historical data first (conversations older than 90 days), then run a delta sync of recent activity during cutover. The cutover window — when you freeze Kustomer, run the final delta, and switch agents to HubSpot — is typically 2–4 hours during off-peak.
Risk register
| Risk | Likelihood | Mitigation |
|---|---|---|
| 429 throttling extends migration window | Medium | Pre-calculate total API calls; request temporary rate limit increase from Kustomer support |
| KObject schema mismatch breaks import | Medium | Validate Custom Object schema in HubSpot sandbox before production load |
| Duplicate contacts created | High | Deduplicate in staging layer using email as primary key; avoid relying on HubSpot Search API |
| Attachments fail to re-upload | Low | Stage all files in S3/GCS first; retry with exponential backoff |
| Transcript loss from CSV reliance | High | Use API transcript extraction exclusively |
| KObject design drift | High | Freeze the HubSpot custom object model before the first dry run |
| Reporting gap post-cutover | Medium | Export Kustomer report data as CSVs before decommissioning; rebuild critical dashboards in HubSpot during schema setup phase |
For a detailed pre-launch checklist, review our HubSpot Service Hub Migration Checklist.
What Do Customers and Agents Notice During the Migration?
If executed correctly, customers notice nothing. The migration happens behind the scenes while your support team continues working in Kustomer until cutover.
Conversation history and thread continuity
All historical conversations — including full message bodies, internal notes, and timestamps — appear on the correct contact record in HubSpot. Agents can search by customer email and see the complete support history.
Customers care about thread continuity. By mapping Kustomer Messages to HubSpot Email Engagements and preserving the original Message-ID headers, agents can reply to historical threads natively in HubSpot without breaking the customer's email experience. If an ongoing conversation is migrated as a flattened internal note instead of an email engagement, the agent loses the ability to hit "Reply" and continue the email chain.
Historical Kustomer chats and social messages typically appear as note engagements on the HubSpot ticket rather than as native Help Desk threads, unless you build a custom channel path using HubSpot's custom channels API. For most migrations, note engagements are the pragmatic choice.
SLA and ticket continuity
HubSpot SLA clocks start fresh at cutover. If you need historical SLA data for reporting, store Kustomer's resolution times as custom ticket properties during migration. Ensure your HubSpot Workflows are configured to not trigger SLA timers on closed historical tickets — importing thousands of old tickets can fire massive SLA breach alerts in your new system.
Open tickets in Kustomer become open tickets in HubSpot, in the correct pipeline stage. Customers replying to existing threads are routed to the corresponding HubSpot ticket if email forwarding is configured during cutover.
Change management tip: Brief your support team on HubSpot's Help Desk workspace 1–2 weeks before go-live. The interface shifts from Kustomer's timeline-first view to HubSpot's ticket-list-first view. Agents who relied on Kustomer's unified timeline will need time to adjust to navigating between ticket records and associated engagement histories. Budget 2–4 hours of hands-on training per agent, ideally using migrated sandbox data so they can practice with familiar conversations.
Edge Cases and Known Limitations
Do not ignore these common failure modes:
-
Multi-channel conversations. A single Kustomer Conversation can include messages from email, chat, SMS, and social in one thread. HubSpot Tickets don't natively support mixed-channel threads. Each channel's messages become separate email or note engagements on the same ticket — the visual experience differs from Kustomer's unified thread.
-
Inline images. Images embedded directly in the body of a Kustomer email often break during export. Your script must parse the HTML body, identify
srctags, download the images, upload them to HubSpot's File Manager, and rewrite the HTMLsrctags in the HubSpot Engagement payload. -
Duplicate contacts. HubSpot strictly enforces unique email addresses for Contacts. Kustomer allows multiple Customer records with the same email via different channels. Your transform step must merge duplicates before import or HubSpot will reject the second and third profiles. Build deduplication logic in your staging environment.
-
KObject relationships. Kustomer KObjects can link to other KObjects (e.g., an Order links to a Subscription). HubSpot Custom Objects support associations with standard objects and other custom objects, but the association model is simpler — you lose multi-level nesting depth.
-
Attachment size limits. HubSpot's Files API accepts files up to 300MB. Kustomer attachments rarely hit this, but verify before bulk upload.
-
Old data access. Kustomer's standard Search API omits records updated more than two years ago. Use
POST /v1/customers/archive/searchfor historical data beyond this window. (help.kustomer.com) -
EU data residency. Kustomer offers EU hosting (
api.prod2.kustomerapp.com). If your HubSpot portal is in a different region, confirm GDPR data transfer requirements before migrating. Standard Contractual Clauses (SCCs) or an adequacy decision may be required for EU-to-US data transfers. See our GDPR-compliant migration guide for the full framework. -
Merged customers. Kustomer tracks customer merges. Use
GET /v1/customers/{customerId}/mergesduring extraction to verify that merged records resolve correctly in HubSpot's single-email-per-contact model.
How to Validate a Kustomer to HubSpot Migration
Never execute a big-bang cutover without validation. Automated count checks are necessary but not sufficient.
-
Record-count reconciliation. Compare total Customers in Kustomer vs. Contacts in HubSpot. Compare total Conversations vs. Tickets. Counts should match within 0.1% (the delta is usually merge-related). Segment validation windows so HubSpot Search's 10,000-result query cap does not hide discrepancies — use
filterGroupswith date ranges to partition counts. -
Field-level spot checks. Sample 50–100 records across high-value customers. Verify custom field values, tags, assignees, and conversation statuses transferred correctly.
-
Conversation thread integrity. For 20+ sampled tickets, open the HubSpot ticket and verify every message appears in correct chronological order with correct sender attribution. This is the highest-value validation step.
-
KObject verification. If you migrated KObjects to HubSpot Custom Objects, verify associations: does each order/subscription link to the correct contact?
-
Attachment spot check. Open 10 tickets with known attachments. Verify files are accessible and not broken.
-
UAT with agents. Have 2–3 support agents work real tickets in HubSpot sandbox using migrated data. Ask them to confirm the data "feels right" — agents catch data quality issues that automated checks miss.
-
Rollback readiness. Before cutover, confirm you can delete all imported records. HubSpot supports bulk deletion via
POST /crm/v3/objects/{objectType}/batch/archive(up to 100 records per call). For large imports, batch deletion at the API's burst limit (190 requests/10 sec × 100 records/request) takes approximately 1 hour per 100K records. Archived records move to the recycling bin and are permanently deleted after 90 days. A clean rollback means re-running the migration from scratch, not surgically fixing records. Keep a rerunnable delta job so final cutover is a replay, not a one-shot gamble.
For a comprehensive post-migration testing checklist, see our Help Desk Migration QA Checklist.
Migration Approach Comparison
| Approach | How It Works | Best For | Biggest Limitation |
|---|---|---|---|
| CSV export/import | Export from Kustomer UI, import via HubSpot UI | Contact/company metadata only | Loses all conversation history, message bodies, attachments |
| HubSpot Kustomer Data Sync app | Pre-built marketplace connector | Ongoing customer profile sync during coexistence | Syncs customers, not tickets — not a migration tool (ecosystem.hubspot.com) |
| API-based custom scripts | Build ETL using Kustomer REST API + HubSpot CRM API | Full-fidelity migration with engineering capacity | Rate limit management, relationship ordering, retry logic |
| iPaaS (Zapier/Make) | Pre-built connectors for record-level sync | Ongoing sync of new records post-cutover | Not built for historical bulk migration; cannot handle KObject relational mapping |
| Managed migration service | Specialist handles end-to-end ETL with validation | Teams needing zero downtime, full history, and KObjects | Vendor dependency; verify Kustomer + HubSpot experience |
Decision matrix
- < 5K conversations, no KObjects: CSV for contacts/companies + API scripts for conversations. 1 developer, 1–2 weeks. Estimated engineering effort: 40–80 hours.
- 5K–100K conversations, KObjects present: API-based migration. 1–2 developers, 3–4 weeks. Estimated engineering effort: 120–200 hours. Consider managed service if engineering bandwidth is constrained.
- 100K+ conversations, enterprise compliance requirements: Managed migration service. Phased cutover with delta sync. Estimated engineering effort for DIY: 200–400 hours.
Build In-House vs. Use a Managed Service
When in-house makes sense
- Under 10,000 conversations with no KObjects
- You have a developer with 2–3 weeks of available bandwidth
- No attachments or minimal attachment volume
- You're comfortable rebuilding workflows, reports, and KB manually
- No hard cutover deadline
When in-house becomes expensive
The hidden cost of a DIY Kustomer to HubSpot migration is not the initial script — it's the edge cases. Handling 429 retries, splitting multi-channel conversations, deduplicating contacts, managing attachment re-uploads, and validating thread ordering across 50K+ tickets consumes 3–5x the engineering time most teams estimate upfront. Based on our experience across hundreds of helpdesk migrations, a DIY migration typically costs 80–160 hours of engineering time for a mid-size dataset (20K–80K conversations). At a loaded engineering cost of $100–$175/hour, that's $8,000–$28,000 in engineering labor — before accounting for a failed first attempt that requires re-extraction, re-transformation, and re-loading.
Where a managed service fits
A managed migration service handles the full extract-transform-load pipeline, including KObject schema translation, attachment re-upload, conversation threading, and delta sync at cutover. The value is not "doing the import for you" — it is removing the failure modes that surface after the first dry run.
For context on HubSpot Service Hub's architecture compared to alternatives, see our Zendesk vs HubSpot Service Hub Architecture Guide.
Frequently Asked Questions
- Can Kustomer conversation history be preserved in HubSpot Service Hub?
- Yes, but only through API-based extraction. Kustomer CSV exports truncate message bodies to previews. Using the Kustomer REST API endpoint GET /v1/conversations/{id}/messages, you can extract full message bodies, timestamps, and channel data, then load them as email or note engagements in HubSpot with hs_timestamp set to the original creation time. Old omnichannel threads typically land as ticket-linked activities rather than native Help Desk threads.
- Do I need HubSpot Enterprise to migrate from Kustomer?
- You need HubSpot Enterprise only if your Kustomer organization uses KObjects (custom objects like orders, subscriptions, or claims). HubSpot Custom Objects require Enterprise on at least one Hub. If you don't use KObjects, HubSpot Professional is sufficient for Tickets, Contacts, Companies, and engagement history.
- Is the native HubSpot Kustomer integration enough for migration?
- No. HubSpot's marketplace listing for the Kustomer Data Sync app scopes the integration to customer data, not tickets. It is useful for profile sync during coexistence but not for a historical help desk migration with conversations, attachments, and KObjects.
- What data is lost when migrating from Kustomer to HubSpot Service Hub?
- Kustomer Business Rules, Workflows, Saved Searches, Snippets, and Shortcuts cannot be exported and must be rebuilt manually. HubSpot has no officially documented public CRUD API for Knowledge Base articles, so they require CSV import or manual recreation. The underlying support data (conversations, messages, attachments, KObjects) can be preserved via API extraction.
- How long does a Kustomer to HubSpot Service Hub migration take?
- A typical migration takes 2–4 weeks for organizations with under 100,000 conversations, including discovery, script development, pilot migration, validation, and cutover. Larger datasets with complex KObject schemas can extend to 4–6 weeks. The primary time driver is the number of per-conversation API calls required for full transcript extraction.



