Skip to content

Zendesk to Salesforce Service Cloud Migration: Technical Guide

Technical guide to Zendesk to Salesforce Service Cloud migration. Covers data mapping, API limits, what breaks in tools, real costs, and step-by-step execution.

Raaj Raaj · · 24 min read
Zendesk to Salesforce Service Cloud Migration: Technical Guide
TALK TO AN ENGINEER

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

A Zendesk to Salesforce Service Cloud migration is not a ticket export followed by a CSV import. It is a model-translation project. Tickets become Cases, customer users become Contacts, agents become paid Salesforce Users, public replies need to land on a different object than private notes, and attachments and knowledge articles each require their own migration logic. If you want agents to trust historical data on day one, you need separate workstreams for cases, comments, files, knowledge, and workflow rebuilds.

This guide covers the full technical scope: data model mapping, API constraints, what breaks in automated tools, real costs, and the step-by-step execution process. For a deeper look at the business triggers behind this move, read our analysis on why top-performing teams migrate to Salesforce.

Why Teams Migrate from Zendesk to Salesforce Service Cloud

The triggers are predictable. Teams move when they need to unify customer data across sales and support — a single Account record that connects pipeline deals, support cases, and marketing engagement. Zendesk keeps support in its own silo; Salesforce puts it in the same org as Sales Cloud, Marketing Cloud, and every AppExchange integration your GTM team runs. (synebo.io)

Common triggers:

  • Unified customer data. Cases, Accounts, Contacts, Opportunities, and custom objects live in one security and reporting model.
  • Reporting flexibility. Zendesk Explore can't join support data with revenue data. Salesforce Reports and Dashboards can, including joined reports and downstream BI.
  • Multi-department case routing. Salesforce's OmniChannel routing, Entitlement Processes, and queue-based assignment handle complex routing scenarios that Zendesk struggles with at scale.
  • Contract consolidation. Finance wants one vendor, one contract, one renewal cycle.
  • Compliance requirements. Salesforce's field-level security, audit trail, and Shield encryption satisfy enterprise compliance mandates more granularly than Zendesk.

What you lose in the move. Be clear-eyed about this:

  • Agent UX simplicity. Zendesk's Agent Workspace is faster and more intuitive out of the box. Salesforce's Service Console requires heavy customization to achieve similar efficiency.
  • Out-of-the-box macros. Zendesk makes it easy for non-technical managers to build macros. In Salesforce, you must rely on Quick Actions and Flow Builder.
  • Marketplace plug-and-play. Zendesk's app marketplace is highly accessible. Salesforce AppExchange integrations often require an admin to configure.
  • Admin overhead. Zendesk is lighter to tune day-to-day. Salesforce demands more admin investment for equivalent results.

If your current org is small, single-brand, and mostly email-only, Salesforce can be overbuilt for the problem. For a deeper look at Service Cloud's capabilities, see our Salesforce Service Cloud guide.

Zendesk to Salesforce Data Model Mapping

This is the section that determines whether your migration succeeds or fails. Every mapping decision here has downstream consequences for reporting, automation, and agent workflows.

Core Object Mapping

Zendesk Object Salesforce Object Mapping Notes
Tickets Cases Clean 1:1 mapping. Subject, Description, Priority map directly. Status and Priority picklist values must be translated.
Ticket Comments (public replies) EmailMessage Public replies become EmailMessage records linked to the Case. This preserves email thread context and displays correctly in the Case Feed.
Ticket Comments (internal notes) CaseComment Internal notes become CaseComment records. Mixing these up destroys historical accuracy. Salesforce CaseComment has a 4 KB size limit per comment — long Zendesk notes may need splitting or alternate storage.
Users (End Users) Contacts Map Zendesk end_user role to Contacts. Zendesk allows duplicate emails; Salesforce does not by default. Dedup before import.
Users (Agents) Salesforce Users License implications: every agent needs a paid Service Cloud seat. Historical agents who no longer work at the company should not be created as active users — use a fallback strategy.
Organizations Accounts Clean mapping. Organization name → Account name. Custom org fields → custom Account fields.
Tags Custom multi-select picklist Salesforce has native Topic Tags, but they're poorly supported in reports and automations. Most teams use a custom multi-select picklist or a child object for high-cardinality tags.
Ticket Forms Record Types (Case) Each Zendesk ticket form becomes a Record Type on the Case object, controlling page layout and picklist values.
Custom Fields Custom Fields (Case/Contact/Account) Data type mismatches are the #1 silent failure mode. See custom field mapping details below.

Ticket Comments Must Split into EmailMessage and CaseComment

This is the biggest structural mismatch in the project — and where most DIY migrations fail.

Zendesk stores all replies (internal and public) in a single comments array on the ticket. Salesforce uses two different objects:

  • Public repliesEmailMessage records. Salesforce's EmailMessage model carries fields like message date, parent case, direction (incoming/outgoing), HTML body, and text body. This preserves thread readability and email-like history inside the case. (developer.salesforce.com)
  • Internal notesCaseComment records. This object carries the private/public comment behavior Salesforce expects.

If you dump all Zendesk comments into CaseComment, public replies look like internal notes, agents can't distinguish what customers actually saw, and email metadata is lost. If you dump everything into EmailMessage, internal notes lose their private behavior. A split model is the only viable option.

Warning

Historical Accuracy Warning: When creating EmailMessage records, map the original sender's email address and timestamp. Without this, every historical reply will appear as if it was sent by the API integration user on the migration date.

The comment split also applies to attachments: files attached to public comments should link to their EmailMessage record. Files attached to internal notes should link to the CaseComment or directly to the Case.

Users Split into Contacts and Salesforce Users

Zendesk's user model combines end users and agents under a single Users object, differentiated by role. Salesforce separates these completely:

  • End UsersContact records (data records, no license cost)
  • AgentsUser records (paid seats with profile, permission, and sharing implications)

This split creates real problems:

  • License costs. Zendesk agent seats run ~$55–$115/month. Salesforce Service Cloud Enterprise lists at $165/user/month. Every agent needs a full license.
  • Historical agents. Agents who no longer work at the company can't always be recreated as full Salesforce users just to preserve case ownership attribution. Map inactive historical agents to a generic "Former Support Agent" user profile, and store the original agent name or email in a custom Legacy_Assignee__c field for reporting.
  • Duplicate end users. Zendesk allows multiple users with the same email address under specific conditions. Salesforce's standard matching rules will block duplicate contacts during insertion. Dedup in the transform phase using email as the unique key. (support.zendesk.com)
  • Light agents and contributors. Zendesk's light agent role has no direct Salesforce equivalent. These users either need full Service Cloud licenses or should not be migrated as active users.

Custom Fields, Tags, and Ticket Forms

Zendesk custom fields land on custom fields in Case, Contact, or Account. The mapping rules:

  • Zendesk dropdown → Salesforce picklist (values must match exactly)
  • Zendesk multi-select → Salesforce multi-select picklist (semicolon-delimited) or a child object if the value set is large
  • Zendesk regex-validated text → Salesforce text field plus a validation rule (no native regex field type in Salesforce)
  • Zendesk numeric/date fields → native Salesforce numeric/date fields
  • Zendesk ticket form → Case Record Type

Tags are a frequent problem. Salesforce's native tagging model is poorly supported in reports and automations. Most teams use a custom multi-select picklist for a small stable tag set, or a child custom object for high-cardinality or analytics-heavy tags. Help Desk Migration's own Salesforce checklist notes that its standard wizard cannot import ticket tags to Service Cloud — a signal that tag handling is not cleanly native in this path. (help-desk-migration.com)

Macros have no 1:1 migration path. Simple macros (set status, insert text) can be rebuilt as Quick Actions or email templates. Complex macros with conditional logic, multi-field updates, and downstream triggers need Flow Builder. Every macro must be manually rebuilt.

Automation and Workflow Mapping

Zendesk Feature Salesforce Equivalent Notes
Macros Quick Actions + Flows No 1:1 equivalent. Simple macros → Quick Actions. Complex macros → Flow Builder. All must be manually rebuilt.
Triggers & Automations Flow Builder Process Builder is deprecated — do not use it. All trigger-based logic goes in Flow Builder. Time-based automations use Scheduled Flows.
Views List Views + Reports Zendesk views → Salesforce List Views for agent queues, Reports for analytics. Straightforward translation.
SLA Policies Entitlement Processes + Milestones Major complexity increase. Zendesk SLA policies configure in minutes. Salesforce requires Entitlements, Entitlement Processes, and Milestones (first response, resolution time). Default limit: 10 milestones per process, raisable to 50 by support. Once activated, you can't modify milestones without creating a new version. (help.salesforce.com)
Satisfaction Ratings (CSAT) Salesforce Surveys or custom solution Salesforce Surveys requires an additional license. Default orgs get 300 survey responses. Most teams build a custom solution using a post-case-close Flow. (help.salesforce.com)

Knowledge Base Mapping

Zendesk Guide uses a Category → Section → Article hierarchy. Salesforce Knowledge uses Data Categories — a hierarchical classification system with Category Groups containing nested categories. (support.zendesk.com)

The structural mismatch means you can't do a straight import:

  • Data Category limits. Salesforce supports up to three active category groups, five levels per group, and 100 categories per group. Zendesk categories and sections rarely map 1:1 — product, region, or audience dimensions usually make better Salesforce category groups than a literal copy of the Zendesk tree. (help.salesforce.com)
  • Visibility model. Zendesk uses "Visible to agents only" vs. "Visible to end users." Salesforce controls this through Data Category Visibility settings tied to roles and permission sets — a fundamentally different approach.
  • Embedded images are the biggest failure point. Zendesk stores images on its own CDN. During migration, every image URL must be downloaded, re-uploaded to Salesforce as a ContentVersion, and the HTML reference in the article body rewritten. Automated tools routinely break this. (support.zendesk.com)
  • Article translations. Zendesk stores translations as variants of the same article. Salesforce Knowledge supports multilingual articles natively, but the import must explicitly map each translation to the correct language version.
  • Reporting gap. Standard Salesforce Knowledge reports do not expose article data categories directly. Validation often requires SOQL queries or a custom report against the data category selection object. Teams that expect Zendesk section-level reporting parity on day one usually discover this late. (help.salesforce.com)

For a detailed walkthrough of Zendesk data extraction, see our guide on how to export tickets from Zendesk.

Field Mapping Reference Table

Zendesk Object Zendesk Field SF Object SF Field SF Type Transform? Notes
Ticket id Case Zendesk_Ticket_ID__c Text (External ID) No Preserve for upsert and rollback
Ticket subject Case Subject Text(255) No Truncate if >255 chars
Ticket description Case Description Long Text Area Yes Strip unsupported HTML if needed
Ticket status Case Status Picklist Yes Map: new→New, open→Working, pending→Pending, solved→Closed, closed→Closed. Keep original in Zendesk_Status__c
Ticket priority Case Priority Picklist Yes Map: low→Low, normal→Medium, high→High, urgent→Critical
Ticket type Case Type Picklist Yes Map: question, incident, problem, task
Ticket group_id Case OwnerId (Queue) Lookup Yes Map Zendesk group to Salesforce Queue
Ticket assignee_id Case OwnerId (User) Lookup Yes Needs valid SF User or fallback owner
Ticket requester_id Case ContactId Lookup Yes Load Contacts first
Ticket organization_id Case AccountId Lookup Yes Load Accounts first
Ticket tags Case Tags__c Multi-select Picklist Yes Join array to semicolon-delimited string
Ticket created_at Case CreatedDate DateTime Yes Requires "Set Audit Fields upon Record Creation" permission
Ticket updated_at Case LastModifiedDate DateTime Yes Same audit field permission required
Ticket ticket_form_id Case RecordTypeId Lookup Yes Manual mapping required
Ticket brand_id Case Brand__c Picklist Yes Important in multi-brand orgs
Ticket via.channel Case Origin Picklist Yes Map email, web, chat, phone, api values
Ticket satisfaction_rating Case CSAT_Score__c Number/Picklist Yes Historical value only; rebuild survey separately
Ticket custom_field_* Case Custom_Field__c Varies Yes Type-by-type mapping required
Comment body/html_body (public) EmailMessage TextBody/HtmlBody Long Text Yes Must link to Case via ParentId
Comment body (internal) CaseComment CommentBody Text Yes 4 KB limit per CaseComment — split long notes
Comment author_id EmailMessage FromAddress Email Yes Resolve Zendesk user ID to email address
Comment created_at EmailMessage MessageDate DateTime No
Comment attachments ContentVersion VersionData Base64 Yes Download binary, encode, upload, link via ContentDocumentLink
User id Contact Zendesk_User_ID__c Text (External ID) No Primary match key
User name Contact FirstName + LastName Text Yes Split on space; handle single names
User email Contact Email Email No Deduplicate before import
User phone Contact Phone Phone No Direct map
User organization_id Contact AccountId Lookup Yes Link after Account load
Organization id Account Zendesk_Org_ID__c Text (External ID) No Primary match key
Organization name Account Name Text No Handle duplicate names during prep
Organization domain_names Account Website URL Yes Take first domain
Article title Knowledge__kav Title Text No Direct map
Article body Knowledge__kav Body__c Rich Text Area Yes Rewrite image URLs post-upload
Article section_id Knowledge__kav Data Category Yes Tree redesign usually required
Article locale Knowledge__kav Language Picklist Yes Multilingual setup must exist first

The rows that usually force custom logic are comment splitting, tag modeling, file migration, and knowledge structure. Those are the places where drag-and-drop tools start to blur history.

Migration Approaches

You have five viable paths. The right one depends less on sticker price and more on whether you need historical fidelity, custom transformation logic, and a controlled cutover.

1. Manual CSV Export/Import

Export tickets from a Zendesk view as CSV, then import into Salesforce using Data Loader or Dataloader.io.

The reality: Zendesk's view CSV export is capped at 1,000 rows per export and does not include ticket comments, descriptions, or attachments. You'd need multiple date-filtered views stitched together, and you still wouldn't get conversation history. (eesel.ai)

When to use it: Only for very small migrations where you genuinely don't need comment history. Read more about how to export tickets from Zendesk.

Practical ceiling: A few thousand active records or reference tables.

2. API-Based Custom Migration

Your engineering team builds scripts that extract data via the Zendesk Incremental Export API (cursor-based pagination), transform it, and load it into Salesforce via Bulk API 2.0.

Zendesk extraction: The Incremental Export API has its own rate limit of 10 requests per minute, regardless of plan tier — separate from the general Support API limit of 200–700 req/min. The High Volume API add-on (available on Growth+ plans, minimum 10 agent seats) increases incremental exports to 30 requests per minute. Each page returns up to 1,000 tickets, but ticket comments require separate per-ticket API calls. (developer.zendesk.com)

Salesforce loading: Bulk API 2.0 auto-batches in chunks of 10,000 records. The 15,000 batch limit per rolling 24-hour period is shared between Bulk API and Bulk API 2.0.

When to use it: Teams with in-house engineering capacity who need full control over transformation logic. Expect 3–8 weeks of engineering effort for a production-grade migration.

3. Help Desk Migration (Automated Tool)

A SaaS wizard that connects to both platforms via API. You map fields through the UI, run a demo migration, then execute the full transfer. Pricing is per-record.

What it does well: Field mapping UI, basic relationship preservation, demo migration before committing, multilingual knowledge base transfer.

Where it falls short: The vendor's own Salesforce checklist notes that its standard wizard cannot import CC users, groups, or ticket tags to Service Cloud. Knowledge dates can change on import. If something doesn't migrate in the demo, it won't suddenly work in the full run — a strong signal that schema mismatch still needs human intervention. (help-desk-migration.com)

4. Third-Party iPaaS (Zapier, Make)

These platforms are built for real-time trigger-based workflows — create a Salesforce Case when a Zendesk ticket is created. They are not designed for historical backfills of hundreds of thousands of tickets, comments, files, and knowledge articles. Use them for ongoing sync after cutover, not the archive migration.

5. Managed Migration Services

A dedicated engineering team handles extraction, transformation, loading, and validation end-to-end. Best for 100K+ tickets, complex custom field schemas, Knowledge Base migration, multi-brand Zendesk instances, or tight timelines.

Approach Comparison

Method Best For Volume Ceiling Relationships Attachments Knowledge Base Est. Cost Risk
CSV + Data Loader Tiny orgs, no history needed ~5K tickets No No No $0 + internal time High (data loss)
API Custom Scripts Engineering-led orgs, full control Unlimited Yes Yes Yes $8K–$60K+ (eng hours) Medium
Help Desk Migration Standard schemas, moderate volume ~200K clean Partial Partial Yes (with prep) $500–$5,000+ Medium
iPaaS (Zapier/Make) Ongoing sync only N/A for migration Partial No No $50–$500/mo High if used for backfill
Managed Service Complex or enterprise migrations Unlimited Yes Yes Yes $5K–$50K+ Low

What Breaks in Automated Tools

Automated tools like Help Desk Migration handle the happy path well. Here's where they fail — and where you'll need engineer intervention. If your automated migration already failed, consult our helpdesk migration rescue guide.

  • Inline images in ticket comments. Zendesk hosts images on its CDN. Automated tools often migrate the text but leave image src attributes pointing at Zendesk URLs. When you decommission Zendesk, all inline images break. The fix: download every image, re-upload to Salesforce as a ContentVersion, and rewrite the HTML references. (support.zendesk.com)

  • Attachment size limits. The legacy Salesforce Attachment object has a 25 MB per-file limit. ContentVersion (Salesforce Files) supports up to 2 GB, but many tools default to the legacy object. Large Zendesk attachments silently fail unless you ensure the tool uses ContentVersion or request a limit increase from Salesforce Support. (help.salesforce.com)

  • Internal notes vs. public replies merged. Some tools merge everything into CaseComment, making it impossible to tell what the customer actually saw versus internal discussion. This is the most common misclassification and the most damaging for agent trust.

  • Custom field type mismatches. A Zendesk multi-select dropdown maps to a Salesforce multi-select picklist, but the delimiter format differs. Values that don't exist in the target picklist are silently dropped — no error, no log entry.

  • Ticket followers and CCs. Zendesk's follower/CC model has no direct Case equivalent. These need to be mapped to Case Team Members, which requires explicit API calls. Help Desk Migration's checklist confirms CC users are not imported in the standard path. (help-desk-migration.com)

  • Merged tickets. Zendesk merged tickets create a parent-child relationship with audit trail entries. Most tools migrate the surviving ticket and lose the merged ticket's context entirely, or migrate them as separate, disconnected cases.

  • Duplicate contacts. Zendesk allows multiple users with the same email. Salesforce standard matching rules will block or alert on these during insertion, causing dropped tickets or orphaned records.

  • Timestamp handling. Setting CreatedDate on Salesforce records requires the "Set Audit Fields upon Record Creation" permission. Without it, every migrated Case gets today's date as its creation date — destroying all historical reporting.

  • Suspended or deleted user associations. Tickets associated with suspended or deleted users in Zendesk become orphaned records during migration. The user reference points to a non-existent contact unless explicitly handled in the transform phase.

Real Cost Comparison

Make your decision based on total cost of ownership, not just tool pricing.

Info

These are planning ranges, not quotes. They combine public pricing signals with the actual work this migration path usually requires.

DIY (Internal Engineering)

  • Engineering time: 120–300 hours for a mid-complexity migration (50K–200K tickets, 10+ custom fields, attachments)
  • Loaded cost: At $100–$150/hr fully loaded, that's $12,000–$45,000 in engineer time alone
  • Testing cycles: Add 40–80 hours for validation and rework
  • Hidden cost: Opportunity cost. Those engineers aren't building product features.
  • Tools: Salesforce Data Loader is free. Dataloader.io has a free tier. (developer.salesforce.com)

Help Desk Migration

  • Pricing model: Per-record, with costs scaling by volume and add-on features
  • Typical range: ~$500–$1,500 for 50K tickets (basic); $2,000–$5,000 for 200K tickets with attachments and knowledge base
  • What's extra: Custom field mapping adjustments, delta sync, and premium support are additional fees
  • Limitation: Complex transformations and data cleanup are quoted separately and not visible in the demo pricing. (help-desk-migration.com)

ClonePartner Managed Migration

  • Pricing model: Flat project pricing based on scope assessment
  • What's included: End-to-end field mapping, custom transformation logic (including the EmailMessage/CaseComment split), relationship preservation, incremental validation, rollback support, and delta sync before cutover
  • Typical range: $5,000–$25,000 for mid-market (50K–500K tickets). Enterprise with complex schemas and multi-brand instances runs higher.
  • Difference: You're paying for engineering judgment, not just record transfer. Rate limit management, Salesforce API constraint handling, and inline image preservation are included.

Step-by-Step Migration Process

Phase 1: Data Audit in Zendesk

Start with an inventory, not code. Before extracting anything:

  • Count active vs. archived vs. closed tickets
  • Identify suspended and deleted users
  • List orphaned organizations with no associated users or tickets
  • Catalog every custom field — note data types and which are actively used
  • Document all ticket forms (these become Record Types)
  • Check for side conversations, Talk/Chat usage, and multi-brand configuration
  • Export a sample of 100 tickets and review comment structure
  • Decide what not to move. The cheapest record to migrate is the one you consciously retire.

Also document which Zendesk features need a rebuild rather than a migration: macros, triggers, automations, SLA policies, Explore dashboards, and app-dependent workflows.

Phase 2: Salesforce Environment Preparation

Do this before migration, not during:

  • Create all custom fields on Case, Contact, and Account objects
  • Create Record Types matching your Zendesk ticket forms
  • Set up Queues corresponding to Zendesk groups
  • Create External ID fields (Zendesk_Ticket_ID__c, Zendesk_User_ID__c, Zendesk_Org_ID__c) for upsert operations
  • Enable the "Set Audit Fields upon Record Creation" permission for the integration user
  • Build your Entitlement Process structure, survey plan, and Knowledge Data Categories
  • Disable all automation rules, validation rules, workflow triggers, and email deliverability
Warning

Failing to disable automations before import is the single most common migration mistake. Importing 200K historical cases will trigger every Flow, assignment rule, and auto-response rule in your org — potentially sending hundreds of thousands of emails to customers about years-old tickets.

Phase 3: Extract from Zendesk

Use the Incremental Export API with cursor-based pagination. The critical nuance: Zendesk's general Support API allows 200–700 requests per minute depending on plan, but the Incremental Export endpoint has its own separate limit of 10 requests per minute (30 with the High Volume add-on). (developer.zendesk.com)

# Zendesk Incremental Export - Tickets
import requests
import time
 
base_url = "https://yoursubdomain.zendesk.com"
headers = {"Authorization": "Bearer YOUR_TOKEN"}
 
start_time = 0  # epoch 0 = export everything
url = f"{base_url}/api/v2/incremental/tickets/cursor.json?start_time={start_time}"
 
all_tickets = []
while True:
    response = requests.get(url, headers=headers)
    if response.status_code == 429:
        retry_after = int(response.headers.get("Retry-After", 60))
        time.sleep(retry_after)
        continue
    data = response.json()
    all_tickets.extend(data["tickets"])
    if data["end_of_stream"]:
        break
    url = data["after_url"]
    time.sleep(6)  # Stay within 10 req/min limit

Ticket comments require separate per-ticket calls to /api/v2/tickets/{id}/comments.json. For a 50K-ticket instance with an average of 5 comments per ticket, that's 50,000+ additional API calls just for comments.

Pull side conversations separately through the side conversation API. If Zendesk Talk or Chat history is in scope, extract through their own APIs — these are not included in the standard ticket export. The Chat API has its own rate limit of 200 req/min.

Info

The Incremental Export API includes deleted tickets by default. Use exclude_deleted=true if you don't want them. Zendesk retains permanently deleted tickets as minimal records for only 90 days. (developer.zendesk.com)

Phase 4: Transform

This is where you fix data — not after the fact in Salesforce reports. Typical transform work:

  • Split comments: Route public replies to EmailMessage records, internal notes to CaseComment records
  • Dedup contacts: Merge Zendesk users with duplicate emails before import
  • Normalize timestamps: Convert all to UTC and ISO 8601 format
  • Map picklist values: Convert Zendesk status, priority, and type values to their Salesforce equivalents. Ensure every value exists in the target picklist before load.
  • Flatten arrays: Tags, domain_names, collaborator_ids → semicolon-delimited strings or child records
  • Rewrite inline image URLs: Download images, prepare for ContentVersion upload, update HTML references
  • Build lookup maps: Create ID maps from Zendesk legacy IDs to Salesforce External IDs
  • Handle edge cases: Suspended users, merged tickets, single-name users, missing organization associations

If you skip this layer, the load may succeed, but the org will be wrong.

Phase 5: Load into Salesforce

Use Bulk API 2.0 for large volumes. Load in strict dependency order:

Accounts → Contacts → Cases → EmailMessages → CaseComments → Attachments (ContentVersion) → Knowledge Articles

# Create a Bulk API 2.0 Ingest Job
curl -X POST https://yourinstance.salesforce.com/services/data/v60.0/jobs/ingest \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "object": "Case",
    "operation": "upsert",
    "externalIdFieldName": "Zendesk_Ticket_ID__c",
    "contentType": "CSV",
    "lineEnding": "LF"
  }'

Upload your CSV data to the job, then close it to begin processing. Monitor job status via GET /services/data/v60.0/jobs/ingest/{jobId}. Salesforce auto-batches every 10,000 records internally.

Key constraints: The 15,000 batch limit per rolling 24-hour period is shared between Bulk API and Bulk API 2.0. Keep individual uploads under ~100 MB for best results. Monitor your general API usage too — paid orgs start at a daily API request limit of 100,000.

If you are assigning Knowledge data categories via API, Salesforce does not support mass-updating them in place. The practical pattern is to delete existing selections and insert the desired ones. (help.salesforce.com)

Phase 6: Relationship Rebuilding

After the bulk load, relink all records:

  • Each Case to its Contact (ContactId) and Account (AccountId)
  • Each EmailMessage to its parent Case (ParentId)
  • Each CaseComment to its parent Case (ParentId)
  • Each ContentVersion to its parent Case via ContentDocumentLink
  • Knowledge articles to their Data Categories

This is also where you decide how to preserve CCs, followers, side conversations, and merged-ticket lineage if you're not modeling them natively.

Phase 7: Validation

Do not decommission Zendesk when the load finishes. Decommission it when validation finishes.

Record count reconciliation:

  • Zendesk tickets exported = Salesforce Cases created
  • Zendesk end users exported = Salesforce Contacts created
  • Zendesk organizations exported = Salesforce Accounts created
  • Public comments = EmailMessage records
  • Internal notes = CaseComment records
  • Attachments = ContentVersion records

Field-level spot checks: Sample 1–2% of records across all objects. Open the Zendesk ticket, open the corresponding Salesforce Case, and verify field-by-field. Focus on tickets with attachments, merged tickets, tickets with internal notes, knowledge articles with images, tickets from each brand, and at least one record for every major custom field.

Relationship integrity: Run SOQL queries to confirm:

  • Every Case has a valid ContactId and AccountId
  • Every EmailMessage has a valid ParentId pointing to a Case
  • Every ContentDocumentLink connects an attachment to its parent Case

Attachment accessibility: Open 20–30 attachments at random in the Salesforce UI. Confirm they render correctly.

Knowledge article rendering: Check embedded images in migrated articles. If images still point at Zendesk CDN URLs, they'll break when Zendesk is decommissioned.

UAT with agents: Have 2–3 actual support agents look up historical tickets they remember and verify the data looks right in Service Console. Agents find readability issues that count reports miss.

Rollback plan: Tag imported records with a migration run ID. If validation fails, delete in reverse dependency order: ContentDocumentLinks → ContentVersions → CaseComments → EmailMessages → Cases → Contacts → Accounts. Use the External ID field to scope the delete.

Edge Cases and Known Pitfalls

  • Zendesk Talk and Chat transcripts. These live in separate data stores with separate APIs. Talk has its own API surface. Chat transcripts must be pulled via the Chat API (200 req/min rate limit) and mapped to Salesforce Chat Transcripts or appended as Case Comments. They are not included in the standard ticket export. (developer.zendesk.com)

  • Side conversations. Zendesk's side conversation feature (child tickets with separate external participants) has no direct Case equivalent. These must be migrated as separate Cases, as CaseComments on the parent Case, or into a custom child object with metadata noting the original context. (developer.zendesk.com)

  • Multi-brand Zendesk instances. Map the Zendesk brand_id to a custom Brand__c picklist or different Case Record Types to maintain routing and filtering logic. A single Salesforce org typically needs queue and business-unit logic to keep multi-brand history separate.

  • Merged tickets. Zendesk retains merged tickets as closed records pointing to a parent ticket. The merged ticket's original comments are folded into the surviving ticket, but the merge event metadata is often lost in migration. Preserve merged source IDs in a custom field if the lineage matters.

  • Custom Zendesk apps. If custom apps wrote data to ticket custom fields, that data is in Zendesk's database and will come through the API. Catalog every custom field — including those created by apps — during the audit phase. Hidden business logic often lives in those custom values.

  • Deleted tickets in exports. The Incremental Export API includes deleted tickets by default. Filter them explicitly with exclude_deleted=true if your target should exclude them. Zendesk says permanently deleted tickets retain a minimal record for only 90 days.

  • Suspended users. Tickets associated with suspended or deleted users become orphaned records during migration. Handle these explicitly in the transform phase — either by mapping to a generic contact or by preserving the association in a legacy field.

Post-Migration Work That Nobody Talks About

The data load is the middle third of the project. The before and after take just as long.

  • Rebuild macros as Quick Actions and Flows. This is manual work. A team with 50 Zendesk macros should budget 2–4 weeks for a Salesforce admin to rebuild them. Complex macros with conditional logic need Flow Builder. Read more about automations and workflow migration.

  • Recreate SLA policies as Entitlement Processes. Zendesk SLA configuration takes an afternoon. Salesforce Entitlement Processes with Milestones, warning actions, and violation actions take days to configure and test. Once an Entitlement Process is activated, you can't modify its milestones without creating a new version.

  • Rebuild reporting from scratch. Zendesk Explore dashboards cannot be exported as Salesforce report logic. Zendesk lets you export dashboard tabs as CSV, Excel, PNG, or PDF — that's data output, not transferable report logic. Every dashboard must be rebuilt natively in Salesforce Reports and Dashboards. (support.zendesk.com)

  • Agent training on Service Console. The Service Console is a significantly different UX from Zendesk's Agent Workspace — tab-based navigation that feels alien to Zendesk-trained agents. Budget 1–2 weeks for training, plus a parallel run period where agents can reference both systems.

  • Update help center URLs. If you migrate your Knowledge Base, every support.yourcompany.com/hc/en-us/articles/... URL needs a 301 redirect to the new Salesforce Knowledge article URL. Set these up before decommissioning Zendesk.

  • Decommission Zendesk carefully. Check your contract termination window. Confirm data retention obligations. Keep Zendesk in read-only mode for 30–90 days post-cutover as a safety net. Cancel the subscription only after agents have confirmed data integrity in Salesforce.

When to Use a Managed Migration Service

Internal teams should not attempt this migration alone when:

  • Limited Salesforce admin experience on the team
  • 100K+ tickets with attachment history
  • Complex custom field schemas (15+ custom fields with type mismatches)
  • Knowledge Base migration is in scope
  • Multi-brand Zendesk instance or multi-language Knowledge Base
  • Tight deadline — under 4 weeks from start to cutover

The hidden costs of DIY are real: engineer opportunity cost (those sprints aren't shipping product), 3–5 testing cycles to get field mappings right, production incident risk if automations fire on imported data, and the data cleanup that inevitably follows a partial failure.

The cleanest budget question is not "What tool is cheapest?" It is "What level of historical accuracy do we need agents to trust on Monday morning?" That answer usually tells you whether you need a tool, custom engineering, or a managed service.

ClonePartner handles this migration end-to-end: field mapping, custom transformation logic (including the EmailMessage/CaseComment split), Zendesk API rate limit management, Salesforce Bulk API constraint handling, inline image preservation, relationship validation, and incremental delta sync before cutover.

Best Practices Summary

  1. Back up everything before starting. Export a full JSON backup from Zendesk.
  2. Run a pilot migration with 500–1,000 tickets first. Validate the output before committing to a full run.
  3. Migrate in dependency order: Accounts → Contacts → Cases → EmailMessages → CaseComments → Attachments → Knowledge.
  4. Use External ID fields for upsert operations. This makes re-runs and delta syncs safe.
  5. Monitor API limits during both extraction and load. The Zendesk Incremental Export limit (10 req/min) and Salesforce batch limit (15,000/24hr) are the bottlenecks.
  6. Keep Zendesk read-only during the final migration window. No new tickets should be created in Zendesk after the last delta sync begins.
  7. Disable all Salesforce automations before import. Re-enable only after validation is complete.
  8. Validate before decommissioning. Never cancel your Zendesk subscription until agents have confirmed data integrity in Salesforce.

For a shorter operational checklist, see our Salesforce Service Cloud Migration Checklist.

Frequently Asked Questions

How do I map Zendesk ticket comments to Salesforce?
Zendesk ticket comments must be split during migration. Public replies should become EmailMessage records linked to the Case, preserving email thread history and metadata. Internal notes should become CaseComment records. Mixing them up makes it impossible for agents to distinguish what customers saw from internal discussion.
How long does a Zendesk to Salesforce Service Cloud migration take?
A typical mid-market migration (50K–200K tickets) takes 2–6 weeks end-to-end: 1 week for data audit and Salesforce prep, 1–2 weeks for extraction and transformation, and 1–2 weeks for loading, validation, and cutover. Complex migrations with Knowledge Base, multi-brand instances, or 500K+ tickets can take 6–10 weeks.
What is the Zendesk API rate limit for data extraction?
The Zendesk Incremental Export API is limited to 10 requests per minute, regardless of plan tier. The High Volume API add-on (Growth plans and above, minimum 10 agent seats) increases this to 30 requests per minute. Ticket comments require separate per-ticket API calls using the standard API, which has its own per-plan limits of 200–700 req/min.
Can I use Zendesk's CSV export for a Salesforce migration?
Not effectively. Zendesk's view CSV export is capped at 1,000 rows per export and does not include ticket comments, descriptions, or attachments. For any migration involving historical conversation data, you need the Incremental Export API or a migration tool.
How much does a Zendesk to Salesforce migration cost?
DIY with internal engineers typically costs $12,000–$45,000 in engineering time for a mid-complexity migration. Help Desk Migration's per-record pricing ranges from $500–$5,000 depending on volume and features. Managed migration services like ClonePartner charge flat project pricing, typically $5,000–$25,000 for mid-market orgs.

More from our Blog

Why Top-Performing Teams are Migrating to Salesforce Service Cloud: A Deep Dive
Salesforce Service Cloud

Why Top-Performing Teams are Migrating to Salesforce Service Cloud: A Deep Dive

Top-performing SaaS teams in the US and Europe are migrating to Salesforce Service Cloud to deliver faster, personalized, and truly omnichannel customer support. This guide explains why legacy support systems fail and how Service Cloud helps businesses scale service operations with AI, automation, and a 360° customer view.

Raaj Raaj · · 8 min read