| Ticket load run— (load settings) |
Case— (automation and email during load) req |
manual review |
Loading cases fires case triggers, flows, assignment and auto-response rules and email alerts, so customers can get emails about years-old tickets. Before any production load, set email deliverability to system email only and give the load user a bypass (a custom permission the triggers and flows check) so automation skips loaded records while staying on for everyone else. Turn deliverability back on only after the load is checked. |
| Ticket (archived)Tickets closed more than 120 days ago |
Case— (load scope) req |
derive |
Zendesk archives tickets about 120 days after they close, and the standard ticket list API leaves archived tickets out. Build the full ticket list (and any attachment job) from the incremental export API, which includes them, so older history is not silently missing from the load. |
| Ticketsubject / description |
CaseSubject / Description req |
direct |
|
| TicketDescription (long or HTML) |
CaseDescription |
derive |
Very long HTML descriptions can break a CSV load: embedded quotes and line breaks shift columns, so values land in the wrong fields. Convert the HTML to plain text and trim it to the Case Description limit (32,000 characters) before loading, and keep the full text in a comment or file if it matters. |
| Ticketstatus / priority |
CaseStatus / Priority req |
picklist map |
|
| Ticketrequester |
CaseContactId req |
lookup |
|
| TicketRequester email with no matching contact |
CaseContactId / SuppliedEmail |
manual review |
Requester lookups by email are the most common reason cases fail to load. Load and dedupe contacts first, then send unmatched tickets to an agreed placeholder contact (or leave ContactId blank and keep the address in SuppliedEmail) so they can be reviewed instead of rejected. |
| TicketTickets with no matching requester (catch-all) |
Account / ContactPlaceholder record Email |
manual review |
If unmatched or no-email tickets are parked on a placeholder account or contact, never give it the old help desk's address or any real inbox. Case auto-responses and email replies would go there. Use a non-deliverable address before loading. |
| TicketRequester email (primary and secondary addresses) |
CaseContactId (matched on email fields marked External ID) |
lookup |
Match in passes: primary email first, then any secondary or alternate email on the contact. Mark each email field you match on as an External ID so it can be used as an upsert key. Hold tickets that still do not match in a review file rather than attaching them to a dummy account. |
| OrganizationOrganization |
AccountName |
direct |
|
| Ticketassignee / group |
CaseOwnerId (user or queue) |
lookup |
|
| TicketGroup and assignee (both set) |
CaseOwnerId + Case Reason (or team field) and list views |
derive |
A Zendesk ticket can carry a group and an assignee at once; a Salesforce case has a single owner, either a user or a queue. Own assigned tickets by the user and unassigned ones by the group queue, and carry the team in Case Reason or a team field with list views filtered on it, so a team still sees its cases when they are owned by someone who is away or has left. If one Zendesk category covers work handled by two different teams, split it into two case reasons. |
| GroupGroups referenced on tickets (including inactive or deleted groups) |
QueueCase OwnerId (queue) req |
lookup |
Build the group-to-queue list from the group IDs that actually appear on exported tickets, not only the current list of active groups. A group with no queue leaves its tickets out of the load. Reconcile ticket counts per group after loading, and fill any gaps with an upsert on the ticket external ID rather than a second import. |
| TicketAssignee (deactivated agent) |
CaseOwnerId |
lookup |
Records owned by people with no active Salesforce user fail the load. Route them to a queue or an integration user and keep the original assignee name in a text field. |
| Ticket commentPublic / private comments |
CaseComment / EmailMessage— |
manual review |
Private comments become internal comments. |
| Ticket commentComments loaded as feed items |
FeedItem / CaseComment— (load method) |
rebuild |
Feed items and case comments cannot be reliably matched for updates, so re-running a load creates duplicates. Treat them as delete-and-reload: run a small trial load in production, check it, delete it, then load the full set once at cutover after the cases exist. Documents can still go in as delta loads. |
| Tickettags / custom fields |
CaseCustom fields |
picklist map |
|
| MacroMacros |
Quick text / macros— |
rebuild |
|
| Help Center articleArticles |
Knowledge article— |
direct |
|
| SLA policyTargets |
Entitlements & milestones— |
rebuild |
|
| TicketTicket ID |
CaseExternal ID field req |
derive |
Store the source ticket ID with a prefix (for example ZD-12345) in an external ID field. Users can still search by the old ticket number, comments and attachments can be linked back, and reruns can upsert instead of duplicating. |
| TicketRequester type (staff or system vs. customer) |
CaseRecordTypeId / Type |
derive |
Tickets raised by internal staff or system senders are not customer cases. Load them under a separate record type or type value so they stay searchable by old ticket number without skewing customer history and service reports. |
| User (agent)Zendesk user ID |
UserZendesk user ID (custom field) |
lookup |
Matching agents and submitters by Zendesk user ID only works if that ID is stored on the Salesforce User first. Add and populate the field before loading cases, or match on email instead. |
| Ticket attachmentAttached files |
Salesforce FilesContentVersion + ContentDocumentLink (to Case) |
association |
Load attachments as Files after the cases exist, then link each file to its case. Attachment exports can run to hundreds of gigabytes, so stage them in cloud storage and load the most recent years first; older history can follow once current records are verified. |
| Ticket commentComment attachments and inline images (file name, type, size, download URL) |
Salesforce FilesContentVersion linked to the Case (matched on ticket external ID) |
association |
Ticket exports do not include the files themselves; every attachment sits on a ticket comment and has to be pulled through the comments API. Download each file as soon as its link is read (private attachment links can expire), write a manifest with ticket ID, comment ID, name and size, checkpoint each batch so reruns skip loaded files, and stay within API rate limits. A file can only attach to a Case that loaded. Reconcile file counts and size per ticket, and check Salesforce file storage before the full load. |