---
title: "Dixa to Zendesk Migration: The CTO's Technical Guide"
slug: dixa-to-zendesk-migration-the-ctos-technical-guide
date: 2026-07-22
author: Rishabh
categories: [Migration Guide, Dixa, Zendesk]
excerpt: "A technical guide to migrating from Dixa to Zendesk: API extraction, data mapping, rate limits, edge cases, and step-by-step implementation."
tldr: "Extract Dixa history via API, load into Zendesk's Ticket Import API with timestamps preserved. Bottlenecks: Dixa's 3 req/min message limit and manual Flows-to-triggers workflow rebuild."
canonical: https://clonepartner.com/blog/dixa-to-zendesk-migration-the-ctos-technical-guide/
---

# Dixa to Zendesk Migration: The CTO's Technical Guide


Migrating from Dixa to Zendesk moves your support operation from a conversation-centric, offer-based routing platform to a ticket-lifecycle, view-based system. Dixa routes conversations in real-time based on agent presence and skills; Zendesk relies on views, triggers, and automations to move tickets through a state machine. This architectural difference means you cannot copy and paste data — you must translate your data model and rebuild your operational workflows.

The data transfer path is well-defined. Dixa's Exports API streams conversations and messages by time range, and Zendesk's Ticket Import API accepts historical tickets with preserved timestamps. The hard part is the workflow redesign: translating Dixa's visual Flow Builder into Zendesk's combination of triggers, automations, views, and SLA policies, and accepting that Dixa's native voice and push-based routing have no direct Zendesk equivalent without additional configuration.

> [!NOTE]
> **TL;DR** Conversation history, contacts, tags, and custom attributes extract cleanly from Dixa via API and load into Zendesk via the Ticket Import API with timestamp preservation. Dixa's Exports API caps at 10 conversation requests per minute and limits each query to a 31-day window — plan extraction accordingly. Zendesk's import endpoint accepts batches of 100 tickets and does not fire triggers or automations on imported records. The workflow redesign (Dixa Flows and Queues → Zendesk triggers, views, and Omnichannel Routing) is the most time-consuming task. Realistic timeline for ~30 agents and 100K conversations: 3–6 weeks including planning, test migration, workflow rebuild, and validation.

For Dixa-side extraction details, see [How to Export Data from Dixa: Methods, API Limits & Data Mapping](https://clonepartner.com/blog/blog/how-to-export-data-from-dixa-methods-api-limits-data-mapping/). For post-migration testing, see [Post-Migration QA: 20 Tests to Run After Your Help Desk Data Migration](https://clonepartner.com/blog/blog/help-desk-data-migration-qa-checklist/).

## Why Teams Migrate from Dixa to Zendesk

Teams move from Dixa to Zendesk for platform-specific reasons, not because one is universally better. The friction points are architectural.

- **Marketplace ecosystem.** Zendesk's marketplace lists over 1,500 apps ([zendesk.com/marketplace](https://www.zendesk.com/marketplace/)). Dixa's integration library is significantly smaller — under 100 native integrations as of 2025. If your stack depends on deep third-party connections (Jira, Salesforce, Shopify analytics), Zendesk covers more ground.
- **Reporting depth.** Zendesk Explore provides custom report building with a drag-and-drop query builder, pre-built dashboards, scheduled delivery, and cross-channel analytics including custom metrics and calculated attributes ([support.zendesk.com/hc/en-us/articles/4408821475098](https://support.zendesk.com/hc/en-us/articles/4408821475098)). Dixa's native reporting supports standard metrics but lacks comparable customization and drill-down capability.
- **Knowledge base maturity.** Zendesk Guide supports categories, sections, community forums, content versioning, and multi-brand knowledge bases. Dixa Knowledge (acquired via Elevio) has fewer content hierarchy features for complex documentation structures.
- **Enterprise compliance.** Zendesk offers FedRAMP LI-SaaS authorization and a HIPAA BAA path on Suite Enterprise and above ([zendesk.com/trust](https://www.zendesk.com/trust/)). Dixa holds SOC 2 Type II and is GDPR-compliant but does not publicly advertise HIPAA compliance or ISO 27001 certification as of mid-2025.
- **Platform consolidation.** When the broader org already runs Zendesk for other teams, maintaining a separate Dixa instance creates data silos, duplicate reporting, and integration overhead.

## Core Architectural Differences

Three design differences make this migration non-trivial:

**Offer-based routing vs. view-based pulling.** Dixa pushes conversations to agents based on real-time availability, skills, and priority scores. Zendesk uses views, groups, and Omnichannel Routing rules to surface work — a fundamentally different approach to workload distribution. Zendesk's Omnichannel Routing (available on Suite Professional and above) can approximate Dixa's push model using auto-routing with agent status and skill-based assignment, but requires explicit configuration of skills, agent unified statuses, and routing rules ([support.zendesk.com/hc/en-us/articles/5066691498650](https://support.zendesk.com/hc/en-us/articles/5066691498650)).

**Visual Flow Builder vs. flat business rules.** Dixa's Flow Builder is a single drag-and-drop canvas handling queue assignment, IVR, auto-replies, priority, and escalation with branching logic. Zendesk distributes the same behavior across triggers (event-based rules that fire on ticket creation or update), automations (time-based rules), SLA policies, groups, views, macros, and Talk settings. There is no automated migration path between these systems. A complex Dixa Flow with 15–20 branches typically translates into 8–15 Zendesk triggers plus 2–4 automations plus SLA policies.

**Native omnichannel vs. add-on voice.** Dixa includes phone, IVR, callback, and recording natively in every plan. Zendesk Talk is a separate product with its own pricing (starting at $49/agent/month for Talk Partner Edition, or usage-based for Zendesk Talk) and configuration layer ([zendesk.com/talk](https://www.zendesk.com/service/voice/)).

## Migration Approaches

There are five viable methods to move data from Dixa to Zendesk. The right choice depends on data volume, engineering bandwidth, and whether you need a one-time transfer or ongoing sync.

### 1. CSV Export / Import

**How it works:** Export conversation data from Dixa's built-in CSV export, restructure the CSV to match Zendesk's bulk import format, and upload via Zendesk Admin Center.

**When to use it:** Small datasets (<5,000 conversations), minimal custom fields, teams without developer resources. Never for full production migrations.

**Pros:** No code required for initial export. Zendesk's UI bulk importer handles up to 2,000 users per upload.

**Cons:** Dixa's CSV export includes conversation metadata but not full message threads — you get summary data, not the complete conversation body. Attachments are lost. Timestamps default to import date unless you use the API. Manual field mapping is error-prone at scale.

**Complexity:** Low

### 2. API-Based Migration

**How it works:** Use Dixa's Exports API ([docs.dixa.io/docs/exports-api](https://docs.dixa.io/docs/exports-api)) and API v1 ([docs.dixa.io/openapi](https://docs.dixa.io/openapi)) to extract conversations, messages, contacts, tags, and custom attributes. Transform the data to match Zendesk's schema. Load into Zendesk using the Ticket Import API ([developer.zendesk.com/api-reference/ticketing/tickets/ticket_import](https://developer.zendesk.com/api-reference/ticketing/tickets/ticket_import/)), Users API, and Organizations API.

**When to use it:** The default choice for most production migrations where you need full message history, timestamp preservation, and attachment migration.

**Pros:** Full control over extraction and transformation. Preserves `created_at`, `updated_at`, and `solved_at` timestamps. Handles attachments, internal notes, tags, and custom fields. Repeatable — run test migrations before cutover.

**Cons:** Requires significant engineering effort (80–160 hours depending on complexity). Dixa's Exports API rate limits are tight: 10 requests/min for conversations, 3 requests/min for messages. Must handle ID mapping, error recovery, and retry logic.

**Complexity:** High

### 3. Third-Party Migration Tools

**How it works:** Services like Help Desk Migration provide a GUI-based wizard that connects to both Dixa and Zendesk via API, maps fields, and transfers data.

**When to use it:** Mid-size migrations (10K–100K conversations) where you want to avoid writing custom code.

**Pros:** Pre-built connectors reduce development time. Visual field mapping. Built-in deduplication and validation.

**Cons:** Per-record pricing can be expensive at scale (typically $1–$5 per 100 records depending on provider and data complexity). Limited control over transformation logic. May not handle edge cases (linked conversations, nested custom attribute hierarchies, call recordings). Verify the vendor uses Dixa API v1, not the deprecated Integrations API.

**Complexity:** Medium

### 4. Custom ETL Pipeline

**How it works:** Extract Dixa data into a data warehouse (e.g., BigQuery, Snowflake), transform with dbt or custom scripts, and load into Zendesk with worker queues and persistent state tables.

**When to use it:** Enterprise volume (500K+ conversations), complex data transformations, regulatory requirements demanding an auditable pipeline, or migrations that also feed BI and archival systems.

**Pros:** Maximum flexibility and control. Auditable transformation logic. Can be reused for ongoing sync or future migrations.

**Cons:** Highest engineering investment (200+ hours). Requires infrastructure setup and maintenance. Overkill for most helpdesk migrations.

**Complexity:** High

### 5. Middleware / Integration Platforms (Zapier, Make)

**How it works:** Use iPaaS platforms to connect Dixa triggers (e.g., conversation closed) to Zendesk actions (create ticket). Event-driven rather than bulk historical.

**When to use it:** Ongoing sync of new conversations during a transition period, or very small historical transfers.

**Pros:** No-code setup. Good for real-time delta sync during a parallel-run cutover.

**Cons:** Not designed for bulk historical migration. Per-task pricing becomes expensive at volume (Zapier charges per task; 100K conversations with 5 messages each = 500K+ tasks). Cannot preserve original timestamps on historical data. Limited error handling and retry logic.

**Complexity:** Low

### Migration Approach Comparison

| Approach | Best For | Timestamp Preservation | Attachments | Engineering Effort | Complexity |
|---|---|---|---|---|---|
| CSV Export/Import | <5K conversations | Requires API | No | Low | Low |
| API-Based | Any volume (default) | Yes | Yes | High (80–160 hrs) | High |
| Third-Party Tools | 10K–100K conversations | Yes | Partial | Low | Medium |
| Custom ETL | >500K conversations | Yes | Yes | Very High (200+ hrs) | High |
| Middleware (Zapier/Make) | Ongoing sync only | No (new records only) | Limited | Low | Low |

### Scenario-Based Recommendations

- **Small business (<10K conversations, no dev team):** Use a third-party migration tool or managed service. The per-record cost is justified by the time saved.
- **Mid-market (10K–200K conversations, some engineering bandwidth):** API-based migration with custom scripts, or a managed migration service.
- **Enterprise (>200K conversations, dedicated dev team):** Custom ETL pipeline or managed service. Dixa's Exports API rate limits make bulk extraction slow — plan for multi-day extraction windows. At 3 req/min for messages with pagination, extracting 500K conversations with an average of 6 messages each can take 40+ hours of continuous API calls.
- **Ongoing sync during transition:** Use Zapier/Make for real-time forwarding of new conversations while historical data migrates via API.

### Estimated Migration Costs

| Scenario | Engineering Hours | Tooling/Service Cost | Zendesk Plan Delta (annual, est.) | Total Estimated Cost |
|---|---|---|---|---|
| Small (<10K convos, third-party tool) | 10–20 hrs | $500–$2,000 | Varies by plan | $2,500–$5,000 |
| Mid-market (50K convos, API-based) | 80–120 hrs | Minimal (hosting) | Varies by plan | $12,000–$24,000 in eng time |
| Enterprise (500K convos, ETL pipeline) | 200–300 hrs | $1,000–$5,000 infra | Varies by plan | $40,000–$60,000+ in eng time |
| Managed service (any volume) | 5–15 hrs internal | $3,000–$15,000 service fee | Varies by plan | $5,000–$20,000 |

*Engineering hours valued at $150/hr (blended rate for mid-senior engineers). Actual costs vary by region, team structure, and data complexity.*

## When to Use a Managed Migration Service

Building a migration script sounds like a weekend project. In practice, handling nested JSON payloads, undocumented API behaviors, and attachment extraction takes weeks of iterative debugging. The real risks are not the happy path — they are the edge cases.

**Risks of DIY migration:**

- **Broken relationships.** Conversations reference contacts by ID. If contacts are not loaded first, or if ID mapping fails, conversations become orphaned. There is no undo button on the Zendesk import API.
- **Silent data loss.** Dixa's export messages endpoint does not include internal notes — those live under `conversation_wrapup_notes` on the conversation object, or require a separate call to `GET /v1/conversations/{id}/notes`. Miss this and you lose all agent context.
- **Rate limit math.** At 3 requests per minute for message export with a 31-day query window, extracting 3 years of data requires dozens of sequential API calls with careful pagination. One malformed request can derail your extraction schedule.
- **Attachment handling.** Each attachment must be downloaded from Dixa, uploaded to Zendesk's Upload API to get a token, then attached to the ticket comment. Upload tokens expire after 60 minutes ([developer.zendesk.com/api-reference/ticketing/tickets/ticket-attachments](https://developer.zendesk.com/api-reference/ticketing/tickets/ticket-attachments/)). This is a separate pipeline with its own failure modes.

**Hidden costs of in-house migration:**

- 80–200+ engineering hours diverted from product work
- 2–3 full test migrations before production is realistic
- Workflow redesign (Dixa Flows → Zendesk triggers/automations) is manual regardless
- Post-migration bug fixing and data patching typically adds 20–40 hours

## Pre-Migration Planning

### Data Audit Checklist

| Data Category | What to Count | Notes |
|---|---|---|
| Conversations | Total count by channel (email, chat, phone, social) | Phone conversations may only contain metadata + recording URLs |
| Messages | Total messages across all conversations | Internal notes are separate from messages |
| End Users (Contacts) | Active and archived contacts | Check for duplicates by email |
| Agents | Active and deactivated agents | Deactivated agents still own historical conversations |
| Tags | Active and deactivated tags | Deactivated tags may still appear on historical conversations |
| Custom Attributes | Conversation-level and end-user-level | Note data types: text, dropdown, number, date |
| Teams & Queues | Team structure and queue routing rules | Queues map to Zendesk Groups + Views |
| Knowledge Base | Articles, categories, sections | Dixa Knowledge → Zendesk Guide is a separate migration |
| Flows | Active Flows and their routing logic | Must be rebuilt manually in Zendesk |
| Attachments | Estimate total size | Zendesk caps at 50MB per attachment for most plans |

### Define Migration Scope

Not everything needs to migrate. Common exclusions:

- **Abandoned conversations** with no agent response — often 20–40% of chat volume
- **Test conversations** from staging environments
- **Spam / junk** conversations already filtered by Dixa
- **Conversations older than N years** — check your data retention policy and any contractual or regulatory retention requirements
- **Inactive users** who have not submitted a ticket in 2+ years

Reducing payload size speeds up the migration, simplifies QA, and lowers Zendesk storage costs.

### GDPR and Data Residency Considerations

Moving customer data between two SaaS platforms has compliance implications:

- **Data Processing Agreements (DPAs).** Ensure you have valid DPAs with both Dixa and Zendesk. Zendesk's DPA is available at [zendesk.com/company/privacy-and-data-protection](https://www.zendesk.com/company/privacy-and-data-protection/). Dixa's DPA is available upon request.
- **Data residency.** Dixa hosts data in the EU (AWS eu-west-1). Zendesk offers regional data hosting in the US, EU (Germany), and Australia on Suite Enterprise plans with the Advanced Data Privacy and Protection add-on ([zendesk.com/trust](https://www.zendesk.com/trust/)). If you are migrating from EU-hosted Dixa to a US-hosted Zendesk instance, this constitutes a cross-border data transfer requiring appropriate safeguards (Standard Contractual Clauses or adequacy decisions).
- **Right to deletion.** If any data subjects have pending or fulfilled deletion requests in Dixa, verify those records are excluded from the migration payload. Importing previously deleted personal data into Zendesk creates a GDPR violation.
- **Data minimization.** The migration is an opportunity to purge data you no longer need. Migrating 5 years of conversation history when your retention policy is 3 years is unnecessary and increases compliance surface area.
- **Temporary storage.** If your ETL pipeline stores extracted data in an intermediate location (local disk, S3 bucket, data warehouse), that storage location must also comply with your DPA and data residency requirements. Encrypt data at rest and delete intermediate files after migration validation.

### Migration Strategy

| Strategy | Best For | Risk Level |
|---|---|---|
| **Big bang** | <50K conversations, small teams, weekend cutover window | Medium — all-or-nothing |
| **Phased** | Large datasets, multiple teams/brands | Low — migrate by channel or team, but requires coordination to prevent data silos |
| **Incremental** | Active environments with high daily volume | Low — historical first, validate, then delta sync |

For most Dixa-to-Zendesk migrations, **incremental** is the safest approach: load historical data first, validate, then run a delta migration for conversations created between the first load and cutover.

## Data Model & Object Mapping

Dixa and Zendesk use fundamentally different data models. Dixa is conversation-centric with a flat structure. Zendesk is ticket-centric with nested relationships (organizations → users → tickets → comments).

### Object-Level Mapping

| Dixa Object | Zendesk Equivalent | Notes |
|---|---|---|
| Conversation | Ticket | 1:1 mapping. Status maps to ticket status. |
| End User | User (end-user role) | Match on email. Create if not exists. |
| Agent | User (agent role) | Must exist in Zendesk before ticket import. Map Dixa agent roles to Zendesk roles: Agent, Admin, or Light Agent (read-only, available on Suite Growth+). |
| Company / Account | Organization | Normalize name, domains, custom attributes. |
| Team | Group | Similar purpose, different routing model. |
| Queue | Group + View + Omnichannel Routing Rule | Dixa queues combine routing + visibility + priority. Zendesk separates these into three distinct configuration layers. |
| Tag | Tag | Dixa tags may have spaces and colors; Zendesk tags are plain text, lowercase with underscores. |
| Custom Attribute (Conversation) | Custom Ticket Field | Type mapping required (see below). |
| Custom Attribute (End User) | Custom User Field | Same type mapping. |
| Message (inbound) | Ticket Comment (public, author = requester) | Preserve `created_at`. |
| Message (outbound) | Ticket Comment (public, author = agent) | Agent must exist as Zendesk user. |
| Internal Note / Wrap-up Note | Ticket Comment (private) | Wrap-up notes live on the conversation object, not in messages. |
| Conversation Rating | Ticket Satisfaction Rating | Zendesk CSAT is binary (good/bad); Dixa may use different scales. |
| Flow | Triggers + Automations + SLA Policies + Omnichannel Routing Config | No automated migration path. Manual rebuild required. |
| Knowledge Article | Zendesk Guide Article | Separate migration project. |

### Dixa Agent Roles → Zendesk Roles

| Dixa Role | Zendesk Equivalent | Notes |
|---|---|---|
| Admin | Admin | Full configuration access |
| Agent | Agent | Standard ticket handling |
| Agent (read-only / limited) | Light Agent or Contributor | Light Agents can add private comments but cannot be assigned tickets. Available on Suite Growth and above. Contributor role replaces Light Agent on some newer plans. |

### Field-Level Mapping

| Dixa Field | Zendesk Field | Type | Transformation |
|---|---|---|---|
| `conversation.id` (csid) | `ticket.external_id` | String | Store for traceability and delta syncs |
| `conversation.created_at` | `ticket.created_at` | DateTime | ISO 8601 — pass via Ticket Import API |
| `conversation.status` | `ticket.status` | Enum | Map: open→open, pending→pending, closed→solved |
| `conversation.channel` | `ticket.via.channel` | Enum | widget_chat→chat, phone→voice, email→email |
| `conversation.requester_id` | `ticket.requester_id` | Integer | Requires ID mapping table |
| `conversation.assigned_to` | `ticket.assignee_id` | Integer | Requires agent ID mapping |
| `conversation.queue_id` | `ticket.group_id` | Integer | Requires queue→group mapping |
| `conversation.tags []` | `ticket.tags []` | String [] | Lowercase, replace spaces with underscores |
| `conversation.customAttributes{}` | `ticket.custom_fields []` | Object→Array | Map attribute UUID → Zendesk field ID |
| `message.content.value` | `comment.body` or `comment.html_body` | String | Handle HTML vs plain text |
| `conversation_wrapup_notes` | Comment (private) | String | Create as last private comment |
| End User `displayName` | User `name` | String | Direct mapping |
| End User `email` | User `email` | String | Primary deduplication key |
| Rating `score` | Satisfaction Rating | Enum | Map to good/bad binary |

> [!WARNING]
> **Critical:** Dixa's Exports API message endpoint does not contain internal notes. Wrap-up notes are found under `conversation_wrapup_notes` on the conversation object, or via `GET /v1/conversations/{id}/notes`. If your extraction script only pulls from the messages endpoint, you will lose all internal agent notes.

### Custom Attribute Type Mapping

| Dixa Type | Zendesk Type | Notes |
|---|---|---|
| Text | Text | Direct mapping |
| Dropdown (single select) | Drop-down | Recreate all option values in Zendesk first |
| Dropdown (nested) | Drop-down | Zendesk does not support nested dropdowns — flatten to single level (e.g., "Payment - Card - Visa") |
| Number | Decimal or Integer | Choose based on whether decimals are needed |
| Date | Date | Verify format compatibility |
| Boolean | Checkbox | Map true/false |

### Zendesk Custom Objects

If you built complex relational data in Dixa that does not map to standard ticket, user, or organization fields, you may need Zendesk Custom Objects (Sunshine). Be aware of plan-level limits: 3/5/30/50 custom objects by plan, 100 fields per object, 5–10 lookup fields per object, and 32 KB per record. Sandboxes do not copy custom object records or lookup-based triggers automatically — seed them deliberately during testing. Legacy custom objects are being removed starting July 27, 2026; use the new custom objects platform only. ([developer.zendesk.com/api-reference/custom-data/introduction/](https://developer.zendesk.com/api-reference/custom-data/introduction/))

> [!WARNING]
> **Zendesk Sell is being retired.** Zendesk announced on June 19, 2026 that Sell will retire on August 31, 2027. If your migration plan includes CRM data going to Zendesk Sell, consider alternative targets. Companies, leads, and deals are Sell-specific objects — treat Support and Sell as separate scoping exercises. ([support.zendesk.com](https://support.zendesk.com/hc/en-us/articles/9591462550042-Announcing-the-retiring-of-Zendesk-Sell))

## Migration Architecture

Your migration infrastructure must handle Extract, Transform, and Load phases independently to allow for failure recovery at each stage.

```
┌─────────────┐     ┌──────────────┐     ┌─────────────┐
│   DIXA       │────▶│  TRANSFORM   │────▶│  ZENDESK    │
│              │     │              │     │             │
│ Exports API  │     │ ID mapping   │     │ Users API   │
│ Dixa API v1  │     │ Field mapping│     │ Orgs API    │
│              │     │ Type convert │     │ Ticket      │
│              │     │ Dedup        │     │ Import API  │
└─────────────┘     └──────────────┘     └─────────────┘
```

### Dixa API Extraction Details

**Exports API** (for bulk conversation/message extraction):
- Host: `exports.dixa.io`
- Rate limit: Conversations 10 req/min, Messages 3 req/min
- Query constraint: each request spans max 31 days (use `_after` and `_before` parameters)
- Returns streamed JSON arrays
- Does **not** include internal notes
- Documentation: [docs.dixa.io/docs/exports-api](https://docs.dixa.io/docs/exports-api)

**Dixa API v1** (for contacts, tags, custom attributes, agents):
- Host: `dev.dixa.io`
- Rate limit: 10 requests/second per token with a burst allowance of 4, daily ceiling of 864,000 per token
- Authentication: Bearer token (organization-scoped)
- Pagination: cursor-based with `pageToken` and `limit` (max 100 per page)
- No `Retry-After` header on 429 responses — implement your own exponential backoff
- Documentation: [docs.dixa.io/openapi](https://docs.dixa.io/openapi)

### Extraction Throughput Benchmarks

| Dataset Size | Extraction Component | Estimated Duration | Bottleneck |
|---|---|---|---|
| 10K conversations | Conversations export | ~17 minutes | 10 req/min limit |
| 10K conversations | Messages export (avg 5 msgs/convo) | ~2.8 hours | 3 req/min limit, pagination |
| 100K conversations | Conversations export | ~2.8 hours | 10 req/min limit |
| 100K conversations | Messages export | ~28 hours | 3 req/min limit |
| 500K conversations | Conversations export | ~14 hours | 10 req/min limit |
| 500K conversations | Messages export | ~5.8 days | 3 req/min limit |

*Estimates assume single-token extraction, average 5 messages per conversation, and no errors requiring retries. Actual times will be higher due to pagination overhead, 429 retries, and network latency. Using multiple API tokens (if available) can parallelize extraction.*

### Zendesk API Loading Details

**Ticket Import API:**
- Endpoint: `POST /api/v2/imports/tickets/create_many` ([developer.zendesk.com/api-reference/ticketing/tickets/ticket_import](https://developer.zendesk.com/api-reference/ticketing/tickets/ticket_import/))
- Batch size: up to 100 tickets per request
- Preserves `created_at`, `updated_at`, `solved_at`, and per-comment `created_at`
- Does **not** fire triggers or automations on imported tickets
- No notifications sent to customers or CC'd users on import
- Comments with empty bodies are rejected — add placeholder text like `"(Attachment only)"`
- Closed historical tickets can use `archive_immediately` to skip the active ticket pool on very large imports

**Do not use the standard Tickets API for historical imports.** The standard API overwrites creation dates with the import date, fires triggers, and sends email notifications to customers about years-old closed tickets.

**Zendesk rate limits by plan** ([developer.zendesk.com/api-reference/introduction/rate-limits](https://developer.zendesk.com/api-reference/introduction/rate-limits/)):

| Zendesk Plan | Rate Limit (req/min) |
|---|---|
| Team | 200 |
| Growth | 400 |
| Professional | 400 |
| Enterprise | 700 |
| Enterprise Plus | 2,500 |

Zendesk enforces a 30-job concurrent limit for bulk operations. If you exceed rate limits, Zendesk returns a `429 Too Many Requests` error with a `Retry-After` header — your script must detect this, sleep for the requested duration, and retry.

> [!TIP]
> **Throughput math:** At 700 req/min (Enterprise) with 100 tickets per batch, you can theoretically import 70,000 tickets per minute. In practice, factor in user creation, attachment uploads, and error handling — realistic throughput is 5,000–15,000 tickets per hour.

### Common Error Responses

When building your migration script, handle these specific failure modes:

**Zendesk 422 (Unprocessable Entity) — empty comment body:**
```json
{
  "error": "RecordInvalid",
  "description": "Record validation errors",
  "details": {
    "base": [{"description": "Comment body is empty", "error": "BlankValue"}]
  }
}
```
*Fix: Add placeholder text like `"(Attachment only)"` to comment bodies that contain only attachments.*

**Zendesk 422 — missing requester:**
```json
{
  "error": "RecordInvalid",
  "description": "Record validation errors",
  "details": {
    "requester_id": [{"description": "Requester not found", "error": "InvalidValue"}]
  }
}
```
*Fix: Ensure all users are loaded (Step 2) before ticket import. Check your ID mapping table for gaps.*

**Dixa 429 (Rate Limited) — no Retry-After header:**
```json
{
  "error": "rate_limit_exceeded",
  "message": "Too many requests"
}
```
*Fix: Dixa does not include a `Retry-After` header. Implement exponential backoff starting at 2 seconds, doubling on each retry, with a maximum of 5 retries.*

**Zendesk 429 — with Retry-After:**
```
HTTP/1.1 429 Too Many Requests
Retry-After: 42

{"error": {"title": "Too Many Requests", "message": "You have exceeded the rate limit..."}}
```
*Fix: Read the `Retry-After` header value and sleep for that many seconds before retrying.*

### Authentication: Zendesk OAuth Timeline

Zendesk is deprecating API token authentication. The timeline: automatic token deactivation begins **July 28, 2026**, new API token creation is blocked **October 27, 2026**, and remaining API tokens are permanently deactivated **April 30, 2027**. Plan your migration to use OAuth. If you use client-credentials OAuth, actions are attributed to the user who created the OAuth client — use a dedicated service account. ([developer.zendesk.com/documentation/api-basics/authentication/oauth-migration/](https://developer.zendesk.com/documentation/api-basics/authentication/oauth-migration/))

## Step-by-Step Migration Process

### Step 1: Set Up Zendesk Target Environment

Before loading any data:

1. Create all **custom ticket fields** and **custom user fields** in Zendesk. Record their numeric IDs.
2. Create **groups** that map to Dixa queues.
3. Create **agent accounts** — agents must exist before you can assign tickets to them. Map Dixa agent roles to Zendesk roles (Admin, Agent, Light Agent/Contributor).
4. **Provision a Zendesk Sandbox** for test migrations. Sandboxes are available on Suite Professional and above. On Professional plans, sandboxes have a 10K ticket limit and refresh weekly; Enterprise sandboxes support up to 100K tickets. Premium Sandboxes (Enterprise+) persist data and support longer test cycles ([support.zendesk.com/hc/en-us/articles/4408832153114](https://support.zendesk.com/hc/en-us/articles/4408832153114)). Note: sandbox refreshes overwrite all data — complete each test cycle before the next refresh.
5. Generate API credentials (OAuth preferred, noting the deprecation timeline above).

### Step 2: Extract and Load Users

Tickets cannot exist without requesters. Extract all Dixa End Users via the API v1 `GET /v1/endusers` endpoint with cursor-based pagination, then load them into Zendesk.

```python
import requests
import time

DIXA_TOKEN = "your_dixa_api_token"
BASE_URL = "https://dev.dixa.io/v1"

def extract_end_users():
    users = []
    page_token = None
    retries = 0
    while True:
        params = {"limit": 100}
        if page_token:
            params["pageToken"] = page_token
        resp = requests.get(
            f"{BASE_URL}/endusers",
            headers={"Authorization": f"Bearer {DIXA_TOKEN}"},
            params=params
        )
        if resp.status_code == 429:
            wait = min(2 ** retries, 60)  # Exponential backoff, max 60s
            time.sleep(wait)
            retries += 1
            if retries > 5:
                raise Exception("Max retries exceeded on Dixa API")
            continue
        resp.raise_for_status()
        retries = 0
        data = resp.json()
        users.extend(data.get("data", []))
        page_token = data.get("nextPageToken")
        if not page_token:
            break
    return users
```

Load users into Zendesk using `POST /api/v2/users/create_or_update_many` (100 users per batch). Store the mapping of `Dixa_User_ID → Zendesk_User_ID` in a persistent store (Redis, SQLite, or a database table) for fast lookups during ticket creation.

Zendesk's bulk user import may not be enabled by default on all accounts — it can return 403 until the account owner requests activation from Zendesk Support.

### Step 3: Extract Conversations and Messages

The Exports API requires time-bounded queries with a maximum 31-day window. Loop through your data range in monthly chunks.

```python
from datetime import datetime, timedelta

def extract_conversations(start_date, end_date):
    all_conversations = []
    current = start_date
    while current < end_date:
        window_end = min(current + timedelta(days=31), end_date)
        resp = requests.get(
            "https://exports.dixa.io/v1/conversation_export",
            headers={"Authorization": f"Bearer {DIXA_TOKEN}"},
            params={
                "_after": current.strftime("%Y-%m-%d"),
                "_before": window_end.strftime("%Y-%m-%d")
            }
        )
        if resp.status_code == 429:
            time.sleep(10)
            continue
        resp.raise_for_status()
        all_conversations.extend(resp.json())
        current = window_end
        time.sleep(6)  # Respect 10 req/min limit
    return all_conversations
```

For each conversation, fetch full message threads via the Dixa API v1, and separately fetch internal notes:

```python
def get_messages(conversation_id):
    resp = requests.get(
        f"{BASE_URL}/conversations/{conversation_id}/messages",
        headers={"Authorization": f"Bearer {DIXA_TOKEN}"}
    )
    resp.raise_for_status()
    return resp.json().get("data", [])

def get_notes(conversation_id):
    resp = requests.get(
        f"{BASE_URL}/conversations/{conversation_id}/notes",
        headers={"Authorization": f"Bearer {DIXA_TOKEN}"}
    )
    resp.raise_for_status()
    return resp.json().get("data", [])
```

Store raw JSON payloads locally before transforming. Do not transform in flight — this allows recovery if the transform step fails.

### Step 4: Handle Attachments

Zendesk requires attachments to be uploaded before the ticket comment is created.

1. Download the file from the Dixa URL (private files require authenticated access).
2. `POST` the binary data to Zendesk `api/v2/uploads?filename=example.png`.
3. Save the returned `upload_token`.

Upload tokens expire after **60 minutes** ([developer.zendesk.com/api-reference/ticketing/tickets/ticket-attachments](https://developer.zendesk.com/api-reference/ticketing/tickets/ticket-attachments/)), so time your uploads close to ticket creation. Zendesk attachment size limit is **50MB** per file — larger files (e.g., call recordings) should be hosted externally and linked from the ticket.

### Step 5: Transform and Import Tickets

Using your locally stored user mappings and upload tokens, construct the ticket payload and push to Zendesk via the Ticket Import API.

```python
ZENDESK_URL = "https://yoursubdomain.zendesk.com/api/v2/imports/tickets/create_many"
HEADERS = {"Content-Type": "application/json"}
AUTH = ("admin@company.com/token", "your_api_token")

# Example single ticket payload (batch up to 100)
ticket = {
    "ticket": {
        "requester_id": 123456789,   # Resolved from Step 2
        "assignee_id": 987654321,    # Resolved from Step 2
        "subject": "Historical Dixa Conversation",
        "external_id": "dixa-conv-abc123",
        "created_at": "2023-01-15T10:00:00Z",
        "status": "solved",
        "tags": ["imported_from_dixa", "billing_question"],
        "comments": [
            {
                "author_id": 123456789,
                "value": "I need help with my account.",
                "created_at": "2023-01-15T10:00:00Z",
                "public": True
            },
            {
                "author_id": 987654321,
                "value": "Fixed that for you.",
                "created_at": "2023-01-15T10:15:00Z",
                "public": True,
                "uploads": ["upload_token_from_step_4"]
            }
        ]
    }
}
```

Tag every imported ticket with `imported_from_dixa` — this enables validation queries, reporting exclusions, and rollback via bulk deletion if needed.

### Step 6: Delta Sync

Run the extraction process again on cutover day, querying Dixa only for conversations created or updated since your initial extraction timestamp. The `external_id` field (populated with the original Dixa Conversation ID) makes delta syncs and deduplication straightforward.

### Step 7: Validate

After import, run validation checks before declaring the migration complete. See the full validation framework below.

## Omnichannel Routing: Translating Dixa Queues

Dixa's queue-based routing is the hardest workflow component to translate. Here is how the concepts map:

### Dixa Queue → Zendesk Omnichannel Routing

| Dixa Queue Concept | Zendesk Equivalent | Configuration Location |
|---|---|---|
| Queue (skill-based assignment) | Omnichannel Routing with skills | Admin Center → Objects and rules → Omnichannel routing |
| Agent skills/competencies | Skills (up to 10 per agent on Enterprise) | Admin Center → People → Skills |
| Queue priority order | Routing priority (urgent/high/normal/low mapped to ticket priority) | Ticket priority field + routing configuration |
| Agent availability/presence | Unified agent statuses | Admin Center → People → Agent statuses |
| Queue capacity limits | Omnichannel capacity rules (max tickets per agent per channel) | Admin Center → Objects and rules → Capacity rules |
| Queue overflow/fallback | Routing rules with fallback groups | Trigger-based group reassignment on SLA breach |

### Configuration Steps

1. **Enable Omnichannel Routing** in Admin Center → Objects and rules → Omnichannel routing. Available on Suite Professional and above.
2. **Define skills** that match your Dixa queue competencies (e.g., "billing," "technical," "spanish-language"). Assign skills to agents.
3. **Create routing rules** that match ticket attributes (tags, custom fields, channel) to required skills. This replaces Dixa's Flow-based queue assignment.
4. **Set capacity rules** per channel: e.g., max 4 chats, 1 phone call, 12 emails simultaneously per agent.
5. **Configure unified agent statuses** to map Dixa's presence states (available, away, offline) to Zendesk statuses.
6. **Set up SLA policies** with response and resolution targets by priority and group, replacing Dixa's queue-level SLA settings.

> [!WARNING]
> **Key difference:** Dixa's offer-based routing presents one conversation at a time and waits for agent acceptance. Zendesk's Omnichannel Routing auto-assigns tickets to agents based on availability and capacity — there is no accept/reject step. This changes agent behavior and may require training to prevent cherry-picking via views.

### SLA Migration

Imported historical tickets do not receive SLA metrics in Zendesk. SLA policies only apply to tickets created after the policy is activated. This means:

- Historical first-response-time and resolution-time data from Dixa is not available in Zendesk Explore
- If you need historical SLA reporting, export it from Dixa before decommissioning and store it separately (e.g., in a BI tool or data warehouse)
- New SLA policies should be configured and tested in the sandbox before cutover

## Edge Cases & Challenges

### Phone Conversations

Dixa phone conversations contain call metadata (duration, recording URL, IVR path) but no text body. Create a ticket with a system note containing structured call metadata (duration, caller number, IVR selections). For call recordings:

- **If recordings are <50MB:** Download from Dixa, upload to Zendesk as attachments.
- **If recordings are >50MB:** Host on S3, GCS, or your existing storage with appropriate access controls and retention policies. Add the URL as a private comment on the ticket.
- **Retention:** Set bucket lifecycle policies matching your call recording retention requirements (typically 90 days to 7 years depending on jurisdiction and industry).
- **Zendesk Talk recordings** are stored separately from ticket attachments and have their own retention settings — imported call recordings attached to tickets behave differently from native Talk recordings.

### Linked Conversations

Dixa supports linking conversations to parent conversations. Zendesk has no native equivalent. Options:

1. Store the parent conversation ID in a custom field (simplest)
2. Use Zendesk's side conversation feature as an approximation (Suite Professional+)
3. Add a private comment with a link to the related ticket using the `external_id` to look up the parent

### Duplicate Contacts

A single customer may exist in Dixa under multiple emails or phone numbers, while Zendesk matching is email-led. Define your match precedence before the first import. Use Zendesk's `create_or_update` endpoint with email as the matching key to deduplicate during import. For contacts with phone numbers but no email, create them with a placeholder identity and merge manually post-migration.

### Nested Custom Attribute Dropdowns

Dixa supports nested dropdown options (e.g., "Payment → Card → Visa"). Zendesk dropdown fields are single-level only. Two approaches:

1. **Concatenate levels:** "Payment - Card - Visa" in a single dropdown. Works if you have <200 total options (Zendesk's per-field option limit).
2. **Split into multiple fields:** "Category" (Payment), "Subcategory" (Card), "Detail" (Visa). More structured but requires three custom fields instead of one.

### Conversation Ratings

Dixa's satisfaction ratings may use a different scale than Zendesk's binary good/bad CSAT. Map scores ≥4 (on a 5-point scale) to "good" and <4 to "bad," or store the original numeric score in a custom field to preserve granularity. Document the mapping logic for future reporting accuracy.

### Empty Comment Bodies

The Zendesk Ticket Import API rejects comments with empty bodies — even though Zendesk's own UI allows them (e.g., attachment-only messages). Add placeholder text like `"(Attachment only)"` for these cases. See the error response example above.

### Deactivated and Suspended Users

Dixa conversations may be assigned to agents who are no longer active. These agents must exist in Zendesk (can be suspended) before import, or the `assignee_id` reference will fail. If Dixa contains deleted users that cannot be created in Zendesk, map them to a generic "Deactivated Agent" account and tag the ticket for manual review.

### Inline Images

Images embedded directly in the HTML of a message body (not attached as files) will break if the Dixa source URL expires. Parse the HTML, download each image, upload it to Zendesk's Upload API, and rewrite the `src` tag in the HTML payload to use the new Zendesk URL. This is a separate extraction pipeline — budget 8–16 hours of engineering time if your conversations frequently contain inline images.

### Multi-Channel Threads

Dixa allows switching channels (e.g., from email to chat) within a single conversation. Zendesk tickets are generally bound to a single primary channel (set via `ticket.via`). Append channel metadata to the comment body or store it in a custom field to preserve this context. Example: add `[via chat]` prefix to comments that originated on a different channel than the ticket's primary channel.

## Limitations & Constraints

| Constraint | Impact |
|---|---|
| Dixa Exports API: 31-day max query window | Multi-year extractions require dozens of sequential API calls |
| Dixa Exports API: 3 req/min for messages | Message extraction is the bottleneck — 200K conversations may take 28+ hours |
| Dixa does not send `Retry-After` on 429 | Must implement custom exponential backoff |
| Zendesk import: 100 tickets per batch | Fine for most volumes, adds overhead for 1M+ ticket migrations |
| Zendesk import: no trigger execution | Post-import automations will not fire — run manual workflows if needed |
| Zendesk import: no SLA/metric history | Imported tickets do not receive SLA tracking — export historical SLA data from Dixa separately |
| Zendesk CSAT: binary only | Dixa's richer rating data loses granularity unless stored in a custom field |
| Zendesk offset pagination: 10K record cap | Use cursor pagination — offset pagination returns 400 past 10K records ([developer.zendesk.com/api-reference/introduction/pagination](https://developer.zendesk.com/api-reference/introduction/pagination/)) |
| Dixa Flows → Zendesk triggers: no migration path | Manual rebuild required — budget 20–40 hours for complex Flow configurations |
| Dixa Knowledge → Zendesk Guide | Separate migration project with its own mapping challenges |
| Zendesk API token deprecation | API tokens being phased out starting July 2026 — use OAuth |
| Zendesk attachment limit: 50MB per file | Call recordings or large files must be hosted externally |
| Zendesk dropdown options: 200 per field | Flattened nested dropdowns may hit this limit |

## Validation & Testing

A 201 HTTP response confirms the record was accepted — not that the data is correct or complete.

### Validation Framework

1. **Record count reconciliation:** Compare Dixa conversation count (by status, by channel) against Zendesk ticket count with `imported_from_dixa` tag. Tolerance: 0% variance — every conversation should be accounted for (migrated, excluded by scope, or logged as error).
2. **Field-level validation:** For a random sample of 100+ tickets, compare every mapped field — status, assignee, requester, timestamps, tags, custom fields — against the Dixa source. Automate this with a script that reads both APIs and diffs the values.
3. **Comment threading:** Verify message count per ticket and chronological ordering for a sample set. Check that `created_at` timestamps on comments match the source within 1 second.
4. **Attachment verification:** Download and verify file sizes and counts match on sample tickets. Check for broken inline image URLs.
5. **Agent assignment check:** Verify assigned agents in Zendesk match the original Dixa assignment. Flag any tickets assigned to the "Deactivated Agent" placeholder.
6. **Private note integrity:** Confirm internal notes (including wrap-up notes) migrated and are marked private. Verify they are not visible to end-users.
7. **Custom field values:** Verify dropdown values, dates, and numeric fields transferred correctly. Check for empty custom fields that should have values.

### Test Migration Protocol

Run at least two full test migrations before production:

- **Test 1:** Small subset (1,000 conversations). Validate schema mapping, identify field-level issues. Use your Zendesk sandbox. Expected duration: 1–2 days.
- **Test 2:** Full dataset on a Zendesk sandbox. Validate at scale, measure timing, identify rate limit bottlenecks. Expected duration: 3–5 days including extraction.
- **Production:** Apply lessons from tests. Run during low-traffic hours (typically weekends or overnight). Have rollback plan ready.

### Rollback Planning

Zendesk's Ticket Import API creates new records — there is no built-in rollback. Mitigate this:

- Tag all imported tickets with `imported_from_dixa`
- If rollback is needed, bulk-delete tickets by tag via the Zendesk API (`DELETE /api/v2/tickets/destroy_many?ids=1,2,3` — batches of 100)
- Keep Dixa in read-only mode during transition — do not decommission until validation passes
- Document the rollback procedure and test it during Test 1

For a complete testing framework, review our [Post-Migration QA Checklist](https://clonepartner.com/blog/blog/help-desk-data-migration-qa-checklist/).

## Post-Migration Tasks

Data migration is half the project. Once the data is in Zendesk, you must configure the operational layer.

### Rebuild Workflows

Dixa Flows do not migrate. You must manually recreate:

- **Triggers** (based on ticket creation/update conditions) — replacing Dixa Flow branches that fire on conversation events
- **Automations** (time-based actions) — replacing Dixa Flow timeout and escalation logic
- **SLA policies** (response time targets by priority/group) — replacing Dixa's queue-level SLA settings
- **Views** (agent-facing filtered ticket lists replacing Dixa queues)
- **Macros** (replacing Dixa quick responses/canned replies)
- **Omnichannel Routing rules** (replacing Dixa's offer-based queue assignment — see section above)

### Knowledge Base Migration

If migrating Dixa Knowledge to Zendesk Guide, treat it as a separate project. Content and hierarchy must be restructured. Key considerations: category/section mapping, article URL redirects, embedded image re-hosting, and multi-language content. See [Document360 to Zendesk Guide Migration](https://clonepartner.com/blog/blog/document360-to-zendesk-guide-migration-the-ctos-technical-guide/) for comparable KB migration patterns.

### User Training

- Agents need training on Zendesk's view-based workflow (vs. Dixa's offer-based routing). Key behavioral change: Zendesk auto-assigns via Omnichannel Routing rather than presenting conversations for acceptance.
- Admins need training on trigger/automation creation (vs. Dixa's visual Flow Builder). Budget 4–8 hours for admin training.
- Reporting users need orientation to Zendesk Explore (vs. Dixa Analytics). Explore uses a different query model — pre-built dashboards cover common metrics, but custom reports require learning the Explore query builder.

### Post-Migration Monitoring

Monitor for 2–4 weeks after cutover:

- Ticket creation rates (ensure nothing is being dropped)
- Agent assignment distribution (verify Omnichannel Routing is distributing equitably)
- Custom field population rates (low rates may indicate UI confusion or mapping errors)
- Suspended Tickets view (catch misconfigured email forwarding — this is the #1 post-migration issue)
- CSAT score trends (baseline comparison against Dixa historical averages)
- Broken attachment links and requester mismatches
- SLA breach rates (compare against Dixa baselines once sufficient new-ticket data accumulates)

### Update External Links

If your application links to specific Dixa knowledge base URLs, set up 301 redirects to the new Zendesk Guide URLs. Create a redirect mapping table before decommissioning Dixa Knowledge.

## Best Practices

1. **Back up everything first.** Export a full Dixa data dump before starting. Store it independently of both platforms in a location that meets your data residency requirements.
2. **Always sandbox first.** Run a full extraction and load tickets into a Zendesk Sandbox environment before touching production. Know your sandbox's ticket limit and refresh schedule.
3. **Create an ID mapping table.** Persist every Dixa ID → Zendesk ID mapping. You need it for validation, debugging, delta syncs, and post-migration patching.
4. **Tag imported records.** Add `imported_from_dixa` to every ticket. This enables validation queries, reporting exclusions, and rollback.
5. **Migrate contacts before conversations.** Zendesk requires valid `requester_id` and `assignee_id` references. Load users first, build the ID map, then load tickets.
6. **Handle the message export bottleneck.** Dixa's 3 req/min message export limit is the slowest part of extraction. Start this process days before your planned cutover.
7. **Freeze Dixa configuration.** Impose a change freeze on Dixa tags, custom fields, and agent roles two weeks before the migration.
8. **Don't migrate everything.** Abandoned conversations, spam, and test data add noise. Define scope filters early.
9. **Preserve Dixa access post-cutover.** Keep Dixa in read-only mode for 30–90 days so agents can reference conversations that may not have migrated cleanly.
10. **Separate history migration from workflow redesign** in your project plan. They are different workstreams with different owners.
11. **Validate incrementally** after every batch instead of waiting for final cutover.
12. **Run a pilot batch with real, messy records** — not clean demo data. The first test always surfaces mapping issues you did not anticipate.

## Automation Script Structure

High-level directory structure for a production API-based migration:

```text
extract/
  dixa_conversations.py
  dixa_messages.py
  dixa_notes.py
  dixa_files.py

transform/
  map_orgs.py
  map_users.py
  map_tickets.py
  normalize_tags.py
  build_crosswalk.py

load/
  zendesk_orgs.py
  zendesk_users.py
  zendesk_uploads.py
  zendesk_ticket_import.py
  poll_jobs.py

qa/
  counts.py
  field_diff.py
  attachment_check.py
  uat_samples.py

state/
  id_map.sqlite
  dead_letter.jsonl
  import_batches.json
```

> [!TIP]
> This is a structural outline. A production implementation needs retry logic with exponential backoff, persistent state tracking (so you can resume after failures), concurrent extraction where rate limits allow, and comprehensive error logging. Budget 2–3 weeks of engineering time for a production-grade implementation.

## Making the Right Call

A Dixa-to-Zendesk migration is a well-defined, moderate-complexity project. The data transfer path is clear: Dixa's APIs export cleanly, and Zendesk's Ticket Import API is purpose-built for historical ingestion. The challenges are the Dixa Exports API rate limits (which make extraction slow for large datasets — 100K conversations takes roughly 28+ hours for message extraction alone), the workflow redesign (which is entirely manual and typically requires 20–40 hours for complex Flow configurations), and the edge cases that surface only during test migrations — phone conversations without text bodies, nested dropdown flattening, empty comment bodies, inline image URL expiration, and deactivated agent references.

For teams with engineering bandwidth and <50K conversations, a custom API-based migration is achievable in 2–4 weeks. For larger datasets, complex Flow configurations, or tight timelines, a managed service compresses the timeline and reduces engineering risk.

For more on Zendesk migration planning, see [Zendesk Migration Checklist](https://clonepartner.com/blog/blog/zendesk-migration-checklist/) and [Best Zendesk Migration Service Providers in 2026](https://clonepartner.com/blog/blog/best-zendesk-migration-service-providers-in-2026-compared/).

## Frequently asked questions

### How long does a Dixa to Zendesk migration take?

For ~100K conversations, expect 3–6 weeks total: 1 week for planning and data audit, 1–2 weeks for test migrations and field mapping, and 1–2 weeks for production migration and validation. The Dixa Exports API rate limit (3 req/min for messages) is the primary time constraint for data extraction.

### Can I preserve timestamps when migrating from Dixa to Zendesk?

Yes. Zendesk's Ticket Import API (POST /api/v2/imports/tickets/create_many) lets you set created_at, updated_at, solved_at on tickets and created_at on individual comments. The standard ticket creation API does not support this — you must use the import endpoint.

### Does Zendesk run triggers on imported tickets?

No. Tickets created via the Ticket Import API do not fire triggers, automations, or notifications. This is by design and prevents duplicate emails during migration. Triggers only resume on subsequent updates to imported tickets that are not in closed status.

### What Dixa data cannot be migrated to Zendesk?

Dixa Flows (routing logic) have no automated migration path and must be rebuilt as Zendesk triggers, automations, and SLA policies. Call recordings require external hosting. Nested custom attribute dropdowns must be flattened. Dixa's satisfaction rating granularity may be lost since Zendesk uses binary good/bad CSAT.

### What are the Dixa API rate limits for data export?

The Dixa Exports API allows 10 requests per minute for conversations and 3 requests per minute for messages, with each query limited to a 31-day window. The Dixa API v1 (for contacts, tags, etc.) allows 10 requests per second per token with a daily ceiling of 864,000 requests. Dixa does not send a Retry-After header on 429 responses.
