Skip to content

How to Migrate from Pylon to Zendesk: The 2026 Technical Guide

Step-by-step guide to migrating Pylon Issues to Zendesk Tickets. Covers API rate limits, field mapping, Slack thread handling, and Zendesk AI accuracy.

Rishabh Rishabh · · 22 min read
How to Migrate from Pylon to Zendesk: The 2026 Technical Guide
TALK TO AN ENGINEER

Planning a migration?

Get a free 30-min call with our engineers. We'll review your setup and map out a custom migration plan — no obligation.

Schedule a free call
  • 1,500+ migrations completed
  • Zero downtime guaranteed
  • Transparent, fixed pricing
  • Project success responsibility
  • Post-migration support included

How to Migrate from Pylon to Zendesk: The 2026 Technical Guide

Info

TL;DR — Pylon to Zendesk Migration

Migrating from Pylon to Zendesk is a moderate-complexity data-model translation problem. Pylon's core object is the Issue — a Slack-native conversational thread that bundles messages, internal notes, and file attachments. Zendesk's core object is the Ticket — a structured lifecycle record with comments, custom fields, SLAs, and triggers. The realistic timeline is 5–10 business days depending on volume and custom field complexity. The single biggest risk is importing noisy Slack thread history that degrades Zendesk Intelligent Triage accuracy. You must use the Zendesk Ticket Import API (/api/v2/imports/tickets) to preserve historical timestamps — the standard ticket creation endpoint overwrites dates with the current server time. Teams with fewer than 5,000 issues and simple fields can self-serve with the API. Anything above that — or with attachment-heavy Slack threads, complex field mappings, and AI accuracy requirements — benefits from a managed migration service.

What Is a Pylon to Zendesk Migration?

A Pylon to Zendesk migration is the process of extracting Issues, Accounts, Contacts, Messages, Tags, Custom Fields, and Knowledge Base articles from Pylon's Slack-native helpdesk and loading them into Zendesk as Tickets, Organizations, Users, Comments, Tags, Custom Fields, and Help Center articles.

Why teams make this move:

  • Channel expansion beyond Slack. Pylon is built for B2B teams running support inside Slack Connect channels. When a company needs email, web form, phone, and social media as first-class channels, Zendesk's omnichannel architecture is the natural next step.
  • Enterprise compliance and reporting. Zendesk offers native SLA management, Explore analytics, HIPAA-eligible configurations, and a mature marketplace with 1,500+ integrations — capabilities Pylon is still building.
  • AI and automation maturity. Zendesk's Intelligent Triage, AI Agents, and trigger/automation engine give operations teams more control over routing, deflection, and self-service at scale.

The architectural differences that make this migration non-trivial:

  1. Conversational vs. lifecycle model. Pylon Issues are conversation-first: messages flow in from Slack threads, and the Issue is a wrapper around that conversation. Zendesk Tickets are lifecycle-first: every ticket moves through defined statuses (New → Open → Pending → Solved → Closed) with triggers firing at each transition.
  2. Channel metadata. Pylon Issues carry destination_metadata that records the Slack channel ID, workspace, and whether the conversation originated via Slack Connect, email, or chat widget. Zendesk has no equivalent field — this context must be flattened into tags or custom fields.
  3. Threading structure. A single Pylon Issue can contain multiple named threads (e.g., a customer-facing Slack thread and an internal side-conversation thread). Zendesk Comments are a flat chronological list with a public/private flag. Multi-thread conversations must be merged and annotated during transformation.

For teams evaluating the reverse path, see our guide on Zendesk to Pylon migration.

How Pylon's Data Model Maps to Zendesk

If you get the data model wrong, historical context is lost. Pylon and Zendesk handle relationships differently, and you must map Slack-native concepts to Zendesk's structured architecture.

Object mapping

Pylon Object Zendesk Object Notes / Caveats
Issue Ticket States map: new→New, waiting_on_you→Open, waiting_on_customer→Pending, on_hold→On-hold, closed→Solved/Closed. Custom statuses require Zendesk custom ticket statuses.
Account Organization Pylon Account types (customer, internal, community, partner) map to Organization tags or a custom dropdown. domain maps to Zendesk domain_names for automatic user association.
Contact User (end-user) Pylon contacts are often tied to Slack IDs. You must extract the email address to map to Zendesk Users. Portal roles (no_access, member, admin) have no direct Zendesk equivalent — use tags or user fields.
User (agent) User (agent) Pylon user.role_id maps to Zendesk agent roles. Recreate agents before tickets to preserve comment authors and assignees.
Message (public) Comment (public: true) Pylon message_html maps to Zendesk html_body. timestamp maps to created_at (only via Import API).
Message (private / internal note) Comment (public: false) Pylon is_private: true → Zendesk private comment. Thread name context is lost — prepend it to the comment body.
Team Group Pylon Teams map to Zendesk Groups. Agent membership must be set up before ticket import.
Tag Tag Direct 1:1 mapping.
Custom Field Custom Ticket/Org/User Field Pylon custom field slug must match a pre-created Zendesk custom field key. Picklist values must be pre-loaded.
Issue followers Followers / collaborators Only migrate after the referenced Zendesk users exist.
Knowledge Base Article Help Center Article Requires Zendesk Guide. No bulk import API — use POST /api/v2/help_center/sections/{id}/articles. This is a separate workstream from ticket migration.
Attachment (file_urls) Attachment (upload token) Pylon returns file URLs. Each must be downloaded, then uploaded to Zendesk via POST /api/v2/uploads, and the resulting token attached to the comment.
Feature Request No equivalent Flatten to tickets with a tag like feature_request, or skip.
Slack channel metadata No equivalent Store as a custom text field or internal comment for audit trail.
Survey / CSAT response Satisfaction Rating Zendesk Satisfaction Ratings have a fixed schema (good/bad + comment). Pylon surveys with multi-question formats require lossy transformation.

Field-level transformations

Field types are where DIY builds fail quietly. Zendesk enforces stricter type validation than Pylon.

Pylon Field Shape Zendesk Target Transform Rule Gotcha
value text text / textarea Direct map Usually safe.
value number integer / decimal Normalize blanks and placeholders Zendesk type enforcement is stricter.
value single-select tagger / dropdown Map to Zendesk option value, not just label Zendesk stores the tag value, not the display label. Duplicate option values can make fields uneditable.
values multi-select multiselect Pre-create target options, then load stored values Duplicate option values can make fields uneditable.
boolean checkbox Normalize true/false before load Do not trust display labels.
Pylon status enum Zendesk status new→New, waiting_on_you→Open, waiting_on_customer→Pending, on_hold→On-hold, closed→Solved Zendesk distinguishes between Solved (can be reopened) and Closed (archived).
Warning

Biggest modeling mistake: treating Pylon Slack threads like plain ticket descriptions. If you only move the issue title and body_html, you lose the conversation agents actually worked from. You must extract per-issue messages via the Messages API and map them as individual Zendesk Comments.

Relationship dependencies — load order matters

  1. Organizations (from Accounts)
  2. Users — both agents and end-users (from Users and Contacts)
  3. Tickets with Comments (from Issues and Messages)
  4. Attachments (uploaded per-comment)

Breaking this order creates orphaned tickets and broken requester_id references. If you load tickets before users, tickets will default to the API admin, destroying historical ownership.

How to Export Data from Pylon

Pylon does not offer a one-click full data export. CSV exports from views are column-scoped and miss messages, threads, and attachments. Extraction requires the Pylon REST API at api.usepylon.com. Only Admin users can create API tokens, and auth is Bearer token-based. Pylon does not currently support OAuth for API access — all automation relies on static Bearer tokens, which do not expire automatically but can be revoked by admins in the Pylon settings panel.

Key endpoints and rate limits

Endpoint Rate Limit Pagination Notes
GET /accounts 60 req/min Cursor-based, max 1,000/page Returns channels, domains, custom fields, tags
GET /contacts 60 req/min Cursor-based, max 1,000/page Includes account association
GET /issues 10 req/min Cursor-based, requires start_time/end_time (max 30-day window) The bottleneck. You must paginate in 30-day windows across your full history.
POST /issues/search 10 req/min Cursor-based, up to 1,000/page Filter by status, assignee, account, or custom field
GET /issues/{id}/messages 20 req/min Cursor-based Must be called per-issue — there is no bulk messages endpoint
GET /issues/{id}/threads Returns all threads for an issue Use to identify multi-thread conversations
GET /users 60 req/min Cursor-based Agent/internal user list

[For engineering] Throughput math: At 10 req/min for Issues with a page size of 1,000, you can extract ~10,000 issues per minute. But Messages at 20 req/min, fetched per-issue, means a 10,000-issue dataset with an average of 8 messages per issue requires ~500 message-fetch calls. At 20/min, that's 25 minutes just for messages — before accounting for pagination within each issue. Budget 2–6 hours for a full extraction of 10,000 issues with messages and attachments.

import requests
import time
 
PYLON_TOKEN = "YOUR_PYLON_TOKEN"
BASE = "https://api.usepylon.com"
 
def fetch_issues(start, end, cursor=None):
    params = {"start_time": start, "end_time": end, "limit": 1000}
    if cursor:
        params["cursor"] = cursor
    resp = requests.get(f"{BASE}/issues",
        headers={"Authorization": f"Bearer {PYLON_TOKEN}"},
        params=params)
    if resp.status_code == 429:
        time.sleep(60)  # Pylon issues rate limit: 10 req/min
        return fetch_issues(start, end, cursor)
    return resp.json()
Tip

Treat Pylon CSV exports as a reconciliation check, not your source of truth. Messages and threads live on separate API endpoints that CSV exports do not cover. CSV-only migrations lose conversation context.

How the Zendesk Ticket Import API Works

The Zendesk Ticket Import API is the only way to preserve historical timestamps during migration. The standard Ticket Creation API (POST /api/v2/tickets) overwrites created_at with the current server time and fires triggers — including sending email notifications to every customer for every historical ticket. The Import API allows setting created_at, updated_at, and solved_at on both tickets and comments while suppressing notifications.

Two endpoints:

  • Single: POST /api/v2/imports/tickets — imports one ticket with its full comment history
  • Batch: POST /api/v2/imports/tickets/create_many — imports up to 100 tickets per request, returns a job_status for async processing

Key constraints:

  • Triggers do not fire on imported tickets (unless the ticket is later updated).
  • Zendesk metrics and SLAs are not calculated for imported tickets. Tag imported tickets with pylon_import and exclude them from SLA reports.
  • Requesters must be active users. Suspended or deleted users cause import failures. Create placeholder users before import.
  • Comments with empty bodies are rejected. Add placeholder text like (No message body) for Slack reactions or file-only messages.
  • The archive_immediately parameter sends closed tickets directly to the archive, bypassing the ticket lifecycle. Zendesk recommends this for imports exceeding 750,000 tickets.
  • No notifications are sent to requesters or CC'd users on imported tickets.
  • A Zendesk ticket can contain up to 5,000 comments, and a single comment body is limited to 64 KB before truncation. Both limits matter for Slack-heavy Pylon history.
  • Job concurrency: Zendesk allows up to 30 queued or running background jobs before returning TooManyJobs.

Zendesk API rate limits by plan

Zendesk Plan Rate Limit (req/min)
Suite Team 200
Suite Growth 400
Suite Professional 400
Suite Enterprise 700
Suite Enterprise Plus 2,500
High Volume API Add-on 2,500 (replaces base limit)

Zendesk also enforces 100 ticket updates per minute per account as a separate cap, and returns 429 with a Retry-After header when exceeded.

Import throughput estimate

Using create_many with 100 tickets per batch on a Suite Enterprise plan (700 req/min), each batch counts as 1 API request. The theoretical ceiling is 70,000 tickets per minute — but Zendesk queues these as background jobs, and real-world throughput depends on job processing time.

The practical bottleneck is attachments. Every attachment requires a separate call to /api/v2/uploads to generate a token before the ticket can be created. If an average ticket has 2 attachments, your actual throughput drops dramatically. Expect 5,000–10,000 tickets per hour as a realistic sustained rate for an import with comments and attachments.

Plan your cutover window accordingly.

For a deeper look at Zendesk data export and import methods, see how to export tickets from Zendesk.

How Bulk Import Affects Zendesk AI Accuracy

This is the most commonly overlooked risk in any Pylon-to-Zendesk migration. Zendesk's Intelligent Triage automatically classifies incoming tickets by intent, sentiment, and language using AI models trained on your ticket history. Importing a large volume of low-quality Pylon data — unresolved Slack chatter, one-word messages, GIFs, internal noise — dilutes the training signal and can push triage accuracy below usable thresholds.

The AI-first migration strategy:

  1. Filter before import. Only migrate Pylon Issues with a closed state and at least 2 messages. Exclude issues that were auto-closed without resolution, have no customer reply, or consist only of Slack reactions.
  2. Tag quality tiers. Mark imported tickets with tags like resolved_import vs. unresolved_import so you can exclude low-quality records from Intelligent Triage training.
  3. Import resolved tickets first. Give Zendesk's AI 2–4 weeks to learn from clean, resolved data before importing the long tail of open or ambiguous issues.
  4. Monitor Intelligent Triage confidence scores. After import, check the Triage Performance dashboard for accuracy drops. Zendesk requires at least 1,000 solved tickets with intent labels to produce reliable predictions, and confidence scores below 0.7 typically indicate the model needs more clean training data.
  5. Quarantine low-confidence predictions. For the first 30 days post-migration, route tickets with triage confidence below 0.5 to a human review queue rather than automated workflows. This prevents cascading misroutes while the model stabilizes.

For more on how Zendesk's AI features interact with migrated data, see Zendesk AI Agents Migration 2026: What Breaks, What Changes.

Step-by-Step Migration Process

Phase 1: Discovery and field mapping (Days 1–2)

Audit Pylon data. Map Slack channels to Zendesk tags. Define exact field translations. Pre-create all custom fields, ticket forms, groups, and custom statuses in Zendesk before loading any records — imported tickets that reference missing structures will fail or lose data.

Deliverable: A signed-off mapping document that covers every Pylon custom field, its Zendesk target field, the value transformation rule, and the handling decision for any unmappable data (discard, flatten to tag, or store in internal comment).

Phase 2: Extract from Pylon (Days 2–3)

Pull all Accounts, Contacts, Users, Teams, and Issues from the Pylon API. Fetch messages and threads per-issue. Download all attachments from Pylon file_urls before starting the Zendesk load phase — Slack attachment URLs expire (typically within 24–72 hours for shared channel files), and if your script attempts to download an attachment using an expired URL, it will fail silently or return a corrupted file.

Build a translation table mapping slack_user_id to email_address before pushing to Zendesk. For Slack Connect channels, some external user emails may not be available through Pylon — you may need to query Slack's users.info API to resolve them.

Phase 3: Transform (Days 3–4)

  • Map Pylon state to Zendesk status
  • Convert message_html to Zendesk html_body
  • Flatten multi-thread conversations into a single chronological comment stream, prepending thread names as headers (e.g., [via Slack], [via Email])
  • Upload attachments to Zendesk via POST /api/v2/uploads and capture tokens
  • Resolve requester_id and assignee_id by matching Pylon Contact/User emails to Zendesk User IDs
  • Convert Slack user mentions (<@U12345>) to display names; handle emoji reactions as text or discard
  • Store the Pylon issue ID in external_id for traceability
  • Filter noisy data per the AI-first strategy
  • Validate all enum/picklist values against pre-created Zendesk field options — log any unmapped values for manual review

Phase 4: Load into Zendesk (Days 4–6)

Load in strict order: Organizations → Users → Tickets.

import requests
import time
import hashlib
 
ZD_URL = "https://yoursubdomain.zendesk.com/api/v2/imports/tickets/create_many"
ZD_AUTH = ("[email protected]/token", "ZD_API_TOKEN")
 
def generate_idempotency_key(batch_data):
    """Deterministic key prevents duplicate imports on retry."""
    return hashlib.sha256(str(batch_data).encode()).hexdigest()
 
def import_batch(tickets):
    resp = requests.post(ZD_URL,
        json={"tickets": tickets},
        auth=ZD_AUTH,
        headers={"Content-Type": "application/json",
                 "Idempotency-Key": generate_idempotency_key(tickets)})
    if resp.status_code == 429:
        wait = int(resp.headers.get("Retry-After", 60))
        time.sleep(wait)
        return import_batch(tickets)
    if resp.status_code == 503:
        # TooManyJobs — back off and wait for queue to drain
        time.sleep(120)
        return import_batch(tickets)
    return resp.json()

Example Zendesk Import Payload:

{
  "ticket": {
    "requester_id": 123456789,
    "assignee_id": 987654321,
    "subject": "Login failure on production",
    "created_at": "2024-02-15T09:00:00Z",
    "solved_at": "2024-02-16T10:30:00Z",
    "status": "solved",
    "tags": ["pylon_import", "resolved_import"],
    "external_id": "pylon_issue_abc123",
    "comments": [
      {
        "author_id": 123456789,
        "value": "I cannot log into the dashboard.",
        "created_at": "2024-02-15T09:00:00Z"
      },
      {
        "author_id": 987654321,
        "value": "We have reset your password. Please try again.",
        "created_at": "2024-02-16T10:30:00Z",
        "public": false,
        "uploads": ["token_xyz123"]
      }
    ]
  }
}

Phase 5: Sandbox testing and UAT (Days 6–8)

Import a 5% sample to a Zendesk Sandbox first. Zendesk Sandbox availability varies by plan: Suite Growth and above include a sandbox environment; Suite Team does not. If you're on a plan without sandbox access, request a trial sandbox from Zendesk support or use a separate test instance.

Support managers verify:

  • Slack threads render correctly as comments
  • Attachments open and are not corrupted 1KB error files
  • Comment ordering and timestamps are accurate
  • Public vs. private visibility is correct
  • Organization → User → Ticket relationships are intact
  • Custom field values display correctly (not raw tag values)
  • Intelligent Triage predictions on sample tickets produce confidence scores above 0.5

Phase 6: Production import and delta sync (Days 9–10)

Run the production import. Then pause Pylon ingestion, extract any issues created since your last batch, and perform a final delta sync. Route live traffic to Zendesk.

Rollback plan: Zendesk's bulk delete API (DELETE /api/v2/tickets/destroy_many) can remove imported tickets by the pylon_import tag (up to 100 ticket IDs per request). For Organizations and Users created during migration, use DELETE /api/v2/organizations/destroy_many and DELETE /api/v2/users/destroy_many respectively — but note that deleting users who have been associated with non-imported tickets will fail. Tag all migration-created records consistently (e.g., pylon_import) to enable clean rollback scoping. Always import to a sandbox first.

Migration Timeline and Resourcing

Phase Duration Dependencies
Discovery and field mapping 1–2 days Access to both Pylon admin and Zendesk sandbox
Pylon API extraction 1–2 days Pylon API token with admin access
Transform and data cleaning 1–2 days Mapping document sign-off
Zendesk sandbox import + UAT 1–2 days Zendesk sandbox environment
Production import 1 day Go-live window approval
Validation + buffer 1 day QA checklist
Total 5–10 business days

If you are also rebuilding ticket forms, routing logic, automations, or a Help Center, add 1–2 weeks.

Estimated costs

Component Estimated Cost
Zendesk Suite Professional (per agent/month) $115/agent/month (annual billing, 2025 pricing)
Zendesk Suite Enterprise (per agent/month) $169/agent/month (annual billing)
High Volume API Add-on Contact Zendesk sales — typically $100–300/month
DIY engineering time (5,000 issues) 40–80 developer hours
DIY engineering time (25,000+ issues with attachments) 120–200 developer hours
Managed migration service (typical range) $3,000–$15,000 depending on volume, complexity, and attachment density

These are representative ranges based on publicly available Zendesk pricing and typical project scoping. Actual costs vary by contract terms and migration complexity.

Risk register

Risk Likelihood Mitigation
Pylon Issues API rate limit (10 req/min) creates extraction bottleneck High Paginate in 30-day time windows; budget extraction time accordingly
Zendesk 429 errors during batch import Medium Implement exponential backoff with Retry-After header; run imports during off-peak hours (UTC 02:00–08:00)
Attachment download failures from expired Pylon/Slack URLs Medium Download all attachments during extraction phase; retry with fresh Pylon API calls; verify file sizes > 1KB
Broken requester references due to missing user records High Always load Organizations and Users before Tickets; run a pre-flight check matching all Pylon contacts to Zendesk users
Unmapped enum values cause silent field corruption High Pre-create all Zendesk custom field options; map by stored value, not display label; log and flag any unmapped values
Slack context flattened badly High Annotate comments with thread source markers ([via Slack], [via Email]); store Slack IDs in custom fields
Intelligent Triage accuracy degradation post-import Medium Follow the AI-first strategy: filter, tag quality tiers, import resolved first, monitor confidence scores
Duplicate Pylon contacts cause silent user merges in Zendesk Medium Deduplicate contacts by email before import; log all merge events

What Customers Notice During Migration

Downtime: Zero, if planned correctly. Pylon remains live during extraction and transformation. The Zendesk import is additive — it does not lock your Zendesk instance. The recommended approach is to keep Pylon live for active conversations while importing historical data into Zendesk. On cutover day, extract any recent issues, run a final delta import, then redirect customer channels to Zendesk.

History continuity: Customers who previously communicated via Slack will see their conversation history as Zendesk ticket comments. Original timestamps are preserved via the Import API, so the timeline is accurate. Slack-specific formatting — emoji reactions, threaded replies, @-mentions with avatars — is reduced to plain text or HTML.

Notification safety: The Ticket Import API suppresses standard email notifications and triggers during import. If you accidentally use the standard creation API, Zendesk will email every customer a "Ticket Created" receipt for every historical issue. This is a common and expensive mistake.

SLA reset: Imported tickets do not carry Zendesk SLA metrics. Communicate to stakeholders that SLA reporting will only reflect tickets created natively in Zendesk post-migration.

Customer communication plan:

  • 1 week before cutover: Email customers explaining the transition. Include the new support email address, Help Center URL, and portal login instructions (if applicable). Example subject line: "Your support experience is moving — here's what changes and what doesn't."
  • Day of cutover: Post in active Slack Connect channels directing customers to the new Zendesk channel. Include a direct link to submit tickets.
  • 1 week after cutover: Follow up with a brief email confirming the transition is complete and reminding customers of new contact methods.

The trust test is simple: agents should not have to ask customers to re-explain solved cases, and customers should not see private internal context exposed as public comments.

Post-Migration Operational Changes

Migrating data is half the project. The other half is adapting your team's workflows to Zendesk's operational model.

Agent retraining priorities:

  • Ticket lifecycle vs. conversation model. Agents accustomed to Pylon's Slack-native workflow need to learn Zendesk's status progression (New → Open → Pending → Solved → Closed) and understand that setting a ticket to "Pending" starts an SLA clock.
  • Internal notes vs. Slack side-conversations. In Pylon, agents collaborate via internal Slack threads. In Zendesk, the equivalent is a private comment (internal note) or a Side Conversation (available on Suite Professional and above). Train agents on when to use each.
  • Macro and shortcut usage. Zendesk Macros replace Pylon's canned response workflows. Pre-build the 10–15 most common macros based on Pylon usage patterns before cutover. Review Pylon's most-used tags and response templates as a source.
  • Views and queue management. Replace Pylon's Slack channel-based triage with Zendesk Views. Create views that mirror prior workflow: e.g., "My Open Tickets," "Waiting on Customer," "Unassigned — [Team Name]."

Internal documentation updates:

  • Update escalation playbooks to reference Zendesk ticket URLs instead of Slack thread links.
  • Revise on-call runbooks to include Zendesk notification routing and trigger behavior.
  • Document the new support email address and Help Center URL in all internal wikis and customer-facing materials.

Budget 2–3 days of agent training and shadowed ticket handling before full cutover.

Edge Cases and Known Limitations

  • Pylon multi-thread Issues. A single Pylon Issue can have a Slack thread, an email thread, and an internal thread simultaneously. Zendesk Comments have no thread concept — all messages become a flat chronological list. Annotate each comment with [via Slack] or [via Email] to preserve source context.

  • Slack emoji reactions and mentions. Slack emoji reactions (:thumbsup:) used for workflow triggers (e.g., 👀 for "looking into it") have no Zendesk equivalent. These must be translated into internal notes (e.g., "Agent X acknowledged this issue via 👀 reaction at 2024-02-15T09:05:00Z") or discarded. Slack user mentions (<@U12345>) should be converted to display names during transformation.

  • Attachment expiration and size limits. Slack attachment URLs expire (typically 24–72 hours for shared channel files). If your script attempts to download a Pylon attachment using an expired URL, it will fail silently or return a corrupted file. Download all attachments during the extraction phase, not during the Zendesk load phase. Zendesk enforces a 50MB per-attachment limit (20MB on Team plans). Verify downloaded file sizes are > 1KB to catch corrupted downloads.

  • Duplicate contacts. Pylon allows multiple contacts with the same email across different accounts. Zendesk enforces unique email addresses. Deduplicate before import or the API will silently merge users, potentially associating tickets with the wrong organization.

  • Zendesk comment and ticket limits. A single ticket can hold up to 5,000 comments, and a single comment body is limited to 64 KB. Very large Slack histories can hit both limits. Split oversized comments and consider whether a single Pylon issue with extreme thread depth should map to multiple Zendesk tickets linked via the problem_id/incident relationship.

  • Custom Objects. Pylon supports Custom Objects — Zendesk also supports Custom Objects (Sunshine), but the schemas are entirely different. Zendesk Custom Objects require defining a schema via POST /api/v2/custom_objects, creating fields, and then loading records via POST /api/v2/custom_objects/{key}/records. Relationship fields linking custom objects to tickets must be created separately. Budget 1–3 additional days for Custom Object migration depending on schema complexity.

  • Macros, Ticket Forms, and Automation rules. These are configuration objects, not data. They must be manually recreated in Zendesk — there is no automated migration path. Audit Pylon's existing automation rules and map each to its Zendesk equivalent: Triggers (event-based), Automations (time-based), or Macros (agent-initiated).

  • Knowledge Base. KB migration is a separate workstream. Pylon KB content lives on different API endpoints and must be loaded through Zendesk Guide's article creation API (POST /api/v2/help_center/sections/{id}/articles), not through Ticket Import. Articles must be assigned to a section within a category — pre-create the Guide category/section hierarchy before loading articles. Image and media references within articles require separate upload and URL rewriting.

Validation and Testing

Post-migration validation requires discrete checks. Do not rely solely on API response codes — a 200 OK does not guarantee data integrity.

  1. Record count reconciliation. The number of closed issues in Pylon must exactly match the number of imported tickets with the pylon_import tag in Zendesk. Use GET /api/v2/search.json?query=tags:pylon_import to count.
  2. Field-level spot check. Randomly sample 5% of tickets (minimum 50 tickets for statistical confidence). Verify that created_at timestamps, statuses, assignees, and custom field values match the original Pylon data.
  3. Comment ordering and visibility. Confirm that comments appear in chronological order and that internal notes are private, not public. Check at least 20 tickets with 5+ comments each.
  4. Attachment integrity. Click 50 random attachments in Zendesk to ensure they open and are not corrupted 1KB error files. Verify file sizes match the originals.
  5. Relationship integrity. Test Organization → User → Ticket chains. Verify that tickets are assigned to the correct organizations and requesters. Check 20 tickets across different organizations.
  6. AI readiness check. If using Intelligent Triage, verify that sample imported tickets receive intent predictions with confidence scores. Flag any systematic misclassifications.

For a comprehensive QA checklist, see Post-Migration QA: 20 Tests to Run After Your Help Desk Data Migration.

Build In-House, Use a Third-Party Tool, or Use a Managed Service

Option comparison

Criterion DIY (API scripts) Third-party tool (e.g., Help Desk Migration) Managed migration service
Best for <5,000 issues, simple fields, available developer 5,000–50,000 issues, standard field mappings 10,000+ issues, complex fields, attachments, AI requirements
Typical cost 40–200 dev hours $1–3 per ticket (vendor pricing varies) $3,000–$15,000 flat fee
Attachment handling Manual pipeline (download → upload → token) Varies — verify with vendor Included
Custom Object support Full control Limited — verify with vendor Included
AI-first filtering Full control Not typically offered Included
Rollback support You build it Varies Included
Timeline 1–4 weeks 1–2 weeks 1–2 weeks

Build in-house when:

  • You have fewer than 5,000 issues with simple fields
  • You have a Python/Node developer available for 1–2 weeks
  • You don't use Pylon Custom Objects or multi-thread Issues
  • You're comfortable managing Zendesk API rate limits, retry logic, and attachment tokenization

Consider a third-party migration tool when:

  • You have 5,000–50,000 issues with standard field types
  • You don't need AI-first data filtering
  • Help Desk Migration (HDM) lists Pylon as a supported source — verify directly with the vendor that your specific data objects (messages, attachments, custom fields) are covered, as connector capabilities vary

Use a managed service when:

  • You have 10,000+ issues or complex custom field schemas
  • You need attachment migration (the download → upload → token pipeline is the most error-prone step)
  • You're running Zendesk AI features and need an AI-first import strategy
  • Engineering bandwidth is scarce and you can't afford a multi-week side project
  • You need zero-downtime guarantees with a rollback plan

The hidden cost of DIY is not the initial script — it's the debugging. Broken requester references, expired attachment URLs, Slack formatting artifacts, silent enum mismatches, and rate-limit-induced partial imports are the failure modes that turn a 1-week project into a 4-week one. See common help desk data migration mistakes and how to avoid them for a deeper look at these patterns.

Pylon to Zendesk Migration FAQ

Can I preserve Pylon Slack thread history in Zendesk? Yes. Pylon Messages extracted via GET /issues/{id}/messages include the full message_html body and timestamp. When imported using Zendesk's Ticket Import API, these become timestamped comments on the Zendesk ticket. Slack-specific formatting like emoji reactions and @-mentions are converted to plain text during transformation. The history is preserved as content — not as native Slack thread UI.

How long does a Pylon to Zendesk migration take? A typical data migration takes 5–10 business days: 1–2 days for extraction, 1–2 days for transformation, 1–2 days for sandbox testing, 1 day for production import, and 1 day for validation. If you are also rebuilding ticket forms, routing logic, or a Help Center, plan for 2–4 weeks total. The primary bottleneck is Pylon's Issues API rate limit of 10 requests per minute.

Does importing Pylon data affect Zendesk AI? It can. Zendesk Intelligent Triage trains on your ticket history to classify intent and sentiment. Bulk-importing unresolved or noisy Slack conversations degrades classification accuracy. The mitigation is to filter imports to resolved, high-quality issues, tag imported records with quality tiers, and give the AI 2–4 weeks to learn from clean data before importing the long tail. Monitor confidence scores in the Triage Performance dashboard — scores consistently below 0.7 indicate the model needs more clean training data.

What data cannot be migrated from Pylon to Zendesk? Slack channel metadata (channel IDs, workspace info), Macros, Ticket Forms, Automation rules, and AI Training Data cannot be migrated programmatically and must be manually recreated. Slack emoji reactions used for workflow states have no Zendesk equivalent. Multi-question survey responses require lossy transformation to fit Zendesk's binary satisfaction rating model.

Is there a native Pylon-to-Zendesk migration tool? No. Neither Pylon nor Zendesk offers a built-in migration tool for this direction. Help Desk Migration (HDM) lists Pylon as a supported source, but functionality should be verified directly with the vendor for your specific data objects. The most reliable method remains the API-based approach using Pylon's REST API for extraction and Zendesk's Ticket Import API for loading.

What happens to my Zendesk SLA metrics after migration? Imported tickets do not generate Zendesk SLA metrics (first reply time, resolution time, etc.). SLA reporting will only reflect tickets created natively in Zendesk post-migration. Tag imported tickets with pylon_import and exclude them from SLA policy scoping to avoid skewing your metrics.

Can I roll back if the migration fails? Yes, with caveats. Tickets tagged with pylon_import can be bulk-deleted via DELETE /api/v2/tickets/destroy_many (100 IDs per request). Organizations and Users created during migration can also be bulk-deleted, but only if they haven't been associated with non-imported tickets or other Zendesk objects. Always test the full import in a sandbox before production.

Frequently Asked Questions

Can I preserve Pylon Slack thread history in Zendesk?
Yes. Pylon Messages extracted via GET /issues/{id}/messages include full message_html and timestamps. When imported using Zendesk's Ticket Import API, these become timestamped comments. Slack-specific formatting like emoji reactions is converted to plain text. The history is preserved as content, not as native Slack thread UI.
How long does a Pylon to Zendesk migration take?
A typical data migration takes 5–10 business days: 1–2 days for extraction, 1–2 days for transformation, 1–2 days for sandbox testing, 1 day for production import, and 1 day for validation. If you also rebuild forms, routing logic, or a Help Center, plan for 2–4 weeks. The primary bottleneck is Pylon's Issues API rate limit of 10 requests per minute.
Does importing Pylon data affect Zendesk AI?
It can. Zendesk Intelligent Triage trains on ticket history to classify intent and sentiment. Bulk-importing unresolved or noisy Slack conversations degrades classification accuracy. Filter imports to resolved, high-quality issues and tag imported records so they can be excluded from AI training if needed.
What data cannot be migrated from Pylon to Zendesk?
Slack channel metadata, Macros, Ticket Forms, Automation rules, and AI Training Data cannot be migrated programmatically and must be manually recreated in Zendesk. Slack emoji reactions used for workflow states have no Zendesk equivalent. Multi-question survey responses require lossy transformation.
Is there a native Pylon-to-Zendesk migration tool?
No. Neither Pylon nor Zendesk offers a built-in migration tool for this direction. Help Desk Migration lists Pylon as a supported source, but the most reliable method is API-based extraction from Pylon and loading via Zendesk's Ticket Import API.

More from our Blog

Post-Migration QA: 20 Tests to Run After Your Help Desk Data Migration
Help Desk

Post-Migration QA: 20 Tests to Run After Your Help Desk Data Migration

Ensure your help desk migration is a success with this comprehensive 20-point post-migration QA checklist. This expert guide details the 20 essential tests needed to validate your data integrity, system functionality, user-friendliness, and performance . Learn exactly how to check everything from ticket data, attachments, and knowledge base articles to critical workflows, automations, and integrations before you go live. This process is your final line of defense against lost tickets, broken workflows, and unhappy customers.

Raaj Raaj · · 8 min read