---
title: "How to Migrate from Freshdesk to Gladly: Complete Technical Guide"
slug: how-to-migrate-from-freshdesk-to-gladly-complete-technical-guide
date: 2026-07-16
author: Raaj
categories: [Migration Guide, Gladly, Freshdesk]
excerpt: "A technical guide to migrating from Freshdesk to Gladly covering data mapping, API limits, text-only import constraints, and step-by-step cutover process."
tldr: Freshdesk to Gladly is a data-model translation from tickets to customer timelines. Gladly's historical import is text-only with no attachments. Plan 2 to 4 weeks for mid-size instances.
canonical: https://clonepartner.com/blog/how-to-migrate-from-freshdesk-to-gladly-complete-technical-guide/
---

# How to Migrate from Freshdesk to Gladly: Complete Technical Guide


# How to Migrate from Freshdesk to Gladly: Complete Technical Guide

> [!NOTE]
> **TL;DR: Freshdesk to Gladly Migration**
>
> Migrating from Freshdesk to Gladly is a data-model translation, not a field-mapping exercise. Freshdesk organizes support around discrete tickets. Gladly organizes support around the customer, storing all interactions in a single lifelong Conversation Timeline with no ticket numbers. The single biggest risk is **silent data loss**: Gladly's documented historical import is text-only and does not support attachments, images, recordings, metrics, or routing assignments. Imported history is not searchable or reportable in Gladly — it is reference-only on the customer profile. Realistic timeline: **2 to 4 weeks** for a mid-size instance (10,000 to 100,000 tickets). Freshdesk Automations, SLA Policies, and Dispatch Rules cannot be migrated programmatically and must be rebuilt manually. Teams with fewer than 5,000 tickets and simple schemas can attempt a scripted DIY migration. For anything larger, or with zero-downtime requirements, a managed migration service is the safer path.

## What Is a Freshdesk to Gladly Migration?

A **Freshdesk to Gladly migration** extracts tickets, contacts, companies, conversations, agents, groups, tags, custom fields, and solution articles from Freshdesk's ticket-centric helpdesk and loads them into Gladly as Customers, Conversation Items, Agents, Teams, Inboxes, Topics, Custom Attributes, and Answers.

This is a data-model translation. You are converting a system built around individual ticket lifecycles into a system built around lifelong customer relationships. Every Freshdesk ticket that belongs to the same requester must be folded into a single Gladly Customer profile, with each ticket's conversation thread becoming a set of Conversation Items on that customer's timeline.

One nuance that matters: Gladly does not use one endless Conversation object per customer. The customer's full history lives in the **Conversation Timeline**, while individual **Conversations** are time-bounded and default to a 24-hour window (configurable per brand). That affects how you represent multiple Freshdesk tickets from the same customer. ([help.gladly.com](https://help.gladly.com/docs/what-is-a-conversation))

For the reverse direction, see [How to Migrate Gladly to Freshdesk: Data Mapping & API Limits](https://clonepartner.com/blog/blog/how-to-migrate-gladly-to-freshdesk-data-mapping-api-limits/).

### Why Teams Move from Freshdesk to Gladly

Teams leave Freshdesk for three platform-specific reasons:

1. **Person-centric model over ticket-centric model.** Gladly replaces discrete ticket numbers with a single, continuous conversation per customer across all channels — email, chat, SMS, voice, social. Agents see every past interaction in one timeline instead of searching for ticket IDs. In official customer stories, Deckers said its prior ticket-based CRM could not meet its goals and later reported a 40 percent service-level improvement within a month, while Birdies said ticketing created duplicate work and hid repeat contacts. ([help.gladly.com](https://help.gladly.com/docs/what-is-a-conversation))
2. **Native omnichannel routing.** Gladly treats channel-switching (chat to phone to email) as a single thread. Freshdesk requires add-ons for voice and treats each channel interaction as a separate ticket.
3. **B2C relationship focus and pricing model.** Gladly is purpose-built for e-commerce and retail brands that measure customer lifetime value, not just ticket resolution time. Gladly uses per-agent pricing with unlimited conversations, whereas Freshdesk's pricing scales with ticket volume and add-on modules.

For a deeper look at Gladly's architecture and capabilities, see our [Ultimate Guide to Mastering Gladly](https://clonepartner.com/blog/blog/ultimate-guide-gladly-2026/).

### The Architectural Differences That Make This Migration Non-Trivial

- **Tickets vs. Timelines.** Freshdesk creates a new ticket for every customer issue. Gladly has no ticket object. All interactions for a customer live on a single Conversation Timeline. You must group all Freshdesk tickets by requester email and flatten them into one customer record.
- **Custom fields live on different objects.** Freshdesk supports ticket-level custom fields (prefixed with `cf_` in the API). Gladly does not have traditional ticket-level custom fields. Custom data must be mapped to Gladly Customer Profile attributes or embedded in conversation item text.
- **Historical import is text-only.** Gladly's historical import does not support attachments, images, recordings, metrics, or routing/conversation assignments. This is a hard platform constraint, not a tooling gap. ([help.gladly.com](https://help.gladly.com/implementation/docs/historical-conversation-item-data-import/))
- **One open conversation per customer.** Gladly allows only one open Conversation per customer at a time. If a customer has multiple unresolved Freshdesk tickets, you cannot simply import them all as open Conversations. ([help.gladly.com](https://help.gladly.com/docs/what-is-a-conversation))

## How Does Freshdesk Data Map to Gladly Objects?

The most critical phase of this project is mapping the Freshdesk data model to Gladly's. If you map objects incorrectly, you will orphan historical messages or create duplicate customer profiles.

| **Freshdesk Object** | **Gladly Object** | **Notes and Caveats** |
|---|---|---|
| Ticket | Conversation Items (on Customer Timeline) | Each ticket becomes a set of timeline items under the matching Customer. No 1:1 ticket equivalent exists in Gladly. |
| Contact | Customer | Matched by email. Email is a unique identifier in Gladly. Phone and name are also stored on the Customer profile. |
| Company | Customer attribute (or external lookup via Lookup Adaptor) | Gladly has no native Company object. Company name must be stored as a custom attribute on the Customer profile, or surfaced at runtime via Gladly's Lookup Adaptor. |
| Conversation (replies/notes) | Conversation Item | Each reply or note becomes a separate Conversation Item on the customer's timeline. |
| Agent | Agent | Mapped by email. Agents must be provisioned in Gladly before import. Historical assignment is not preserved in the import. |
| Group | Team / Inbox | Freshdesk Groups map to Gladly Teams or Inboxes depending on routing configuration. |
| Tag | Topic | Freshdesk Tags map to Gladly Topics. Topics must be pre-created in Gladly. |
| Custom Field (ticket-level) | Customer Custom Attribute | Gladly does not support ticket-level custom fields. Data must move to the Customer profile or be appended to conversation item text. |
| Product | Brand | Freshdesk Products map to Gladly Brands. Multi-product instances require explicit brand mapping before import. |
| Solution Article | Answer | Gladly Answers can be imported via CSV with Markdown formatting. |
| Attachment | **Not supported in historical import** | Gladly's import is text-based only. Attachments must be stored externally and linked. |
| Automation / Dispatch Rule | Rule (manual rebuild) | Cannot be migrated programmatically. Must be recreated in Gladly's Rules engine and People Match. |
| SLA Policy | SLA (manual rebuild) | No programmatic migration path. |
| Canned Response | Answer (manual rebuild) | Can be imported as Answers via CSV but requires manual formatting. |

Gladly's published CSV schema has no source ticket ID, no status field, no privacy flag, and no attachment field. It requires `customer_email`, `body`, `activityType`, and `occurredAt`, with optional `title`, `link.url`, `link.title`, `sourceName`, and `customAttribute`. Gladly's own Freshdesk recipe carries ticket identity in the `title` field using the format `Ticket # {id} - {subject}`. ([help.gladly.com](https://help.gladly.com/implementation/docs/historical-conversation-item-data-import/))

### Field-Level Mapping Details

Three field mappings cause the most confusion:

**Status and priority.** Freshdesk stores these as numeric codes. Default status values are Open (`2`), Pending (`3`), Resolved (`4`), Closed (`5`). Default priority values are Low (`1`), Medium (`2`), High (`3`), Urgent (`4`). Gladly's historical CSV has no native column for either. Preserve them in the title, body, or an audit file. ([developers.freshdesk.com](https://developers.freshdesk.com/api/))

**Source to activityType.** Freshdesk source codes include Email (`1`), Portal (`2`), Phone (`3`), Chat (`7`), Feedback Widget (`9`), and Outbound Email (`10`). Gladly's historical import accepts only `EMAIL`, `ISSUE`, `SMS`, or `SURVEY`, so Portal, Chat, and Phone usually collapse into `ISSUE`. ([developers.freshdesk.com](https://developers.freshdesk.com/api/))

**Custom fields and identity.** Freshdesk ticket custom fields are ticket-scoped (`cf_` prefix), while Gladly's `customAttribute` is customer-scoped. If a customer had multiple Freshdesk tickets with conflicting custom field values, you must write logic to determine which value survives — usually the most recently updated ticket dictates the final value. Freshdesk contacts can also carry `other_emails`, but Gladly groups rows by one `customer_email`. Imported phone numbers are marked `OTHER`, not `MOBILE`, so SMS readiness is not automatic. ([developers.freshdesk.com](https://developers.freshdesk.com/api/))

### What Has No Clean Equivalent in Gladly?

- **Ticket status lifecycle** (Open, Pending, Resolved, Closed). Gladly Conversations are either open or closed. There is no Pending or Resolved state.
- **Ticket priority** (Low, Medium, High, Urgent). Gladly does not use priority levels on conversations.
- **Private note state.** Freshdesk conversations have a `private` boolean. Gladly's historical CSV schema has no privacy field. Prefix internal notes with a clear marker (e.g., `[INTERNAL NOTE]`) or exclude them.
- **Satisfaction ratings.** Historical CSAT scores from Freshdesk do not transfer. Gladly has its own CSAT mechanism.
- **Time-tracking and SLA metrics.** Historical SLA data (first response time, resolution time) does not migrate. Export these to a data warehouse before cutover if you need reporting continuity.
- **Multi-level company hierarchies.** Gladly does not have a native Company object. Consider Gladly's Lookup Adaptor (see below) for surfacing company data at runtime.

### Alternative to Full Migration: Gladly's Lookup Adaptor

Not all Freshdesk data needs to be flattened into Gladly. Gladly's **Lookup Adaptor** allows agents to retrieve external data in real time from a third-party system and display it within the Customer profile. For teams that want to keep company hierarchies, order history, or other structured data in an external system (CRM, ERP, data warehouse), the Lookup Adaptor can surface that data without migrating it. This is particularly useful for data that does not fit Gladly's customer-scoped attribute model, such as multi-level company hierarchies or per-order metadata. The Lookup Adaptor requires a hosted API endpoint that Gladly calls with the customer identifier. ([developer.gladly.com](https://developer.gladly.com/rest/))

## What Are the Migration Approaches?

Choosing the right method depends on ticket volume, attachment requirements, and engineering bandwidth.

| **Approach** | **How It Works** | **Best For** | **Complexity** | **Risks** |
|---|---|---|---|---|
| Gladly Historical Import (CSV) | Export from Freshdesk, transform to Gladly's CSV template, upload via Gladly's implementation team Dropbox. | Small to mid-size (under 50K tickets), text-only history. | Medium | Text-only. No attachments. Requires Gladly Professional Services engagement. |
| Freshdesk Account Export + Custom Transform | Use Freshdesk's full account export (XML), then build Gladly CSV. | One-time full-history migration including archived tickets. | Medium | Identity cleanup and attachment externalization required. |
| API-Based Custom Script | Extract via Freshdesk REST API v2, transform in code, load via Gladly CSV import or REST API. | Teams with developer resources and complex field mapping. | High | Must handle rate limits. Freshdesk API defaults to last 30 days. |
| Third-Party Migration Tool | Automated mapping tools like Help Desk Migration (charges per record, typically $1–$5 per 100 records depending on volume tier). | Simple schemas, quick turnaround. | Low | Limited customization. May not handle Gladly's person-centric model correctly. |
| Managed Migration Service | A dedicated team handles extraction, transformation, loading, and validation. | Enterprise volumes, complex custom fields, zero-downtime requirements. | Low (for you) | Lowest risk. Higher cost (typically $3,000–$15,000 depending on scope). |

**When to use which:**

- **Under 5,000 tickets, no attachments needed:** Gladly Historical Import via CSV.
- **5,000 to 50,000 tickets with custom fields:** API-based extraction with CSV load, or managed service.
- **Over 50,000 tickets or zero-downtime requirement:** Managed migration service.

An important distinction: Freshdesk's ticket export UI does not include full conversation threads or archived tickets. The full account export does. If you need complete history, the UI export alone is the wrong starting point. ([support.freshdesk.com](https://support.freshdesk.com/support/solutions/articles/225158-how-do-i-export-my-tickets-from-freshdesk-))

Treat ongoing sync as a separate integration project after cutover. Gladly's REST and Lookup APIs work for customer context and enrichment, but historical ticket replay is a different workload.

For comparison, see our guides on [migrating from Zendesk to Gladly](https://clonepartner.com/blog/blog/how-to-migrate-zendesk-to-gladly/) and [migrating from Intercom to Gladly](https://clonepartner.com/blog/blog/how-to-migrate-intercom-to-gladly/) — both share Gladly-side constraints but differ significantly in source extraction complexity.

## How Do API Rate Limits and Import Constraints Shape the Architecture?

Architect this as: extract from Freshdesk, normalize into customer-keyed rows, then load through Gladly's historical CSV import. Writing historical tickets directly through Gladly's live REST API is usually the wrong shape for bulk historical migration. ([help.gladly.com](https://help.gladly.com/implementation/docs/historical-conversation-item-data-import/))

### Freshdesk Extraction: API Limits and Endpoints

Freshdesk's REST API v2 uses HTTP Basic Auth with your API key as the username. The base URL is `https://<domain>.freshdesk.com/api/v2/`.

**Rate limits by plan (per minute, account-wide):**

| **Freshdesk Plan** | **API Calls per Minute** |
|---|---|
| Free | 100 |
| Growth | 200 |
| Pro | 400 |
| Enterprise | 700 |
| Trial | 50 |

The List Tickets endpoint (`GET /api/v2/tickets`) has a per-endpoint sub-limit. On the Growth plan, you can call it a maximum of 20 times per minute. With 100 records per page, that means a ceiling of **2,000 ticket headers per minute** from this endpoint alone.

The Filter Tickets endpoint (`GET /api/v2/search/tickets`) is capped at **10 pages** with 30 results per page — a hard ceiling of 300 results per filter query. To export more, segment queries by date range.

Three critical caveats for extraction:

1. **The default API scope is the last 30 days.** Use the `updated_since` parameter for incremental pulls, or use the full account export for complete history. ([developers.freshdesk.com](https://developers.freshdesk.com/api/))
2. **`include=conversations` returns at most 10 conversations per ticket.** For tickets with more than 10 replies or notes, use the separate `/api/v2/tickets/{id}/conversations` endpoint for full threads. ([developers.freshdesk.com](https://developers.freshdesk.com/api/))
3. **Archived tickets are excluded from standard listing.** Both the `GET /api/v2/tickets` endpoint and the Filter endpoint exclude archived tickets. Use the Account Export API or the individual `/api/v2/tickets/archived/{id}` endpoint.

Key extraction endpoints:

- `GET /api/v2/tickets` with `per_page=100` and `updated_since` for incremental pulls
- `GET /api/v2/tickets/{id}/conversations` for full thread with all replies and notes
- `GET /api/v2/contacts` for requester data
- `GET /api/v2/companies` for company associations
- `GET /api/v2/agents` for agent roster
- `GET /api/v2/groups` for group structure
- `GET /api/v2/ticket_fields` to discover custom field API names (`cf_` prefix differs from UI labels)
- `GET /api/v2/solutions/categories` for knowledge base articles

### Gladly Load: Import Options and API Versions

Gladly's REST API currently uses two version prefixes: `/api/v1/` for older endpoints (including customer profile reads) and `/api/v2/` for newer endpoints (including customer profile creation). Check Gladly's API changelog for current version status before building integrations. The examples in this guide use the version documented at the time of writing.

Gladly enforces a default rate limit of **10 requests per second** across all HTTP methods (GET, POST, PUT, PATCH, DELETE). Tracked via response headers `Ratelimit-Limit-Second` and `Ratelimit-Remaining-Second`. Exceeding the limit returns HTTP 429.

Gladly offers two import paths:

**1. Historical Conversation Item Import** (via Gladly's implementation team). Upload a CSV or JSON file to a Gladly-provided Dropbox link. Gladly's Professional Services team processes the import. Required fields: `customer_email`, `body` (25,000 characters or fewer), `activityType`, and `occurredAt`. The `title` field has a 100-character limit. Gladly recommends batches of **500,000 rows** and suggests completing the bulk import two weeks before launch with a delta import two days after. ([help.gladly.com](https://help.gladly.com/implementation/docs/historical-conversation-item-data-import/))

**2. REST API.** Use the Customers API to create customer profiles (`POST /api/v2/customer-profiles`) and the Timeline Items API to add conversation items to a customer's timeline. Items created via the Timeline Items API are **non-routable and non-searchable** aside from email or phone number on the payload.

> [!WARNING]
> **Gladly's historical import is text-based only.** It does not support the import of historical images, recordings, attachments, metrics, or routing/conversation assignments. Imported history (other than contact information) is not searchable or reportable in Gladly. Plan for this constraint before you begin. ([help.gladly.com](https://help.gladly.com/implementation/docs/historical-conversation-item-data-import/))

### Throughput Math

On the Gladly REST API at 10 requests per second, you can create approximately **36,000 records per hour** assuming one call per record with no retries. In practice, with 429 backoffs, 409 conflicts on duplicate emails, and network latency, expect **20,000 to 25,000 records per hour** as a realistic sustained rate.

On the Freshdesk side, an Enterprise plan (700 calls/min) can pull ticket headers quickly, but fetching full conversations for each ticket requires an additional call per ticket. For a 50,000-ticket instance with an average of 5 replies per ticket, full extraction takes approximately 2 to 4 hours at Enterprise-tier rate limits. On a Growth plan (200 calls/min), the same extraction takes 8 to 12 hours.

For the CSV historical import path, Gladly's batch processing speed is managed by their Professional Services team, so your bottleneck is preparation and transformation, not load speed.

## What Is the Step-by-Step Process?

The order of operations matters. Loading conversation items before creating the parent Customer profile will cause orphaned records or 404 errors. Identity first, history second, cutover last.

**Step 1: Extract Agents, Groups, Tags, and Products from Freshdesk**

Pull the agent roster (`GET /api/v2/agents`), groups (`GET /api/v2/groups`), all tags used across tickets, and products (`GET /api/v2/products`). These must be provisioned in Gladly before any customer or conversation data is loaded. If your Freshdesk instance uses multiple Products, map each to a Gladly Brand before proceeding.

**Step 2: Provision Agents, Teams, Inboxes, Topics, and Brands in Gladly**

Create corresponding Agents in Gladly (matched by email). Map Freshdesk Groups to Gladly Teams or Inboxes. Create Topics in Gladly for each Freshdesk Tag you want to preserve. Map Freshdesk Products to Gladly Brands. Custom attributes must be pre-configured by a Gladly Support or Professional Services representative before they display on the Customer profile.

**Step 3: Extract and Deduplicate Contacts from Freshdesk**

Paginate through `GET /api/v2/contacts?per_page=100`. Deduplicate contacts by email — Freshdesk allows multiple contacts with the same email in rare edge cases. Gladly enforces email uniqueness, so duplicates must be merged before load. Choose one canonical email per contact from the `email` and `other_emails` fields.

**Step 4: Create Customer Profiles in Gladly**

For each deduplicated contact, create a Gladly Customer profile via the Customers API or CSV upload. Include name, email(s), phone(s), and any custom attributes mapped from Freshdesk custom fields.

```python
# Create Gladly Customer with retry logic
import requests
import time
import random

gladly_url = "https://<org>.gladly.com/api/v2/customer-profiles"
headers = {"Authorization": "Basic <token>", "Content-Type": "application/json"}

def create_customer(contact, max_retries=5):
    payload = {
        "name": contact["name"],
        "emails": [{"original": contact["email"]}],
        "phones": [{"original": contact.get("phone")}] if contact.get("phone") else [],
        "customAttributes": {"freshdesk_company": contact.get("company_name", "")}
    }

    for attempt in range(max_retries):
        response = requests.post(gladly_url, json=payload, headers=headers)

        if response.status_code == 201:
            return response.json()["id"]

        if response.status_code == 409:
            # Duplicate email — retrieve existing customer and update
            existing = lookup_customer_by_email(contact["email"])
            return existing["id"]

        if response.status_code == 429:
            # Rate limited — exponential backoff with jitter
            wait = min(2 ** attempt + random.uniform(0, 1), 30)
            logging.warning(f"Rate limited. Retrying in {wait:.1f}s (attempt {attempt+1})")
            time.sleep(wait)
            continue

        # Log unexpected errors for manual review
        logging.error(f"Unexpected {response.status_code} for {contact['email']}: {response.text}")
        break

    return None
```

**Step 5: Extract Tickets with Full Conversations from Freshdesk**

For each ticket, fetch the full thread including all replies and notes. Use the dedicated conversations endpoint rather than `include=conversations` on the ticket endpoint, since the include parameter returns at most 10 entries per ticket:

```python
# Freshdesk: get full conversation thread with pagination
def get_all_conversations(domain, ticket_id, api_key):
    conversations = []
    page = 1
    while True:
        url = f"https://{domain}.freshdesk.com/api/v2/tickets/{ticket_id}/conversations?page={page}&per_page=100"
        response = requests.get(url, auth=(api_key, "X"))
        if response.status_code == 429:
            retry_after = int(response.headers.get("Retry-After", 60))
            time.sleep(retry_after)
            continue
        batch = response.json()
        if not batch:
            break
        conversations.extend(batch)
        page += 1
    return conversations
```

Group all tickets by requester email. This grouping is what allows you to reconstruct the customer timeline in Gladly.

**Step 6: Transform and Load Conversation Items**

Transform each Freshdesk ticket reply and note into a Gladly historical conversation item. Preserve the original timestamp, author, and message body. Strip inline image references that point to Freshdesk-hosted URLs (e.g., `https://<domain>.freshdesk.com/attachments/...`) — these URLs stop working when the Freshdesk account is deactivated.

If using the CSV import path, each row should match Gladly's published schema:

```python
row = {
    'customer_email': email,
    'customer_name': contact.get('name'),
    'customer_phone': e164(contact.get('phone')),
    'title': truncate(f'Ticket #{ticket_id} - {subject}', 100),
    'body': render_body(ticket_or_note),
    'activityType': map_activity_type(source_code),
    'occurredAt': to_iso8601(timestamp),
    'link.url': freshdesk_ticket_url(ticket_id),
    'link.title': 'Open in Freshdesk',
    'sourceName': 'Freshdesk'
}
```

Put only stable customer data into `customAttribute`. Ticket-specific metadata belongs in the body, the title, or a parallel audit file. ([help.gladly.com](https://help.gladly.com/implementation/docs/historical-conversation-item-data-import/))

**Step 7: Separate Open Backlog from Closed History**

Do not treat unresolved Freshdesk tickets as passive archive data. Gladly allows only one open Conversation per customer, so you cannot import multiple open tickets for the same person. Decide which open records will be consolidated, recreated as live work, or closed and imported as history. This is a cutover workflow decision, not a data transformation. ([help.gladly.com](https://help.gladly.com/docs/what-is-a-conversation))

**Step 8: Implement Delta Sync**

Tickets created or updated between the bulk extraction and go-live must be captured. Implement a delta sync using the `updated_since` parameter on `GET /api/v2/tickets`:

1. Record the timestamp of your bulk extraction start.
2. After the bulk import is processed by Gladly, re-query Freshdesk with `updated_since={bulk_extraction_timestamp}`.
3. For each net-new or updated ticket, check whether the customer already exists in Gladly (by email lookup). If so, append the new conversation items. If not, create the customer first.
4. Deduplicate by checking the `title` field (which contains the Freshdesk ticket ID) to avoid importing the same conversation item twice.
5. Gladly recommends running the delta import **two days after go-live** to capture the tail of tickets resolved during the transition window.

**Step 9: Import Knowledge Base Articles**

Extract Freshdesk Solution Articles via `GET /api/v2/solutions/categories/{id}/folders/{id}/articles`. Transform article content from HTML to Gladly's Markdown format. Import as Gladly Answers via CSV upload.

**Step 10: Validate**

Run record-count reconciliation, field-level spot checks, timestamp verification, and agent-facing UAT before go-live.

## How Long Does a Freshdesk to Gladly Migration Take?

| **Phase** | **Duration** | **Dependencies** |
|---|---|---|
| Discovery and field mapping | 2 to 3 days | Access to both Freshdesk admin and Gladly sandbox |
| Script development or tool configuration | 3 to 5 days | Finalized field mapping, API credentials |
| Test migration (sandbox) | 2 to 3 days | Working scripts, sample data |
| Data cleanup and deduplication | 1 to 2 days | Test migration results, duplicate report |
| Production migration | 1 to 3 days | Go-live approval, maintenance window |
| Delta sync (catch-up) | 1 day | Cutover timestamp, coordinated with agents |
| Post-migration validation and UAT | 2 to 3 days | Agent availability for testing |
| **Total** | **12 to 20 business days** | |

For small instances under 5,000 tickets, the total can compress to **5 to 8 business days**. For enterprise instances over 100,000 tickets with complex custom fields and multiple brands, expect **3 to 5 weeks**.

### Rollback Plan

Gladly does not have a native bulk-delete or undo import function. If the migration goes wrong, rollback requires deleting customer profiles individually via the `DELETE /api/v1/customer-profiles/{profileId}` endpoint. Conversation items associated with a deleted profile are cascade-deleted. At Gladly's 10 req/s rate limit, deleting 50,000 profiles takes approximately 83 minutes of sustained API calls, assuming no errors. In practice, with backoffs, expect 2 to 3 hours for a full rollback of a mid-size import.

This makes test migrations in a Gladly sandbox environment critical before touching production. Request a sandbox from your Gladly implementation contact before beginning development.

## What Do Customers and Agents Notice During Migration?

If planned correctly, end customers notice very little. The recommended approach is to route new incoming requests to Gladly while keeping Freshdesk active for reference on open tickets. Run both systems in parallel for 1 to 2 weeks until all open Freshdesk tickets are resolved, then perform a final delta sync and deactivate Freshdesk.

Agents should expect three operational changes:

1. **Imported history is for reference, not reporting.** Historical imports (other than contact information) are not searchable or reportable in Gladly. Agents can see the history when viewing a customer profile but cannot find it through global search. For reporting continuity, export Freshdesk data to a data warehouse (e.g., via Freshdesk Analytics or the API) before migration, and maintain Freshdesk in read-only mode until the reporting transition is complete. ([help.gladly.com](https://help.gladly.com/implementation/docs/historical-conversation-item-data-import/))
2. **No ticket numbers.** The biggest user-facing change. Agents accustomed to referencing ticket IDs must adapt to searching by customer name or email. Source ticket numbers can be preserved in the conversation item title for reference.
3. **Imported phone numbers come in as `OTHER`, not `MOBILE`.** SMS readiness is not automatic — phone numbers may need to be re-categorized after import.

For a comprehensive pre-migration planning checklist, see our [Help Desk Data Migration Checklist](https://clonepartner.com/blog/blog/help-desk-data-migration-checklist/).

## What Are the Edge Cases and Known Limitations?

### Attachments Are Not Importable

Gladly's historical import explicitly does not support images, recordings, attachments, metrics, or routing assignments. This is a hard platform constraint, not a tooling gap. Options for preserving attachment context:

1. Store attachments in an external system (S3, Google Drive) and include the link in the conversation item body using the `link.url` and `link.title` CSV fields.
2. Keep read-only access to Freshdesk for a transition period so agents can look up attachments when needed.
3. Accept the data loss for attachments that are unlikely to be referenced.

### Freshdesk Inline Images

Ticket descriptions and replies in Freshdesk often contain `<img>` tags pointing to Freshdesk-hosted URLs (e.g., `https://<domain>.freshdesk.com/attachments/...`). These URLs stop working when the Freshdesk account is deactivated. Download all inline images during extraction and re-host them (e.g., on S3 with public read access) before loading into Gladly or deactivating Freshdesk.

### Gladly API Read Truncation

When reading data *from* Gladly — relevant for delta sync or validation — the Conversations API returns a maximum of **100 conversations per customer** and caps timeline items at **1,000 per conversation**. The API does not paginate beyond these limits. Truncation is flagged only by the `Gladly-Limited-Data` response header. If you do not check this header during validation, you will silently miss data for high-volume customers. ([developer.gladly.com](https://developer.gladly.com/rest/))

### Archived Tickets in Freshdesk

The standard `GET /api/v2/tickets` endpoint does not return archived tickets. The Filter Tickets endpoint explicitly excludes them. Use the Account Export API or the individual `/api/v2/tickets/archived/{id}` endpoint to access archived ticket data.

### Multiple Open Tickets Per Customer

Freshdesk allows unlimited open tickets per requester. Gladly allows only one open Conversation per customer at a time. If a customer has five unresolved Freshdesk tickets, you must consolidate them, close all but one, or handle them through a separate backlog triage process before cutover. ([help.gladly.com](https://help.gladly.com/docs/what-is-a-conversation))

### Private Notes Have No CSV Field

Freshdesk conversations have a `private` boolean to distinguish internal notes from customer-facing replies. Gladly's historical CSV schema has no privacy field. Prefix internal notes with a clear marker (e.g., `[INTERNAL NOTE]`) or exclude them from the import deliberately.

### Custom Attributes Require Pre-Configuration

On the Gladly side, custom attributes must be pre-configured by a Gladly Support or Professional Services representative before they display on the Customer profile. On the Freshdesk side, use `GET /api/v2/ticket_fields` to discover the correct API field names — they use the `cf_` prefix and differ from the UI labels.

### Multi-Brand / Multi-Product Mapping

Freshdesk supports multiple Products, each with its own portal and email address. Gladly supports multiple Brands, each with independent channel configurations. If your Freshdesk instance uses Products, create a corresponding Gladly Brand for each and tag imported conversation items with the correct brand. Failing to map Products to Brands will route historical context to the wrong brand in Gladly, confusing agents who work across brands.

### Post-Migration Reporting Gap

Imported history is not reportable in Gladly. This creates a gap: pre-migration metrics (CSAT, first response time, resolution time, volume trends) are only available from Freshdesk. Before deactivating Freshdesk:

1. Export all historical reports from Freshdesk Analytics.
2. Use the Freshdesk API to extract raw ticket data into a data warehouse (BigQuery, Snowflake, Redshift).
3. Maintain Freshdesk in read-only mode until historical reporting has been rebuilt from the warehouse.
4. Gladly's reporting starts fresh from the go-live date. Plan for a 30 to 90 day ramp before trend data becomes meaningful in Gladly's native reporting.

## How Should You Validate the Migration?

Never trust a "200 OK" response as proof of data integrity. Run discrete validation tests:

1. **Record-count reconciliation.** Compare total contacts, tickets, and conversation entries between Freshdesk and Gladly. The Gladly Conversation Item count will be higher than the Freshdesk ticket count due to the one-to-many mapping (one ticket becomes multiple items).
2. **Field-level spot check.** Select a random 5% sample of customer profiles and verify that email, name, phone, custom attributes, and conversation history match the source.
3. **Timestamp verification.** Confirm that conversation items appear in chronological order on the Gladly timeline. Out-of-order timestamps indicate a transformation bug.
4. **Agent assignment check.** Verify that agents appear correctly in Gladly and that team/inbox assignments match the original group structure.
5. **Legacy link verification.** Open 10 to 15 imported conversation items and confirm that `link.url` values resolve to the correct Freshdesk ticket.
6. **Knowledge base review.** Open imported Answers in Gladly and compare content and formatting against the original Freshdesk Solution Articles.
7. **Truncation monitoring.** Use `/api/v1/customer-profiles` to spot-check high-volume customers. Check for the `Gladly-Limited-Data` response header, which indicates the API has truncated results. ([developer.gladly.com](https://developer.gladly.com/rest/))
8. **Brand/product mapping check.** For multi-brand instances, verify that conversation items are tagged to the correct Gladly Brand by sampling 5 to 10 customers from each Freshdesk Product.
9. **UAT with agents.** Have 2 to 3 agents use Gladly in a sandbox for a day. Ask them to search for specific customers and verify that the timeline is complete and readable.

Keep Freshdesk available in read-only mode until business owners sign off on the migration.

### Risk Register

| **Risk** | **Likelihood** | **Impact** | **Mitigation** |
|---|---|---|---|
| Attachment data loss | High (platform constraint) | Medium — most attachments are not re-referenced | Store attachments externally, link from conversation item body |
| Duplicate customer profiles | Medium | High — causes split history | Deduplicate by email before load, handle 409 errors |
| Rate limiting causes incomplete load | Medium | Medium — recoverable with retry | Implement exponential backoff with jitter, monitor `Ratelimit-Remaining-Second` |
| Freshdesk inline images break post-cutover | High | Medium — affects readability | Download and re-host images before deactivating Freshdesk |
| Custom field data loss | Medium | Medium — depends on field criticality | Map all `cf_` fields to Customer Custom Attributes or embed in text |
| Open ticket collisions | Medium | High — blocks agent workflow | Backlog triage before cutover — Gladly allows one open conversation per customer |
| Validation blind spots from API truncation | Medium | High — silently missing data | Row-level totals plus `Gladly-Limited-Data` header monitoring |
| Reporting continuity gap | High (platform constraint) | High — no historical metrics in Gladly | Export Freshdesk data to warehouse before migration |
| Multi-brand misrouting | Low (if mapped) / High (if not) | High — wrong context shown to agents | Explicit Product-to-Brand mapping in transformation layer |
| Delta sync gaps | Medium | Medium — missing recent tickets | Timestamp-based incremental pull with deduplication by ticket ID |

## Should You Build In-House or Use a Managed Service?

### When In-House Makes Sense

- Your instance has fewer than 5,000 tickets.
- You have a developer who can dedicate 2 to 3 weeks.
- You do not need attachment migration.
- You have a simple schema with fewer than 5 custom fields.
- You have a single Freshdesk Product (no multi-brand complexity).
- You can tolerate some downtime during cutover.

### When In-House Gets Expensive

The hidden cost of a DIY Freshdesk to Gladly migration is not the initial script. It is the second and third re-migration when edge cases surface: duplicate contacts causing 409 errors, custom field values silently failing validation, inline images breaking after Freshdesk deactivation, the delta sync that must cover tickets created between extraction and go-live, and the open-ticket consolidation that nobody scoped upfront.

DIY API-based migrations typically require 80 to 160 engineering hours for a mid-size instance (10,000 to 50,000 tickets). Based on industry benchmarks for helpdesk migration projects, most teams underestimate total engineering time by 50% to 100%, primarily due to edge cases discovered during test migrations.

### Cost Comparison

| **Approach** | **Typical Cost** | **Timeline** | **Best For** |
|---|---|---|---|
| DIY (API scripts) | 80–160 engineering hours (~$8K–$24K at $100–$150/hr fully loaded) | 2–4 weeks | Under 5K tickets, simple schema |
| Third-party tool (e.g., Help Desk Migration) | $1–$5 per 100 records + setup fee | 1–2 weeks | Simple schemas, under 20K tickets |
| Gladly Professional Services (CSV import) | Varies by contract; included in some implementation packages | 2–3 weeks (including 2-week pre-launch bulk + delta) | All sizes; required for historical CSV import |
| Managed migration service | $3,000–$15,000 depending on volume, custom fields, and brand count | 2–5 weeks | Over 10K tickets, multi-brand, zero-downtime |

### When to Use a Managed Service

- Your instance has over 10,000 tickets.
- You need zero downtime during cutover.
- You have complex custom fields or multi-brand configurations.
- Your team cannot dedicate engineering time for 3+ weeks.
- You need attachment externalization (download, re-host, re-link) handled for you.

For a deeper look at why teams choose Gladly, see [Why Teams Are Choosing Gladly](https://clonepartner.com/blog/blog/why-migrating-to-gladly/).

## What a Safe Freshdesk to Gladly Migration Looks Like

A Freshdesk to Gladly migration is not a CSV upload. It is a data-model translation that requires careful identity mapping, deduplication, and validation. The platform differences are real: Gladly's text-only historical import, its 10-requests-per-second rate limit, its lack of a native Company object, the one-open-conversation-per-customer constraint, and imported history that is reference-only and non-searchable.

Get the mapping right. Choose one canonical email per customer. Test in a sandbox. Plan for attachment loss. Separate open backlog from closed history. Export historical metrics to a data warehouse before cutover. Map Products to Brands. Implement delta sync with deduplication. Run both systems in parallel during cutover. That is how you avoid a re-migration.

> Need help migrating from Freshdesk to Gladly? Our engineers have handled hundreds of helpdesk migrations with custom field mapping and zero-downtime cutover. Book a free 30-minute scoping call.
>
> [Talk to us](https://cal.com/clonepartner/meet?duration=30)

## Frequently asked questions

### Can I migrate Freshdesk to Gladly without losing data?

You can migrate all text-based conversation history without loss. However, Gladly's historical import does not support attachments, inline images, recordings, or SLA metrics. These data types will not transfer through any standard import path. The practical workaround is storing attachments in an external archive and linking to them from the imported conversation items.

### How long does a Freshdesk to Gladly migration take?

A small instance (under 5,000 tickets) takes 5 to 8 business days. A mid-size instance (10,000 to 50,000 tickets) takes 2 to 3 weeks. Enterprise instances over 100,000 tickets with complex schemas typically require 3 to 5 weeks including testing and validation.

### What data cannot be migrated from Freshdesk to Gladly?

Freshdesk Automations, Dispatch Rules, SLA Policies, Canned Responses (as functional macros), satisfaction survey results, time-tracking entries, and ticket-level custom field structures cannot be migrated programmatically. They must be rebuilt manually in Gladly. Attachments, images, and call recordings are also excluded from Gladly's historical import.

### Does Gladly have a native import tool for Freshdesk?

No. Gladly supports direct JSON imports from Zendesk but not from Freshdesk. For Freshdesk data, you must export and transform it into Gladly's CSV template format. Gladly's implementation team then processes the upload via a shared Dropbox link.

### How do I handle open Freshdesk tickets during migration to Gladly?

Gladly allows only one open Conversation per customer, so you cannot import multiple open tickets for the same person. Treat open work as a cutover workflow decision: consolidate, close, or recreate only the live backlog that still needs action. Run both systems in parallel for 1 to 2 weeks until open Freshdesk tickets are resolved.
