How to Migrate from Freshdesk to Gladly: Complete Technical Guide
A technical guide to migrating from Freshdesk to Gladly covering data mapping, API limits, text-only import constraints, and step-by-step cutover 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
How to Migrate from Freshdesk to Gladly: Complete Technical Guide
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)
For the reverse direction, see 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:
- 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)
- 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.
- 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.
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)
- 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)
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)
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)
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)
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)
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
privateboolean. 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)
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)
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 and migrating from 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)
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:
- The default API scope is the last 30 days. Use the
updated_sinceparameter for incremental pulls, or use the full account export for complete history. (developers.freshdesk.com) include=conversationsreturns at most 10 conversations per ticket. For tickets with more than 10 replies or notes, use the separate/api/v2/tickets/{id}/conversationsendpoint for full threads. (developers.freshdesk.com)- Archived tickets are excluded from standard listing. Both the
GET /api/v2/ticketsendpoint 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/ticketswithper_page=100andupdated_sincefor incremental pullsGET /api/v2/tickets/{id}/conversationsfor full thread with all replies and notesGET /api/v2/contactsfor requester dataGET /api/v2/companiesfor company associationsGET /api/v2/agentsfor agent rosterGET /api/v2/groupsfor group structureGET /api/v2/ticket_fieldsto discover custom field API names (cf_prefix differs from UI labels)GET /api/v2/solutions/categoriesfor 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)
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.
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)
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.
# 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 NoneStep 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:
# 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 conversationsGroup 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:
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)
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)
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:
- Record the timestamp of your bulk extraction start.
- After the bulk import is processed by Gladly, re-query Freshdesk with
updated_since={bulk_extraction_timestamp}. - 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.
- Deduplicate by checking the
titlefield (which contains the Freshdesk ticket ID) to avoid importing the same conversation item twice. - 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:
- 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)
- 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.
- Imported phone numbers come in as
OTHER, notMOBILE. 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.
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:
- Store attachments in an external system (S3, Google Drive) and include the link in the conversation item body using the
link.urlandlink.titleCSV fields. - Keep read-only access to Freshdesk for a transition period so agents can look up attachments when needed.
- 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)
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)
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:
- Export all historical reports from Freshdesk Analytics.
- Use the Freshdesk API to extract raw ticket data into a data warehouse (BigQuery, Snowflake, Redshift).
- Maintain Freshdesk in read-only mode until historical reporting has been rebuilt from the warehouse.
- 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:
- 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).
- 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.
- Timestamp verification. Confirm that conversation items appear in chronological order on the Gladly timeline. Out-of-order timestamps indicate a transformation bug.
- Agent assignment check. Verify that agents appear correctly in Gladly and that team/inbox assignments match the original group structure.
- Legacy link verification. Open 10 to 15 imported conversation items and confirm that
link.urlvalues resolve to the correct Freshdesk ticket. - Knowledge base review. Open imported Answers in Gladly and compare content and formatting against the original Freshdesk Solution Articles.
- Truncation monitoring. Use
/api/v1/customer-profilesto spot-check high-volume customers. Check for theGladly-Limited-Dataresponse header, which indicates the API has truncated results. (developer.gladly.com) - 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.
- 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.
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.
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.

