Skip to content

Zendesk to LiveChat Migration: The Complete Technical Guide

Technical guide to migrating from Zendesk to LiveChat + HelpDesk. Covers API extraction, data model mapping, the importedTickets endpoint, rate limits, and edge cases.

Roopi Roopi · · 18 min read
Zendesk to LiveChat Migration: The Complete 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

What This Migration Actually Involves

Zendesk groups all interactions — emails, web widgets, API submissions, and live chats — into a single Ticket object. A live chat in Zendesk is just a ticket with a specific via.channel attribute. Its data model includes tickets, users, organizations, custom fields, tags, macros, triggers, automations, SLAs, views, and a knowledge base (Guide).

LiveChat is a real-time chat platform. It handles live conversations through the Agent Chat API v3.5. For asynchronous support (email, ticket-based workflows), LiveChat now relies on HelpDesk (helpdesk.com), a separate product by Text, LiveChat's parent company. LiveChat's legacy built-in ticketing system was sunset in January 2025 and replaced by HelpDesk. HelpDesk's data model centers on tickets with events (messages, status changes, assignments), teams, agents, tags, custom fields, and canned responses.

This means migrating from Zendesk requires splitting your data into two targets:

  1. LiveChat: Historical live chats (Zendesk tickets where via.channel = chat). These map to LiveChat's Chats → Threads → Events hierarchy.
  2. HelpDesk: Asynchronous tickets — email, web form, and API-submitted tickets. These map to HelpDesk's ticket → event model.

The core data-model challenge: Zendesk organizes conversations as comments on tickets (each comment is a separate object with an author, body, and timestamp). HelpDesk organizes conversations as events within tickets (each event has a type, date, and payload). A direct field-copy will produce broken records.

API references used in this guide:

Last verified: June 2025 against Zendesk API v2, HelpDesk API v1, and LiveChat Agent Chat API v3.5.

Why Teams Move from Zendesk to LiveChat

Teams make this switch for specific operational reasons:

  • Chat-first support model. The team is pivoting from email/ticket-based support to real-time chat as the primary channel — common in e-commerce and SaaS with high-volume, low-complexity queries.
  • Cost reduction. Zendesk's per-agent pricing scales steeply. A team on Suite Professional ($115/agent/month) can often cover the same use case with LiveChat ($49/agent/month) + HelpDesk Team ($29/agent/month) for roughly half the cost.
  • Platform consolidation. Teams standardizing on the Text ecosystem (LiveChat + HelpDesk + ChatBot + KnowledgeBase) want all customer interactions under one vendor.
  • Agent experience. LiveChat's interface is purpose-built for real-time conversations. Teams that spend most of their time in chat find Zendesk's agent workspace heavier than needed.
Warning

What you lose in the move: Zendesk's mature trigger/automation engine, SLA policies with business-hour calculations, multi-brand support, side conversations, satisfaction prediction, and Explore analytics do not have direct equivalents in LiveChat/HelpDesk. Evaluate these gaps before committing.

Zendesk vs HelpDesk: Data Model Comparison

Before writing migration code, understand how the two data models differ:

Zendesk Concept HelpDesk Equivalent Migration Notes
Ticket Ticket 1:1 mapping. Use POST /v1/importedTickets for timestamp preservation.
Comment (public) Event (type: message, isPrivate: false) Must include date for each event in chronological order.
Comment (internal note) Event (type: message, isPrivate: true) Set agentID and agentName on agent-issued events.
User (requester) Requester (email + name) HelpDesk has no standalone contacts/users table.
User (agent) Agent Must pre-create agents via POST /v1/agents before referencing in tickets.
Organization No equivalent. Store in a custom field if needed.
Group Team Create teams first via POST /v1/teams.
Custom Field Custom Field (singleLine, multiLine, date, url) HelpDesk supports only 4 types. Dropdowns, checkboxes, numeric, and regex fields must be flattened to singleLine. 120-char limit on single-line fields; 1,000-char limit on multi-line.
Tag Tag Tags are team-scoped in HelpDesk. Create via POST /v1/tags with a teamID.
Priority (low, normal, high, urgent) Priority (-10, 0, 10, 20) Direct numeric mapping: low→-10, normal→0, high→10, urgent→20.
Status (new, open, pending, hold, solved, closed) Status (open, pending, onhold, solved, closed) Zendesk new has no equivalent — map to open.
Macro Macro Rebuild manually. HelpDesk limits macros to 20 shared + 20 per user.
Trigger / Automation Rule Rebuild manually via POST /v1/rules. HelpDesk Rules use a condition/action model but lack Zendesk's time-based trigger scheduling and business-hour arithmetic.
SLA Policy No native SLA engine in HelpDesk.
Attachment Attachment (via Transaction) 3-step process: create transaction → upload file → reference in ticket.
Satisfaction Rating Rating (good, neutral, bad) Zendesk has 2 ratings (good/bad). HelpDesk has 3 (good/neutral/bad). Map Zendesk goodgood, badbad; no source value maps to neutral.
Webhook Zendesk webhooks break at cutover. Rebuild downstream integrations against HelpDesk webhook events before go-live.

Zendesk vs LiveChat: Chat Data Model Comparison

For Zendesk tickets routed to LiveChat (via.channel = chat), the hierarchy is structurally different from HelpDesk's:

Zendesk Concept LiveChat Equivalent Migration Notes
Ticket (chat) Chat Top-level container.
Ticket thread / comments Thread A Chat contains one or more Threads.
Comment Event (type: message) Each agent or customer message becomes a discrete Event with author_type and timestamp.
Internal note Event (type: system_message) No direct equivalent for private agent notes in archived chats.
Attachment on comment Event (type: file) Separate event type; requires file upload to LiveChat CDN before referencing.
Agent (comment author) Agent (author_type: "agent") Agent must exist in LiveChat before the Chat is created.
End-user (requester) Customer (author_type: "customer") Customer identified by email in the Chat payload.

Zendesk frequently exports chat transcripts as a single monolithic comment block — a plain-text concatenation of the entire conversation rather than individual per-message records. Your transformation layer must parse this block using regex or structured splitting (matching patterns like [HH:MM] AgentName: message text) to reconstruct individual events with correct authors and timestamps before posting to the Agent Chat API v3.5.

Agent Chat API v3.5 event payload example (single message event):

{
  "type": "message",
  "text": "How can I help you today?",
  "author": {
    "type": "agent",
    "id": "agent_uuid_here",
    "name": "Jane Smith"
  },
  "created_at": "2024-03-15T10:23:45Z"
}

LiveChat Agent Chat API v3.5 rate limits: 1,000 requests per minute for most endpoints. Historical chat import calls follow the same limit. Monitor the X-RateLimit-Remaining response header.

How to Extract Data from Zendesk

Authentication

Zendesk supports two authentication methods for API access during migration:

  • API token (recommended for migration scripts): Use {email}/token:{api_token} as Basic Auth credentials. Tokens are scoped to the creating agent's permissions. Generate under Admin Center → Apps and Integrations → Zendesk API.
  • OAuth 2.0: Required if your migration tooling needs to act on behalf of multiple agents. More complex to set up but necessary for multi-agent impersonation scenarios.

For migration purposes, API token auth against an admin account is sufficient and simpler. Rotate the token after migration is complete.

As we noted in our Zendesk to Intercom migration guide, do not rely on Zendesk's standard /api/v2/tickets.json endpoint for a full migration. It caps pagination at 1,000 pages and shares the account-wide rate limit. The Incremental Ticket Export (cursor-based) is the correct extraction method. It returns all tickets created or modified since a given timestamp and supports full-dataset pagination without hitting the page cap.

# Initial request — start from Unix epoch 0 to get everything
GET /api/v2/incremental/tickets/cursor.json?start_time=0
 
# Subsequent pages — use the cursor from the previous response
GET /api/v2/incremental/tickets/cursor.json?cursor={after_cursor}

Key constraints:

  • Rate limit: 10 requests per minute to incremental export endpoints (30 with the High Volume API add-on). This is a separate, lower limit from the account-wide limit.
  • Pagination: Each page returns up to 1,000 tickets. Read end_of_stream: true in the response to detect completion.
  • Comments are not included in incremental ticket exports. Fetch them separately per ticket:
GET /api/v2/tickets/{ticket_id}/comments.json

This call counts against your account-wide rate limit. For 50,000 tickets on a Professional plan (400 req/min), fetching comments alone takes ~125 minutes at sustained max throughput.

  • Attachments are URLs, not binary files. Each comment attachment includes a content_url pointing to an AWS S3-hosted file behind an expiring signed URL. You must download the binary during extraction and store it locally — not as a deferred step. URLs expire and cannot be reused during the load phase.

Sideloading to Reduce API Calls

Use Zendesk's sideloading capability to minimize rate limit exhaustion. Append ?include=users,groups,organizations to your ticket API requests. This bundles associated metadata into the same JSON response, preventing separate queries to the Users API for every ticket author.

Full Data Export (JSON)

Zendesk's built-in full JSON export (Admin Center → Account → Tools → Reports → Export) includes tickets and comments in separate files. Available on Growth plans and above.

Limitations:

  • Processing time can exceed 24 hours for large accounts.
  • Tickets over 1 MB have comments excluded from the export.
  • Attachments are exported as URLs only, not binary files.
  • No incremental capability — it's a full snapshot every time.
  • Rate-limited to approximately one export per 7 days.

Use the full JSON export only as a validation baseline. The Incremental API gives you full control over pagination, retry logic, and supports delta syncs before cutover.

Zendesk API Rate Limits by Plan

Zendesk Plan Support API Limit Incremental Export Limit
Suite Team 200 req/min 10 req/min
Suite Growth 400 req/min 10 req/min
Suite Professional 400 req/min 10 req/min
Suite Enterprise 700 req/min 10 req/min
Suite Enterprise Plus 2,500 req/min 30 req/min
+ High Volume Add-on 2,500 req/min 30 req/min

The account-wide limit is shared across all API consumers — your migration script, active integrations, and some UI actions. Monitor the X-RateLimit-Remaining header and implement exponential backoff on 429 responses. On 429, wait the number of seconds specified in the Retry-After header before retrying; do not implement fixed-interval retries.

Error Handling During Extraction

HTTP Status Meaning Action
200 Success Continue
429 Rate limit exceeded Retry after Retry-After seconds (exponential backoff)
404 Ticket deleted since export started Log and skip
422 Malformed cursor Restart from last known good cursor
503 Zendesk maintenance Retry with backoff; check Zendesk status page

Separate recoverable errors (429, 503) from fatal ones (422 with bad cursor) in your error handler. A 404 on a ticket comment fetch means the ticket was deleted between your incremental export and the comment fetch — log it and continue.

How to Load Data into HelpDesk

Authentication

HelpDesk API uses Bearer token authentication:

Authorization: Bearer {your_api_token}

Generate tokens under HelpDesk Settings → API. Tokens are license-scoped — a single token has access to all agents and teams on that license. For migration, use one dedicated migration token and rotate it after import is complete.

The Imported Tickets Endpoint: Full Schema

HelpDesk provides a dedicated migration endpoint at POST /v1/importedTickets. The key difference from the standard POST /v1/tickets endpoint: imported tickets accept a full events array with custom dates, and the first message event's date becomes the ticket's createdAt timestamp. The standard ticket creation endpoint ignores any client-supplied created_at value and stamps the server's current time.

Required fields:

{
  "subject": "string (required)",
  "requester": {
    "email": "string (required)",
    "name": "string (required)"
  },
  "teamIDs": ["uuid (required — at least one)"],
  "events": [
    {
      "date": "ISO 8601 datetime (required, must be in the past)",
      "type": "message | status | assignment | tag (required)",
      "message": {
        "text": "string (plain text body)",
        "html": "string (HTML body, optional)"
      },
      "isPrivate": "boolean (default: false)",
      "agentID": "uuid (required for agent-issued messages)",
      "agentName": "string (required for agent-issued messages)"
    }
  ]
}

Optional fields:

{
  "tagIDs": ["uuid"],
  "priority": -10 | 0 | 10 | 20,
  "status": "open | pending | onhold | solved | closed",
  "assigneeID": "uuid",
  "customFields": [
    { "id": "uuid", "value": "string" }
  ],
  "transactionID": "uuid (required when attaching files)",
  "cc": ["email@example.com"],
  "followers": ["agent_uuid"]
}

Rules for the imported ticket endpoint:

  1. First event must be of type message — its date becomes the ticket creation date.
  2. Events must be in chronological order and all dates must be in the past.
  3. Agent-issued messages require agentID, agentName, and isPrivate parameters. Messages without these fields are treated as requester-issued.
  4. Status changes are expressed as events of type status — the last status event determines the final ticket status.
  5. A missing teamIDs field returns HTTP 400. This is the most common cause of bulk import failures.

Error Responses from the HelpDesk Import Endpoint

HTTP Status Common Cause Resolution
400 Missing required field (e.g., teamIDs, requester.email) Validate payload schema before POSTing
400 agentID references an agent not provisioned on the license Create the agent first via POST /v1/agents
400 Event date is in the future Check timezone handling in your transformer
409 Duplicate ticket (same external ID if you're passing one) Check your deduplication logic
429 Rate limit exceeded Retry after Retry-After seconds
500 HelpDesk internal error Retry up to 3 times with backoff; log and skip if persistent

A 400 from the HelpDesk import endpoint is never retryable without fixing the payload. Log the full request body on any 4xx response so you can diagnose field-level failures without re-running the full extraction.

Transformation Example

# Pseudocode: transform a Zendesk ticket to HelpDesk imported ticket
def transform_ticket(zd_ticket, zd_comments, id_map):
    events = []
    for comment in sorted(zd_comments, key=lambda c: c['created_at']):
        event = {
            "date": comment["created_at"],
            "type": "message",
            "message": {
                "text": strip_html(comment["body"]),
                "html": comment["html_body"]
            }
        }
        if comment["author_id"] in id_map["agents"]:
            event["agentID"] = id_map["agents"][comment["author_id"]]
            event["agentName"] = id_map["agent_names"][comment["author_id"]]
            event["isPrivate"] = not comment["public"]
        events.append(event)
    
    # Add final status event
    events.append({
        "date": zd_ticket["updated_at"],
        "type": "status",
        "status": map_status(zd_ticket["status"])
    })
    
    return {
        "subject": zd_ticket["subject"],
        "requester": {
            "email": get_requester_email(zd_ticket),
            "name": get_requester_name(zd_ticket)
        },
        "teamIDs": [id_map["teams"][zd_ticket["group_id"]]],
        "tagIDs": [id_map["tags"][t] for t in zd_ticket["tags"]],
        "priority": map_priority(zd_ticket["priority"]),
        "events": events
    }

Loading Tickets with Attachments

Attachments require a 3-step transaction process:

1. POST /v1/importedTickets/transactions
   → Returns { transactionID: "uuid" }

2. POST /v1/importedTickets/attachments
   Content-Type: multipart/form-data
   transactionID={uuid}
   attachments=@file1.pdf
   → Returns [{ attachmentID: "uuid" }]

3. POST /v1/importedTickets
   Include transactionID in the payload
   Reference attachmentIDs in attachment events
Warning

Transaction IDs expire after 24 hours. If your migration script pauses or crashes, you cannot reuse a stale transaction. All uploaded attachments associated with an unused transaction are purged automatically. Generate a new transaction ID at the start of each ticket's processing, not once at the start of the migration run.

Zendesk attachment content_url values point to AWS S3-hosted files behind expiring signed URLs. You cannot pass a Zendesk content_url directly to HelpDesk — the link will expire between extraction and load. Your middleware must download each binary from Zendesk during the extraction phase and store it locally before the load phase begins.

For inline images embedded in the HTML body of a Zendesk comment: parse the HTML, extract src attributes, download the images, upload them via the HelpDesk transaction flow, and rewrite the HTML src tags with the new attachment URLs before posting the event.

Throughput note: Benchmarked against a standard HelpDesk license, attachment-free tickets can be imported at approximately 80–100 tickets per minute (limited by the 1,000 req/10-min rate limit and ~10ms average API response time). Tickets with attachments require 3 sequential API calls per ticket; at the same rate limit ceiling, realistic throughput drops to 25–33 tickets per minute for attachment-heavy batches. These figures assume a single-threaded import loop; parallel workers can increase throughput up to the shared rate limit ceiling.

Suppressing Notifications During Import

The most critical failure mode during a migration is accidentally emailing your entire customer base with updates on years-old tickets.

Before executing the load into HelpDesk:

  1. Disable all automated workflows, auto-responders, and Rules in HelpDesk.
  2. Ensure your API token is used in a context that does not trigger outbound SMTP.
  3. Run a test batch of 10 tickets to a dedicated test team, verify that no outbound email is generated, then proceed.

HelpDesk Rate Limits

The HelpDesk platform enforces a shared rate limit of 1,000 requests per 10-minute window per license. This limit is shared across all tokens and integrations on the same license — including any active agent sessions. Monitor X-RateLimit-Remaining and Retry-After headers on every response.

Loading Historical Chats into LiveChat

For Zendesk tickets where via.channel = chat, the data routes to LiveChat rather than HelpDesk. LiveChat organizes data as: ChatsThreadsEvents. Each Thread corresponds to one continuous chat session; each Event is a discrete message, file, or system action.

Agent Chat API v3.5 Chat creation flow:

1. POST /v3.5/agent/action/start_chat
   → Returns { chat_id: "string", thread_id: "string" }

2. POST /v3.5/agent/action/send_event
   Payload: { chat_id, event: { type, text, created_at, author } }
   → Repeat for each message event in chronological order

3. POST /v3.5/agent/action/deactivate_chat
   Payload: { id: chat_id }
   → Closes the thread (marks the historical chat as ended)

Handling monolithic Zendesk chat transcripts:

Zendesk frequently exports chat transcripts as a single comment block. Parse using a pattern like:

import re
 
def parse_chat_transcript(transcript_text):
    """
    Parses Zendesk monolithic chat transcripts into structured events.
    Matches patterns like: [14:23] Agent Jane: Hello, how can I help?
    """
    pattern = r'\[(\d{2}:\d{2})\]\s+(.*?):\s+(.*?)(?=\[\d{2}:\d{2}\]|$)'
    matches = re.findall(pattern, transcript_text, re.DOTALL)
    events = []
    for timestamp_str, author_name, message_text in matches:
        events.append({
            "time": timestamp_str,
            "author": author_name.strip(),
            "text": message_text.strip(),
            "author_type": "agent" if author_name.strip() in known_agents else "customer"
        })
    return events

Note: Zendesk chat transcripts store times as HH:MM without a date. Reconstruct full ISO 8601 timestamps using the ticket's created_at date as the base, incrementing events sequentially. If a transcript crosses midnight, detect HH:MM rollover and increment the date.

Step-by-Step Migration Process

Step 1: Audit Your Zendesk Instance

Before extracting anything, inventory what you have:

  • Ticket count by status (new, open, pending, hold, solved, closed) and by channel (email, chat, web, API)
  • Custom fields — list types, names, and which ones are in active use
  • Groups and their agent membership
  • Tags — active tags vs. orphaned ones
  • Macros, triggers, automations — document the logic; these must be rebuilt
  • Webhooks — list all active webhooks and their downstream consumers; these break at cutover
  • Attachment volume — large attachment volumes significantly increase migration time

Decide what to migrate. Most teams skip closed tickets older than 2 years, deleted tickets, and suspended tickets (often spam or failed email routing). Migrating spam inflates your HelpDesk reporting metrics.

Step 2: Pre-Create Reference Data in HelpDesk

Before loading tickets, create the entities that tickets reference:

  1. TeamsPOST /v1/teams — map from Zendesk groups
  2. AgentsPOST /v1/agents — each agent needs an email and team assignment
  3. TagsPOST /v1/tags — HelpDesk tags are team-scoped (require a teamID)
  4. Custom FieldsPOST /v1/customFields — map Zendesk field types to HelpDesk's 4 supported types

Build an ID mapping table (Zendesk integer ID → HelpDesk UUID) for each entity type. You will reference this lookup table in every ticket transformation.

For agents who have left your company: their email addresses exist in Zendesk but won't be provisioned in HelpDesk. If you attempt to assign a historical ticket to an unprovisioned agent UUID, the API returns HTTP 400. Create a "Legacy Agent" profile in HelpDesk and default assignments for inactive agents to this profile while preserving the original agent's name in a custom field or private note event.

Step 3: Extract and Transform

Run the extraction against the Zendesk Incremental API starting from your earliest ticket date. Store raw JSON payloads in a local database (PostgreSQL or MongoDB work well) or structured flat files. Separate extraction from transformation — if your transformation logic has a bug, you can fix and re-run the transform without re-querying Zendesk or exhausting rate limits.

For each ticket:

  1. Fetch via the incremental export cursor
  2. Fetch all comments via GET /api/v2/tickets/{id}/comments.json
  3. Download attachment binaries from content_url and store locally
  4. Route based on via.channel: chat → LiveChat pipeline, everything else → HelpDesk pipeline
  5. Transform into the target format and store transformed payloads

Compliance note for EU-based teams: Extracted Zendesk data stored in local middleware (databases, flat files) contains PII (customer names, emails, message content). Ensure your migration environment complies with GDPR Article 28 (processor obligations) — use encrypted storage, restrict access, and delete extracted data from middleware once the migration is validated and complete.

Step 4: Load into HelpDesk and LiveChat

Iterate through transformed tickets and POST to /v1/importedTickets. For tickets with attachments, use the 3-step transaction process.

Implement checkpoint logging — record each successfully created ticket's Zendesk ID and HelpDesk UUID so you can resume after failures without creating duplicates. Log every ID mapping in a persistent table; this is essential for delta migrations and QA reconciliation.

Use exponential backoff to handle 429 responses. Starting interval: 2 seconds, doubling on each retry, maximum 5 retries before logging as a failed record for manual review.

Step 5: Validate

Do not assume HTTP 200 responses mean the data is correct. Run a programmatic validation script after import:

  • Ticket counts match expected totals by status and channel
  • Event counts per ticket — spot-check 50–100 tickets across different sizes and verify comment counts match
  • Timestamps — verify createdAt values match Zendesk originals, not the import date
  • Agent assignments resolve to the correct HelpDesk agents (not "Legacy Agent" where unintended)
  • Tags and custom fields populated correctly, no truncation on 120-char single-line fields
  • Attachments — sample 100 random tickets, download attachment URLs, verify files are accessible and non-zero in size

Step 6: Delta Sync and Cutover

On cutover day:

  1. Update DNS MX records and mail forwarding rules to route support emails to HelpDesk
  2. Deploy the LiveChat widget to your website (replace or alongside Zendesk widget)
  3. Rebuild Zendesk webhooks as HelpDesk webhook subscriptions — map event types and repoint downstream consumers
  4. Run a final delta extraction from Zendesk, pulling only tickets updated since Step 3 began (use the cursor from your last incremental export page)
  5. Transform and load the delta batch
  6. Rebuild Zendesk triggers, automations, and macros as HelpDesk Rules and Macros
  7. Enable HelpDesk automations and test with a real inbound email

Edge Cases That Break Migrations

Side conversations. Zendesk side conversations (child tickets, Slack threads, email threads initiated from a ticket) have no equivalent in HelpDesk. Flatten them into the parent ticket as private note events or discard them.

Merged tickets. Zendesk merged tickets redirect to a parent. HelpDesk supports ticket merging (POST /v1/tickets/{ticketID}/childTickets), but you must create both tickets first, then merge. The merge operation may reorder events chronologically.

Custom field type mismatches. HelpDesk supports only 4 custom field types: singleLine (120-char limit), multiLine (1,000-char limit), date, and url. Zendesk dropdowns, checkboxes, multi-select fields, numeric fields, and regex fields must all be converted to singleLine. Audit your field values for truncation risk before migration — values exceeding 120 characters will be silently truncated or rejected depending on HelpDesk API version.

Ticket followers vs. CCs. Zendesk distinguishes between CCs (external email recipients) and followers (internal agents). HelpDesk has both cc (array of email strings) and followers (array of agent UUIDs). Map Zendesk CCs to HelpDesk cc and Zendesk followers to HelpDesk followers with their resolved agent UUIDs.

Organization data. HelpDesk has no organizations table. If you rely on organization-level routing or reporting in Zendesk, store the organization name in a singleLine custom field on each ticket.

Webhook consumers. Any downstream system subscribed to Zendesk webhooks (CRM updates, Slack notifications, custom integrations) stops receiving events at cutover. Inventory all active Zendesk webhooks before migration and rebuild them against HelpDesk's webhook event schema before enabling new ticket intake.

Zendesk CSV export trap. Zendesk's CSV export contains only ticket metadata — no comments, descriptions, or attachments. It cannot be used as a migration source. (This is a common limitation across platforms; we see the exact same issue when migrating from LiveAgent to Zendesk).

Timeline and Effort Estimates

Migration Size Ticket Volume Expected Duration Primary Bottleneck
Small < 5,000 tickets 1–2 weeks Custom field mapping
Medium 5,000–50,000 2–5 weeks Attachment download/re-upload volume
Large 50,000–200,000 4–8 weeks Delta sync coordination near cutover
Very large 200,000+ 8–12 weeks Consider archiving tickets >3 years old vs. migrating

Engineering effort breakdown for a medium migration (20,000 tickets, moderate attachment volume):

  • Zendesk extraction pipeline: 3–5 days
  • HelpDesk/LiveChat transformation and load: 4–6 days
  • Attachment proxying middleware: 2–3 days
  • Validation scripts and QA: 2–3 days
  • Delta sync and cutover: 1–2 days

When Not to Make This Move

Don't migrate from Zendesk to LiveChat/HelpDesk if:

  • You depend heavily on Zendesk's SLA engine with business-hour calculations — HelpDesk has no native equivalent
  • You use Zendesk Guide extensively and need tight knowledge-base-to-ticket integration
  • You run multi-brand support with brand-specific routing and distinct inboxes per brand
  • Your team's workflow is email-first, not chat-first — HelpDesk handles email, but without LiveChat the value proposition weakens significantly
  • You need Explore-level analytics — HelpDesk's reporting covers standard metrics but offers limited custom report building compared to Zendesk Explore

Make the Move With Confidence

Migrating from Zendesk to LiveChat + HelpDesk is a data-model translation that requires custom scripting, rate-limit management, and careful validation. The HelpDesk imported tickets endpoint is purpose-built for this — but you need to get the event ordering, agent mapping, attachment transactions, and webhook reconstruction right.

For related walkthroughs, see our guides on HappyFox to LiveChat Migration and Freshservice to LiveChat Migration, or the broader Zendesk Migration Checklist.

Frequently Asked Questions

Does LiveChat still have a built-in ticketing system?
No. LiveChat's legacy ticketing was sunset in January 2025. Ticketing now runs through HelpDesk (helpdesk.com), a separate product by the same parent company, Text. HelpDesk integrates directly into the LiveChat agent app and shares the same authentication system.
Can I import Zendesk tickets into HelpDesk with original timestamps?
Yes, but only through the HelpDesk POST /v1/importedTickets endpoint. The first message event's date becomes the ticket's createdAt timestamp. The standard POST /v1/tickets endpoint ignores client-supplied dates and stamps the server's current time.
What are the API rate limits for Zendesk and HelpDesk during migration?
Zendesk Support API limits range from 200 req/min (Team) to 2,500 req/min (Enterprise Plus). Incremental exports are capped at 10 req/min. HelpDesk enforces 1,000 requests per 10-minute window per license, shared across all integrations.
Will migrating historical tickets trigger email notifications to customers?
Yes, unless you explicitly suppress them. Disable all automated workflows and auto-responders in HelpDesk before the migration, ensure your API token bypasses outbound email triggers, and run a test batch to verify no SMTP traffic is generated.
How long does a Zendesk to LiveChat migration take?
A small migration (under 5,000 tickets) takes 1–2 weeks. Medium (5,000–50,000) takes 2–5 weeks. Large migrations (50,000+) can take 4–12 weeks. Attachment volume and custom field complexity are the biggest variables.

More from our Blog

Zendesk to Intercom Migration: The 2026 Technical Guide
Migration Guide/Intercom/Zendesk

Zendesk to Intercom Migration: The 2026 Technical Guide

A technical guide to migrating from Zendesk to Intercom — covering data model mismatches, API rate limits, attachment handling, notification traps, and how to choose the right migration method.

Nachi Nachi · · 20 min read