Zendesk to Gorgias Migration: The Complete Technical Guide
How to migrate from Zendesk to Gorgias — data mapping, API rate limits, native importer limits, edge cases, and the step-by-step process.
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
Zendesk to Gorgias Migration: The Complete Technical Guide
TL;DR — Zendesk to Gorgias Migration
A Zendesk to Gorgias migration is moderate complexity for data, high complexity for workflow reconstruction. Realistic timeline: 2–3 weeks end to end. The single biggest risk is silent data loss — the native Gorgias importer splits any ticket with more than 250 comments into multiple closed tickets, does not import attachments, and fails to import ticket fields if your Zendesk instance has more than 500 fields. Zendesk's 6 standard statuses collapse to Gorgias's 2 API statuses (Open and Closed) — Pending, On-hold, and Solved all become Closed. Teams with fewer than 10,000 tickets and no complex custom fields can use the native importer. Everyone else should use an API-based migration or a managed service.
What Is a Zendesk to Gorgias Migration?
A Zendesk to Gorgias migration is the process of moving helpdesk data — tickets, conversations, customers, tags, macros, and ticket fields — from Zendesk's general-purpose support platform to Gorgias's e-commerce-native helpdesk. The goal is to preserve full conversation history, maintain customer context, and rebuild automation workflows without interrupting live support. (docs.gorgias.com)
Why E-Commerce Teams Move from Zendesk to Gorgias
Teams make this switch for platform-specific reasons, not generic ones. If you're evaluating the decision itself, see our Zendesk vs Gorgias decision matrix.
- Native Shopify integration. Gorgias surfaces order data, refund actions, and shipping status directly inside the ticket. Agents can issue refunds, duplicate orders, and award loyalty points without leaving the conversation. Zendesk requires marketplace apps that offer less depth.
- Ticket-based pricing. Gorgias charges by ticket volume and includes up to 500 agent seats on most plans. Zendesk charges per agent per month — at $55–$115/agent/month on Professional and Enterprise plans, this becomes expensive for teams with 20+ agents handling relatively low ticket volumes.
- E-commerce automation. Gorgias Rules can trigger actions based on Shopify order data — auto-tagging by order value, auto-responding to "where is my order" queries with tracking info, or escalating orders above a dollar threshold. Zendesk triggers cannot access Shopify order data natively.
That said, Gorgias is purpose-built for e-commerce. It is not a general-purpose helpdesk. Teams with B2B, IT, or multi-department support needs may find Gorgias limiting — you lose Zendesk Explore analytics, community forums, the mature app marketplace (1,500+ integrations vs. Gorgias's ~100), and organization-level grouping.
What Makes This Migration Non-Trivial
The hard part is not exporting tickets from Zendesk. The hard part is translating Zendesk's richer support model into Gorgias's data model without flattening away operational meaning. Four architectural differences drive most surprises. (developer.zendesk.com)
Status model mismatch. Zendesk has 6 standard status categories (New, Open, Pending, On-hold, Solved, Closed) plus optional custom ticket statuses. Gorgias's API exposes status as only open or closed, with snoozing handled separately via snooze_datetime. (support.zendesk.com) Every status mapping decision has downstream impact on your Views, Rules, and SLA tracking.
Workflow model mismatch. Zendesk triggers fire when tickets are created or updated. Zendesk automations are hourly time-based checks (e.g., "close ticket 48 hours after status set to Solved"). Gorgias Rules are event-driven, with supported triggers like ticket-created, ticket-updated, and ticket-message-created. A Zendesk automation that checks hourly whether a Pending ticket has been idle for 72 hours has no direct Gorgias equivalent — you must approximate it with snooze timers or external scheduling. (developer.zendesk.com)
Entity model mismatch. Zendesk centers on tickets, users, organizations, groups, macros, triggers, automations, and SLA policies. Gorgias centers on tickets, customers, users, teams, tags, rules, macros, custom fields, and channel-based SLAs. Notably, Gorgias has no Organization object — org data must be stored as customer tags or custom attributes. This is a significant gap for teams managing B2B accounts where multiple contacts share an organization.
Ticket-message coupling. In Gorgias, a ticket cannot exist without at least one message. Zendesk allows empty tickets (e.g., tickets created via API or side conversations with no public comment). Any Zendesk ticket with no comments will fail to import into Gorgias via the API unless you attach a placeholder message.
Zendesk to Gorgias Data Mapping: Object by Object
Data mapping dictates whether your historical reporting and customer context survive the move. You must translate Zendesk's relational objects into Gorgias's conversation-first model.
| Zendesk Object | Gorgias Object | Notes / Caveats |
|---|---|---|
| Tickets | Tickets | Zendesk ticket IDs are not preserved. Gorgias assigns new IDs. Store the original in external_id for traceability. |
| Ticket Comments (public) | Messages | Each comment becomes a Gorgias message. Must set sent_datetime or Gorgias will attempt to send the message to the customer. |
| Ticket Comments (internal) | Internal Notes | Map using channel: "internal-note" in the Gorgias API. |
| End-users / Requesters | Customers | Matched by email address. Users without ticket activity are not imported by the native tool. Gorgias does not allow CSV customer import — API only. |
| Agents | Users | Must be pre-created in Gorgias with matching email addresses before loading tickets. Assignment mapping requires exact email match. |
| Organizations | — | No equivalent. Gorgias has no Organization object. Store org data as customer tags or custom attributes. Teams managing 50+ organizations should consider a naming convention like org:company-name for tags. |
| Groups | Teams | Must be created manually in Gorgias before import. |
| Tags | Tags | Direct import, but only tags attached to tickets are included by the native importer. Standalone tags are skipped. |
| Macros | Macros | Native tool imports text templates, but macros with Zendesk-specific actions (Set Priority, Add CC, Change Form) lose all non-text actions. Liquid markup variables (e.g., {{ticket.requester.name}}) must be rewritten to Gorgias variables (e.g., {{ticket.customer.name}}). |
| Ticket Fields (custom) | Ticket Fields (custom) | Fails entirely if Zendesk has 500+ fields. Gorgias allows many fields but only 25 can be active at once. Multi-select and regex-validated fields need manual mapping. (docs.gorgias.com) |
| Triggers / Automations | Rules | Not migrated. Must be rebuilt manually. Zendesk automations are hourly checks; Gorgias Rules are event-driven. |
| SLA Policies | SLA Policies | Must be rebuilt manually. Gorgias SLAs are channel-based with tag and ticket-field conditions. (docs.gorgias.com) |
| Satisfaction Ratings (CSAT) | — | Not imported by native tool or API. Export from Zendesk Explore before decommissioning. |
| Attachments | — | Not imported by native importer. API-based migration can handle them, but each file requires a separate upload request via POST /api/upload. |
| Views | — | Not migrated. Rebuild in Gorgias. |
| Zendesk Talk recordings | — | No migration path. Gorgias does not store call recordings from Zendesk Talk. Export and archive separately. Voice tickets import as text-only records if comments exist. |
| Knowledge Base (Guide) | Help Center | Articles can be imported via CSV or the Help Center import tool. Categories and sections are restructured into Gorgias's flat collection model. Article-level SEO metadata (meta descriptions, canonical URLs) may need manual review post-import. |
How Zendesk Ticket Statuses Map to Gorgias
This is the most common source of post-migration confusion and support issues.
| Zendesk Status | Gorgias Status | What Happens |
|---|---|---|
| New | Open | Imported as open |
| Open | Open | Imported as open |
| Pending | Closed | Tagged with pending for View filtering |
| On-hold | Closed | No special tagging by native importer |
| Solved | Closed | No distinction from Closed |
| Closed | Closed | Standard mapping |
| Custom statuses | Flattened | Mapped to underlying category; store original value in a tag or field for reporting |
The native importer explicitly states that only Open or Closed statuses are retained. (docs.gorgias.com)
If your team uses Pending status to track tickets awaiting customer response, you lose that distinction out of the box. Build a Gorgias View filtering on the pending tag immediately post-migration, or agents will miss follow-ups. For a more intentional approach, map Pending to Open with a zendesk_status:pending tag and use Gorgias Rules to manage the SLA. On-hold tickets should similarly receive a zendesk_status:on-hold tag if your team distinguishes between waiting-on-customer and waiting-on-internal.
Custom Field Constraints
Gorgias's native importer preserves decimal, boolean, and date field types; converts integer to decimal; skips lookup fields entirely; and imports several other Zendesk field types as text, with metadata like regex or multiselect options pushed into the description. (docs.gorgias.com)
If your Zendesk instance has more than 500 ticket fields, the native importer silently skips all ticket field imports. You won't get an error — the fields simply won't appear. Audit and prune fields before migration. Gorgias allows many ticket fields to exist, but only 25 can be active at once, so field pruning is often mandatory before cutover.
Field type conversion reference:
| Zendesk Field Type | Gorgias Result | Action Required |
|---|---|---|
| Text, Textarea | Text | None |
| Integer | Decimal | Verify downstream reporting handles decimal format |
| Decimal | Decimal | None |
| Boolean (Checkbox) | Boolean | None |
| Date | Date | None |
| Dropdown | Text | Dropdown options lost; recreate as Gorgias dropdown manually |
| Multi-select | Text | Options concatenated; recreate as separate fields or tags |
| Regex-validated | Text | Validation rules not preserved; add validation via Rules if needed |
| Lookup | Skipped | Must recreate manually or store as text |
What Data Cannot Be Migrated from Zendesk to Gorgias
Be honest with stakeholders about what doesn't survive the move:
- Attachments — not migrated by the native tool. API-based migration can move them, but each file requires a separate upload request, adding significant time. For a 100K-ticket instance averaging 0.5 attachments per ticket, expect ~50,000 additional API calls.
- CSAT / Satisfaction ratings — no migration path. Export from Zendesk Explore and archive separately. Gorgias has its own CSAT system that starts fresh post-migration.
- Triggers and automations — must be rebuilt as Gorgias Rules. Zendesk trigger logic does not map 1:1 to Gorgias Rules. Budget 1–2 days for teams with 20+ triggers.
- SLA policies — Gorgias has channel-based SLAs, but they must be rebuilt from scratch against a different condition model.
- Organizations — no Gorgias equivalent. Store as customer tags or custom attributes.
- Views — no migration path. Rebuild manually.
- Zendesk ticket IDs — Gorgias assigns new IDs. Store old IDs in
external_idor a custom field for reference. - Lookup fields — skipped entirely by the native importer.
- Zendesk Talk call recordings — no migration path. Export from Zendesk and archive separately. Voice ticket text comments can migrate if they exist.
- Data older than 2 years — the native importer caps at 2 years. The API has no such limit, but you must decide if older data justifies the migration cost.
- Zendesk Explore reports and dashboards — no migration path. Gorgias Statistics provides basic reporting (response time, resolution time, ticket volume by channel). For Explore-equivalent depth, teams typically export historical data to a BI tool (Looker, Metabase, or Google Sheets + BigQuery) before decommissioning Zendesk.
Migration Approaches: Native Importer vs. API vs. Managed Service
Gorgias Native Import Tool
How it works: Connect your Zendesk API credentials in Gorgias Settings → Advanced → Historical Imports. The tool imports tickets, macros, users, tags, and ticket fields. It also offers a continuous sync mode for ongoing coexistence during transition.
When to use it: Small Zendesk instances under 10,000 tickets, fewer than 500 custom fields, and no tickets exceeding 250 comments.
Documented limitations:
- Average import rate of 720 tickets per hour — 100,000 tickets takes roughly 6 days
- Tickets with more than 250 comments are split into multiple closed tickets
- Fails to import ticket fields if Zendesk has more than 500 fields
- Does not import attachments or satisfaction ratings
- Only imports the most recent 2 years of ticket history
- Cannot selectively import by channel — all or nothing
- One import per Zendesk domain — if it fails, you can't re-run it
- Imported macros cannot be edited while sync is active
- Tags added after import starts do not appear in Gorgias sync
Custom API Migration (DIY)
How it works: Extract data via the Zendesk REST API (v2) or Incremental Export API, transform it, and load via Gorgias's REST API (POST /api/tickets, POST /api/tickets/{id}/messages). Gorgias's current API base URL follows the pattern https://{domain}.gorgias.com/api/.
When to use it: Teams with engineering resources who need control over field mapping, want to preserve attachments, or need to handle tickets with 250+ comments without splitting.
Risks:
- Gorgias API rate limits throttle hard: 40 requests per 20-second window on API key auth, 80 requests per 20-second window on OAuth2
- You must set
sent_datetimeon every imported message — omitting it causes Gorgias to send the message to the customer - Rate limit budget is shared across all integrations on the account
- Engineering time is typically 3–5× what teams initially estimate. A 50K-ticket migration that looks like "a few days of scripting" commonly consumes 80–120 engineering hours once you account for rate limit handling, edge cases, retry logic, validation, and debugging.
Managed Migration Service
How it works: A migration partner handles extraction, transformation, loading, validation, and cutover planning.
When to use it: High-volume instances (50,000+ tickets), complex custom field configurations, need for attachment migration, or teams without spare engineering bandwidth. Managed migration services for Zendesk-to-Gorgias typically cost $2,000–$15,000 depending on ticket volume, attachment requirements, and custom field complexity. Budget guidance: roughly $0.02–$0.10 per ticket migrated for full-service providers.
| Criteria | Native Importer | Custom API (DIY) | Managed Service |
|---|---|---|---|
| Complexity | Low | High | Low (for you) |
| Cost | Free | 80–120+ engineering hours | $2K–$15K typical |
| Attachments | ❌ No | ✅ Yes | ✅ Yes |
| 250+ comment tickets | ❌ Splits | ✅ Preservable | ✅ Preservable |
| 500+ custom fields | ❌ Fields skipped | ✅ Full control | ✅ Full control |
| Speed (100K tickets) | ~6 days | 35–50 hours | < 1 day |
| Risk of re-sending messages | Low (handled) | ⚠️ High if sent_datetime missed |
Low |
| History depth | 2 years max | Unlimited | Unlimited |
| Rollback support | None (one-shot) | Manual | Typically included |
If your Zendesk instance has fewer than 5,000 tickets, no attachments worth keeping, and simple custom fields, the native tool is fine. For everything else, the cost of getting it wrong — broken history, re-sent messages, weeks of agent confusion — outweighs the cost of doing it right.
Technical Architecture: Beating Gorgias API Rate Limits
Zendesk Extraction
For bulk ticket extraction, use the Incremental Exports API (GET /api/v2/incremental/tickets/cursor). It returns up to 1,000 tickets per page with cursor-based pagination. The incremental export endpoint is rate-limited to 10 requests per minute, shared across all export jobs on the account. The High Volume API add-on increases this to 30 requests per minute. (developer.zendesk.com)
For individual ticket comments, use GET /api/v2/tickets/{id}/comments. This endpoint falls under the account-wide rate limit, which Zendesk documents as varying by plan — Professional plans typically see 400–700 requests per minute, Enterprise plans up to 2,500. (developer.zendesk.com)
If you need full operational history — not just messages but field changes, status changes, and tag changes — fetch audits per ticket via GET /api/v2/tickets/{id}/audits, not just comments. The list-audits-for-ticket endpoint returns a maximum of 100 records per page and is more expensive than the comments endpoint.
Multi-brand Zendesk instances: If you run multiple Zendesk brands, each brand's tickets export through the same API. You'll need to decide whether to migrate all brands into a single Gorgias account (using tags to distinguish brand origin) or into separate Gorgias accounts. Gorgias does not have a native multi-brand concept — each account maps to one store. For multi-brand setups, create separate Gorgias accounts per brand and run parallel migrations.
For a detailed walkthrough on Zendesk data extraction, see our guide on how to export tickets from Zendesk.
Gorgias Loading
Gorgias's API is the bottleneck. Rate limits are enforced per-account using a leaky bucket algorithm:
| Auth Method | Requests per Window | Window | Effective Rate |
|---|---|---|---|
| API Key (Basic Auth) | 40 | 20 seconds | ~2 req/s |
| OAuth2 | 80 | 20 seconds | ~4 req/s |
| Enterprise (OAuth2) | 80 | 10 seconds | ~8 req/s |
The per-account limit means every integration connected to your Gorgias account shares the same budget. If your Shopify integration, phone integration, and migration script all hit the API simultaneously, they compete for the same 40 or 80 requests. Gorgias provides Retry-After and X-Gorgias-Account-Api-Call-Limit headers for throttling control.
Throughput math: At 80 requests per 20 seconds (OAuth2), you get 4 requests per second. Creating a ticket with one message requires 1 API call. A ticket with 10 messages requires 1 ticket creation + 9 message creation calls = 10 calls. A ticket with 50 comments consumes 50 API calls — roughly 12.5 seconds of your rate limit budget.
For a 100,000-ticket migration where the average ticket has 5 messages:
- Total API calls: ~500,000 (100K ticket creates + 400K message creates)
- At 4 requests/second: ~125,000 seconds ≈ ~35 hours of continuous loading
- With 429 retries and backoff overhead: realistically 40–50 hours
On API key auth (~2 req/s), those numbers roughly double. Attachment uploads add another request per file on top.
Optimization strategies:
- Disconnect non-essential integrations during migration to reclaim rate limit budget
- Use OAuth2 auth for the migration script (2× throughput vs. API key)
- Include the first message in the ticket creation payload to save one call per ticket
- Batch customer creation before ticket loading to avoid lookup overhead during ticket creation
- Run migration during off-peak hours when Shopify webhooks and live agent activity are minimal
Critical: Set sent_datetime on every imported message. If sent_datetime is empty, Gorgias treats the message as new and will attempt to send it to the customer. For historical imports, always populate this field with the original created_at timestamp from Zendesk.
Do not blindly PUT /tickets/{ticket_id}/custom-fields. That Gorgias endpoint uses replace-all semantics: any existing field value you omit will be deleted. Use single-field updates, or fetch the current values, merge, then write the full set. (developers.gorgias.com)
Step-by-Step Migration Process
The order matters. Loading tickets before creating users breaks agent assignments. Loading messages without sent_datetime emails your customers. Here's the sequence that prevents broken relationships.
1. Audit and Plan
- Count tickets, comments, custom fields, macros, and agents in Zendesk
- Identify tickets with 250+ comments — these need special handling
- Decide how much history to migrate (last 6 months? 2 years? all?). See our help desk data migration playbook for guidance on what to move and what to leave behind
- Map Zendesk custom fields to Gorgias ticket fields — prune low-value fields early. Reduce to ≤25 active fields
- Export Zendesk ticket field configs, macros, triggers, automations, groups, and SLAs
- Identify multi-brand configurations and decide on single vs. multi-account Gorgias setup
- Export Zendesk Explore reports and CSAT data for archival — these cannot be migrated
- Decide what will be archived rather than migrated
- Define your rollback criteria: what conditions trigger a revert to Zendesk? (See Rollback Plan below)
2. Prepare the Gorgias Instance
- Create all Teams (mapped from Zendesk Groups)
- Create all agent User accounts with correct email addresses
- Create custom ticket fields with correct types and values (stay under the 25-active-field limit)
- Connect email, chat, and social integrations — but do not point production email domains at Gorgias yet
- Set up SLA policies and macro shells
- Verify Gorgias plan supports required features (SLA policies require the Advanced plan or higher; Enterprise rate limits require Enterprise plan)
- Disable auto-responders and automation Rules until migration is validated
3. Extract from Zendesk
# Zendesk Incremental Export — cursor-based (API v2)
import requests, time
ZD_SUBDOMAIN = "yourcompany"
ZD_AUTH = ("[email protected]/token", "your-api-token")
start_time = 1672531200 # Unix timestamp — beginning of export window
def extract_tickets(start_time):
url = f"https://{ZD_SUBDOMAIN}.zendesk.com/api/v2/incremental/tickets/cursor.json?start_time={start_time}"
all_tickets = []
while url:
resp = requests.get(url, auth=ZD_AUTH)
if resp.status_code == 429:
time.sleep(int(resp.headers.get("Retry-After", 60)))
continue
data = resp.json()
all_tickets.extend(data["tickets"])
url = data.get("after_url") if not data.get("end_of_stream") else None
time.sleep(6) # Respect 10 req/min limit
return all_ticketsStore the JSON payloads in a secure, intermediate staging layer (PostgreSQL, S3, or similar). For thread fidelity, pull comments via GET /api/v2/tickets/{id}/comments. For full operational audit trails, fetch audits per ticket via GET /api/v2/tickets/{id}/audits instead.
4. Transform Data
- Map Zendesk statuses to Gorgias Open/Closed
- Tag Pending tickets with
pending(and optionallyzendesk_status:pending) for View filtering - Tag On-hold tickets with
zendesk_status:on-hold - Preserve original Zendesk status in a tag or custom field if reporting matters
- Strip unsupported custom field types (lookup fields, regex-validated fields)
- Convert Zendesk
comment.author_idto Gorgias customer email or agent email using a pre-built ID→email lookup from the Zendesk Users API - Set
sent_datetimeon every message from the Zendesk comment'screated_attimestamp - Rewrite Zendesk Liquid variables in macros to Gorgias variable syntax
- Attach a placeholder message (e.g., "Migrated from Zendesk — no original message body") to any ticket with zero comments
5. Load Identities Before Conversations
Create or resolve customers, users, and teams before loading tickets so assignment and sender identity can be rebuilt cleanly. Preserve Zendesk IDs in external_id fields — this makes reruns and reconciliation safe.
Note that Gorgias does not support CSV, Google Sheet, or Excel customer imports — the API is the only path. (developers.gorgias.com)
# Store the Zendesk → Gorgias ID mapping
id_map = {}
def create_customer(zendesk_user):
url = f"https://{GORGIAS_DOMAIN}.gorgias.com/api/customers"
payload = {
"email": zendesk_user["email"],
"name": zendesk_user["name"],
"external_id": f"zd-user:{zendesk_user['id']}"
}
resp = requests.post(url, json=payload, auth=GORGIAS_AUTH)
if resp.status_code == 201:
id_map[zendesk_user["id"]] = resp.json()["id"]
elif resp.status_code == 409:
# Customer already exists — fetch by email and map
existing = requests.get(
f"https://{GORGIAS_DOMAIN}.gorgias.com/api/customers?email={zendesk_user['email']}",
auth=GORGIAS_AUTH
).json()
if existing.get("data"):
id_map[zendesk_user["id"]] = existing["data"][0]["id"]
return resp6. Load Tickets and Messages
Create each Gorgias ticket with its first message included, then append subsequent messages oldest-to-newest. Private Zendesk comments should map to channel: "internal-note". Upload attachments first via POST /api/upload, then reference them in the message payload.
# Gorgias ticket creation with rate-limit handling
import time
GORGIAS_DOMAIN = "yourstore"
GORGIAS_AUTH = ("[email protected]", "your-api-key") # or OAuth2 token
def create_ticket(ticket_payload):
url = f"https://{GORGIAS_DOMAIN}.gorgias.com/api/tickets"
while True:
resp = requests.post(url, json=ticket_payload, auth=GORGIAS_AUTH)
if resp.status_code == 429:
wait = int(resp.headers.get("Retry-After", 10))
time.sleep(wait)
continue
if resp.status_code == 201:
return resp.json()
resp.raise_for_status()
# Example ticket payload with first message
ticket_payload = {
"external_id": f"zd-ticket:{zd_ticket_id}",
"subject": subject[:998],
"status": mapped_status, # "open" or "closed"
"messages": [{
"external_id": f"zd-comment:{first_comment_id}",
"channel": "email",
"via": "api",
"from_agent": False,
"sent_datetime": first_comment_created_at, # ISO 8601 format
"body_text": first_comment_body,
"sender": {"email": requester_email}
}]
}Gorgias documents external_id on tickets, messages, and custom fields as foreign-system identifiers — useful anchors for idempotency, replay safety, and reconciliation. (developers.gorgias.com)
For tickets with multiple comments, add subsequent messages via POST /api/tickets/{ticket_id}/messages. Always include sent_datetime.
7. Delta Sync and Cutover
Because support cannot pause, run a final delta sync immediately before cutover to capture tickets created or updated in Zendesk during the migration window. Use the Zendesk Incremental Export with the start_time set to the beginning of your initial extraction to catch all changes.
Switch email and chat integrations from Zendesk to Gorgias during a low-traffic window — typically a weekend night or early morning. The cutover sequence:
- Disable Zendesk triggers and automations to prevent race conditions
- Run final delta sync from Zendesk → Gorgias
- Update MX records or email forwarding to point at Gorgias
- Reconnect social media integrations in Gorgias
- Enable Gorgias Rules and auto-responders
- Verify first few live tickets route correctly
- Keep Zendesk in read-only mode for 7–14 days as a rollback safety net
Do not connect the same email address or social integration to both Zendesk and Gorgias simultaneously. Gorgias explicitly warns that shared integrations across both platforms can duplicate messages and break sync. (docs.gorgias.com)
8. Validate
- Record count reconciliation. Total Zendesk tickets exported vs. total Gorgias tickets created. Account for skipped blank or deleted tickets.
- Message-level spot checks. Sample at least 50–100 tickets across channels, priorities, and statuses. Verify message count, body content, timestamps, private/public visibility, and agent attribution.
- Custom field verification. Check that dropdown values, text fields, and checkbox fields transferred correctly. Pay special attention to multi-select fields.
- Tag integrity. Export the Gorgias tag list and compare against Zendesk.
- Macro audit. Review every imported macro. Delete or fix macros with Zendesk-specific actions that won't work in Gorgias.
- Send-log check. Confirm no outbound messages were triggered during import by reviewing Gorgias's sent message log.
- Integration test. Verify Shopify, email, chat, and social integrations are connected, receiving new tickets, and recognizing migrated customers.
- SLA validation. Confirm SLA policies are firing on new tickets with correct thresholds.
For a complete post-cutover checklist, see our post-migration QA guide.
Rollback Plan
No migration guide is complete without a rollback procedure. If the Gorgias migration fails catastrophically mid-cutover:
- Keep Zendesk active in read-only mode for 7–14 days post-cutover. Do not decommission until Gorgias is validated in production.
- Revert email routing. Update MX records or forwarding rules to point back at Zendesk. DNS propagation typically takes 15–60 minutes for MX changes with low TTL.
- Reconnect social integrations to Zendesk. Disconnect from Gorgias first to avoid dual-connection conflicts.
- Re-enable Zendesk triggers and automations.
- Communicate to agents. Have a pre-written Slack message or email ready: "We're reverting to Zendesk. Switch back now. Details at [link]."
Rollback triggers (define these before cutover):
- More than 5% of live tickets failing to create in Gorgias
- Evidence of messages being sent to customers from historical imports
- Email integration not receiving new messages within 30 minutes of cutover
- Shopify integration failing to surface order data
The rollback cost is low if you keep Zendesk active. The cost of not having a rollback plan is a team with no working helpdesk.
How Long Does a Zendesk to Gorgias Migration Take?
Timeline depends on ticket volume, custom field complexity, and whether you need attachments.
| Phase | Duration | Depends On |
|---|---|---|
| Discovery & audit | 2–3 days | Instance complexity, stakeholder availability |
| Field mapping & Gorgias setup | 2–3 days | Number of custom fields, teams, integrations |
| Test migration (subset) | 1–2 days | Data volume, API rate limits |
| Validation & UAT | 2–3 days | QA thoroughness, stakeholder sign-off |
| Full migration + cutover | 1–3 days | Total ticket volume, message count |
| Post-go-live support | 3–5 days | Agent training, Rule rebuilding |
| Total | ~2–3 weeks |
For very large histories (250K+ tickets), attachment migration, or heavy workflow rebuilds (30+ triggers/automations to reconstruct as Rules), expect the timeline to push toward 3–4 weeks. QA and cutover dominate the schedule, not extraction.
Risk Register
| Risk | Likelihood | Mitigation |
|---|---|---|
| Messages re-sent to customers | Medium | Always set sent_datetime on every imported message |
| Tickets split (250+ comments) | High (for long-running tickets) | Use API-based migration instead of native importer |
| Custom fields dropped (500+ limit) | Medium | Pre-audit field count; use API if over 500 |
| Agent assignment breaks | Medium | Pre-create all agents with matching emails before loading tickets |
| Rate limit stalls during cutover | High | Schedule during low-traffic window; use OAuth2 for 80 req/20s; disconnect non-essential integrations |
| Duplicate live messages | Medium | Never connect the same email or integration to both systems at once |
| Status/reporting drift | High | Preserve original Zendesk status in a tag or field; rebuild Views before go-live |
| Field sprawl after load | Medium | Prune before load; respect the 25-active-field limit in Gorgias |
| Failed migration with no rollback | Low | Keep Zendesk in read-only mode for 7–14 days; define rollback triggers pre-cutover |
| Reporting gaps post-migration | High | Export Zendesk Explore data before decommission; set up Gorgias Statistics or BI tool |
Edge Cases That Break During Migration
Do not rely on best-case scenarios. Plan for the documented failure modes.
Tickets with 250+ comments. The native Gorgias importer splits these into multiple closed tickets with no cross-reference between them. A single complex B2B ticket becomes 2–3 disconnected records. If your support handles enterprise accounts with long-running threads, this is a show-stopper for the native tool. On the API path, you can keep all messages under one ticket — Gorgias does not impose a per-ticket message limit via the API. (docs.gorgias.com)
500+ Zendesk ticket fields. The native importer silently skips all ticket field imports. No error message — the fields simply don't appear. Audit your field count before choosing an import method. Run GET /api/v2/ticket_fields and check the count header.
Duplicate customers. Gorgias deduplicates customers by email address. If your Zendesk instance has the same email across multiple end-user records (common after merges), you'll get merged customer profiles in Gorgias. Audit and deduplicate before migration. Run a Zendesk query for duplicate emails: GET /api/v2/search.json?query=type:user and cross-reference.
Empty Zendesk tickets. Gorgias requires at least one message per ticket. Any Zendesk ticket with no comments fails on import. Attach a placeholder message or skip these records. Common sources: API-created tickets, side conversations, or tickets created by system automations.
Macros with unsupported actions. Zendesk macros can set Priority, add CCs, change ticket form, or apply SLA. None of these actions exist in Gorgias. Imported macros carry over the text template but lose all non-text actions. Audit each macro post-migration and document which actions were dropped.
Inline attachments with authentication. If your Zendesk instance requires authentication to view attachments (the default for non-public attachments), the native importer imports broken image links. Temporarily disable attachment authentication during migration via Zendesk Admin → Settings → Tickets → "Require authentication to download," or download binaries via API and re-upload to Gorgias.
One import per Zendesk domain. The native importer allows only one import per Zendesk domain. If it fails mid-way, you cannot re-run it. This is why a test migration on a Zendesk sandbox is critical before running against production. (docs.gorgias.com)
Tags added after import starts. Tags added to Zendesk tickets after the native import begins will not appear in Gorgias. Freeze tag changes during the import window.
Channel reconnection. The native importer preserves channel type (email, chat, phone), but social media integration reconnection is required post-migration. Facebook and Instagram integrations must be re-authorized in Gorgias.
Shared integrations during transition. Do not connect the same email address to both Zendesk and Gorgias simultaneously. This causes duplicate messages and tickets that won't sync properly.
Zendesk Talk / voice tickets. Call recordings from Zendesk Talk have no migration path. Voice tickets that contain text comments (agent notes, transcriptions) will import as standard tickets, but the audio files are lost. Export recordings from Zendesk Talk before decommissioning.
What Customers and Agents Notice During Migration
Customers should experience zero downtime if channels are switched once, not dual-connected. The Zendesk instance stays live during extraction and loading. Cutover should happen during a low-volume window. Customers may notice a slight change in email formatting (Gorgias uses its own email templates) — preview and customize templates before cutover.
Ticket ID changes. Gorgias assigns new IDs. If your team shares ticket IDs externally — in emails, Slack, or customer-facing portals — those references break. Communicate this to agents before cutover and store old Zendesk IDs in a custom field or external_id.
Status behavior changes. Agents notice new status behavior first. Pending and On-hold semantics need new Views, tags, or snooze rules to replicate familiar workflows. Create a one-page reference sheet mapping old workflows to new ones.
SLA gaps. If your team reports on first-response time or resolution time against formal SLA targets, rebuild these in Gorgias's channel-based SLA system. Gorgias SLAs use tag and ticket-field conditions and measure first response and resolution time with values from 1 minute to 14 days. Note that SLA configuration requires Gorgias's Advanced plan or higher. (docs.gorgias.com)
Reporting gaps. Teams accustomed to Zendesk Explore's custom dashboards will find Gorgias Statistics more limited. Gorgias Statistics covers: ticket volume, response time, resolution time, CSAT, agent performance, and channel breakdown. It does not support custom calculated metrics, multi-dimensional cross-tabs, or scheduled report delivery. Teams needing deeper analytics should plan to pipe Gorgias data into a BI tool via the API or a connector like Fivetran.
Agent retraining. Budget 2–3 days minimum. Gorgias's UI, keyboard shortcuts, and macro system differ from Zendesk. The Shopify sidebar is a net positive for e-commerce agents, but the adjustment period is real. Key differences agents need to learn: Gorgias's snooze function (replacing Pending), the tag-based View system, and the macro variable syntax. Change management is the highest hidden cost of this migration. For training guidance during a platform transition, see our help desk data migration playbook.
Should You Build In-House or Use a Managed Service?
Build in-house when:
- Your Zendesk instance is small (under 10,000 tickets)
- You have a backend engineer with 2–3 weeks of availability
- You don't need attachments migrated
- Your custom fields are simple (text, dropdowns under 50 values)
- You can accept some model flattening and are prepared for retries and debugging
Use a managed service when:
- Ticket volume exceeds 50,000
- You have tickets with 250+ comments that must stay intact
- Your Zendesk has 500+ custom fields
- You need attachments preserved
- You can't afford a failed migration and re-migration cycle
- Your engineering team is already at capacity
- You have custom statuses, field sprawl, or heavy automations that need rebuilding
The hidden cost of DIY isn't the initial build — it's the debugging. Rate limit handling, sent_datetime errors, broken agent assignments, split tickets, and the PUT replace-all gotcha on custom fields all surface after the migration starts. Re-migration after a failed attempt doubles the timeline and frustrates the entire support team.
ClonePartner has completed over 1,500 helpdesk migrations, including complex Zendesk-to-Gorgias moves with high-volume ticket histories, 500+ custom field configurations, and full attachment preservation. Our engineers handle rate limit orchestration, attachment transfer, and full validation — typically completing migrations in 1–5 business days with zero downtime.
Frequently Asked Questions
- How long does a Zendesk to Gorgias migration take?
- The native Gorgias importer processes about 720 tickets per hour — roughly 6 days for 100,000 tickets. An API-based or managed migration can complete the same volume in 1–2 days. Including planning, testing, and cutover, the full project typically takes 2–3 weeks.
- Can I migrate Zendesk to Gorgias without losing data?
- You can migrate tickets, messages, tags, macros, users, and ticket fields without loss if you use the API and handle edge cases properly. Attachments, CSAT ratings, SLA policies, triggers, and organizations cannot be migrated via the native tool and require API-level work or manual rebuilding.
- What data cannot be migrated from Zendesk to Gorgias?
- Attachments, satisfaction ratings, SLA policies, triggers/automations, organizations, Views, and Zendesk ticket IDs do not transfer automatically. Triggers must be rebuilt as Gorgias Rules. Zendesk's 6 ticket statuses collapse to Gorgias's 2 (Open and Closed). Lookup fields and data older than 2 years are also skipped by the native importer.
- What happens to Zendesk Pending tickets in Gorgias?
- Pending tickets are imported as Closed in Gorgias but automatically tagged with 'pending.' You can create a Gorgias View filtering on this tag to replicate the Pending workflow, but Pending is not a native Gorgias status. On-hold and Solved are also mapped to Closed.
- Can I keep support live during the migration?
- Yes, if you keep channels single-homed and do a delta cutover. The Zendesk instance stays live during extraction and loading. Do not connect the same email or social integration to both Zendesk and Gorgias simultaneously — Gorgias warns this causes duplicate messages and breaks sync.

