Skip to content

Front to Thena Migration: A Technical Guide

No native importer exists between Front and Thena. This guide covers the API endpoints, data-model mapping, rate limits, and ETL pipeline needed for the migration.

Roopi Roopi · · 20 min read
Front to Thena Migration: A 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

Front to Thena Migration: A Technical Guide

Info

TL;DR: Front → Thena Migration

Front is an email-first shared inbox; Thena is a Slack-native, AI-first B2B ticketing platform. No native migration tool exists between them. You must build a custom ETL pipeline using Front's Core API and Thena's Platform API. Expect to extract Front conversations, transform HTML email bodies into Slack-compatible formats, map Front Teammates to Thena Agents, and work within strict rate limits on both sides. Budget 1–4 weeks depending on dataset size.

Migrating from Front to Thena means translating a shared-inbox conversation system into an account-centric, Slack-native B2B ticketing system. Front anchors its architecture around the email protocol — treating SMS, WhatsApp, and webchat as extensions of a shared inbox. Thena flips this model, building its core around Slack and MS Teams, treating internal messaging channels as the primary interface for ticketing, routing, and AI triage.

Because these platforms solve the same problem using different architectural paradigms, this is a data-model transformation, not a simple field copy. Thena does not offer a built-in Front importer, and no third-party migration tool currently supports Front as a source and Thena as a target. Every migration requires a custom API-based ETL pipeline. If you're evaluating whether to leave Front at all, start with our Top Front Alternatives in 2026 overview.

Last verified against Front Core API (api2.frontapp.com) and Thena Platform API v2 (platform.thena.ai), tested June 2025. Both vendors update regularly — re-verify rate limits and endpoint availability before starting your migration.

What This Migration Actually Involves

Front is a shared-inbox platform designed around Conversations — threaded message streams spanning email, SMS, chat, social, and WhatsApp, organized into team inboxes with assignment, collision detection, and rule-based routing. Each Conversation belongs to one or more Inboxes, is linked to a Contact, optionally tied to an Account, and tagged for classification. When ticketing is enabled, Front layers additional status categories (Open, Waiting, Resolved) on top of the base conversation statuses. (dev.frontapp.com)

Thena is an AI-native B2B customer support platform organized around Tickets. Thena unifies conversations from Slack, MS Teams, Discord, email, and web chat into a single ticketing workspace with account management, SLAs, workflow automation, and AI-powered features like auto-tagging, sentiment analysis, and AI-generated summaries. Every ticket belongs to an Account, has an assigned agent, and carries AI metadata. Thena creates four default parent statuses for new organizations: Open, In progress, On hold, and Closed. (docs.thena.ai)

The core mismatch: Front's data model is inbox-and-conversation-centric — a single conversation can live in multiple inboxes. Thena's model is account-and-ticket-centric — every ticket requires a teamId and is tied to an account hierarchy. Moving between them demands careful schema mapping at every level.

Entity Relationship Comparison

The following diagram encodes the full relational schema for both platforms. Use it to identify where referential integrity constraints will force sequenced loading.

Front Entity Graph:

Company
  └── Workspace
        ├── Inbox (many)
        │     └── Conversation (many) ←── Tag (many-to-many)
        │           ├── Message (many)
        │           │     └── Attachment (many)
        │           ├── Comment (many, internal)
        │           └── Assignee → Teammate
        ├── Contact ←── Account (optional)
        ├── Teammate (many)
        └── Custom Field (scoped to Workspace)

Thena Entity Graph:

Organization
  └── Team (maps to Front Inbox)
        └── Ticket (many) ←── Tag (many-to-many)
              ├── Description (first message)
              ├── Comment (many, public or private)
              │     └── Attachment (many)
              ├── Assigned Agent → User
              └── Account (required for SLA; optional at creation)
                    ├── primaryDomain (required)
                    ├── secondaryDomain (optional)
                    └── Parent Account (optional, for subsidiaries)

Key structural asymmetries this diagram exposes:

  • Front conversations can belong to multiple Inboxes simultaneously; Thena tickets have exactly one owning Team. This forces a canonical-inbox decision during transformation.
  • Front Accounts are optional and can exist without domains; Thena Accounts require primaryDomain. Front instances without CRM integration often have conversations with no _account_id at all — in a 40K-conversation migration, this typically affects 10–15% of records and requires a separate attribution strategy.
  • Thena's Comment model supports is_private at the field level; Front separates internal Comments from external Messages entirely. The mapping is straightforward but must be explicitly set per record.

Data Model Mapping: Front vs. Thena

Before writing a single line of extraction code, map Front's schema to Thena's. This table covers the primary entities:

Front Entity Thena Equivalent Mapping Notes
Conversation Ticket 1:1 mapping. Front conversation thread becomes Thena ticket history. Status mapping required. Multi-inbox conversations need one canonical Thena team.
Message Ticket Comment / Description First message → ticket description. Subsequent messages → public comments. Preserve author, timestamp, and inbound/outbound direction.
Comment Internal Note / Private Comment Front's internal @-mention comments map to Thena's private comments (is_private: true). Thena renders these as internal notes visible only to agents — verify this matches your team's expectation before assuming parity.
Contact Contact Email is the primary key on both sides. Phone, name, and custom fields require field-by-field mapping.
Account Account Front accounts can exist without domains. Thena accounts require name and primaryDomain, and support parent-subsidiary relationships. Domain cleanup may be needed before load. (help.front.com)
Tag Tag Direct mapping by name. Create all tags in Thena before import.
Teammate Agent / User Map Front teammate IDs to Thena user IDs. Build a lookup table before migration begins.
Inbox Team / Board Front inboxes map to Thena teams or ticket boards. No 1:1 API equivalent — requires an organizational decision.
Custom Field Custom Field Map field-by-field. Type compatibility must be verified — a Front enum must match a Thena dropdown or single_select; a Front boolean has no direct Thena equivalent and must be mapped to checkbox or a two-option dropdown.
Rule Workflow No automated migration. Rebuild manually in Thena's workflow builder.
SLA Policy SLA Policy No automated migration. Recreate in Thena's SLA management module.
Info

What doesn't transfer automatically: Front rules, macros, message templates, analytics history, Front Chat widget config, AI-generated Topics, Copilot history, shared drafts, collision detection state, and channel connection settings all require manual recreation in Thena or must be accepted as lost. Thena generates its own AI metadata (titles, summaries, sentiment, tags) post-ingestion — Front's AI outputs have no import path.

Extracting Data from Front

Front's Core API is the only reliable extraction path for migration-scale data. Front also documents a sample export application that handles conversations, messages, comments, and attachments. (dev.frontapp.com)

Key Endpoints

  • GET /conversations — List and search conversations. Supports filtering by inbox, tag, assignee, and date range via the q parameter.
  • GET /conversations/search/{query} — Targeted slices using Front's search syntax: is:open, tag:..., before:..., after:.... Allows up to 15 filters per query with AND logic between different filter types. (dev.frontapp.com)
  • GET /conversations/{id}/messages — All messages in a thread, including sender, recipients, body (HTML), and attachments.
  • GET /conversations/{id}/comments — Internal comments (private notes).
  • GET /contacts — All contacts with handles, custom fields, and linked accounts.
  • GET /accounts — Accounts with custom fields and domain information.
  • GET /tags — All tags across company, workspace, and personal scopes.

Front API Rate Limits

Front's rate limits are per-company, not per-token:

Plan Global Rate Limit
Starter 50 requests/minute
Professional 100 requests/minute
Enterprise 200 requests/minute

The conversation search endpoint is further capped at 40% of the company rate limit. Burst rate limits also apply: Tier 2 resources like conversations and messages are capped at 5 requests per resource per second. (dev.frontapp.com)

Front returns a 429 Too Many Requests response when limits are exceeded. Implement exponential backoff — don't just retry immediately.

import requests
import time
import json
 
BASE_URL = "https://api2.frontapp.com"
HEADERS = {
    "Authorization": "Bearer YOUR_FRONT_API_TOKEN",
    "Accept": "application/json"
}
 
def fetch_paginated(endpoint, params=None):
    """Generic paginated fetch with rate-limit handling."""
    results = []
    url = f"{BASE_URL}{endpoint}"
    while url:
        resp = requests.get(url, headers=HEADERS, params=params)
        if resp.status_code == 429:
            time.sleep(60)  # Back off on rate limit
            continue
        resp.raise_for_status()
        data = resp.json()
        results.extend(data.get("_results", []))
        url = data.get("_pagination", {}).get("next", None)
        params = None  # Pagination URL includes params
        time.sleep(1.2)  # Stay under 50 rpm default
    return results
 
# Extract conversations with messages and comments
conversations = fetch_paginated("/conversations")
for conv in conversations:
    conv_id = conv["id"]
    conv["_messages"] = fetch_paginated(f"/conversations/{conv_id}/messages")
    conv["_comments"] = fetch_paginated(f"/conversations/{conv_id}/comments")
Tip

Rate limit math matters. For a 10K-conversation migration on the 50 rpm Starter plan, extraction alone takes 10+ hours. Each conversation needs 1+ calls for messages plus 1 for comments, so net throughput is roughly 15–16 fully-extracted conversations per minute. If you have 50K+ conversations, consider purchasing Front's API rate limit add-on (available on Professional plan and above) before starting.

Don't Rely on Front's Support Export or Analytics Export

Front offers a support-led account export, but it only includes shared-inbox content. It excludes individual inbox conversations, contact data, and tags. Front acknowledges export requests within 72 hours — not something to schedule during cutover week. (help.front.com)

Front's analytics conversation export is capped at 31 days per export, 100,000 rows, and only covers inboxes with ticketing enabled. Useful for QA spot-checks, not for rebuilding full history. (help.front.com)

Warning

Timestamps: Front uses Unix time with millisecond precision. Thena uses ISO 8601 timestamps. Convert during transformation — don't store raw Unix timestamps in your intermediate format.

Transformation: Mapping Front Data to Thena's Schema

The transformation layer is where most DIY migrations fail. Front and Thena diverge on several structural assumptions.

Status Mapping

Front conversations carry a base status of open, archived, deleted, or spam. When ticketing is enabled, Front adds status categories: Open, Waiting, and Resolved. Thena's default statuses are Open, In progress, On hold, and Closed.

Front Status Thena Status Notes
open (no assignee) Open Unassigned work
open (with assignee) In progress Active work
waiting (ticketing status) On hold Waiting on customer or third party. (help.front.com)
archived / resolved Closed Completed work
deleted Skip or Closed Typically excluded from migration
spam Skip Do not migrate spam conversations
Warning

Snoozed is not the same as archived. In Front's search, is:snoozed is its own state, but snoozed conversations can surface with status: archived in API responses — distinguished only through reminder metadata. If you map every archived record to Thena Closed, you will incorrectly close work that was only deferred. Detect snoozed conversations explicitly during extraction by checking for the presence of a scheduled_reminders array in the conversation payload. (dev.frontapp.com)

Contact and Account Matching

Both platforms use email domain as the natural join key for accounts:

  1. Extract all Front Accounts with their domain lists and custom fields.
  2. Create corresponding Accounts in Thena via the Platform API. Thena accounts require name and primaryDomain, and support secondaryDomain plus parent-subsidiary relationships. Front accounts can exist without domains, so cleanup may be needed.
  3. Build an account_id_map: {front_account_id: thena_account_id} lookup.
  4. For Contacts, match on email address — create in Thena if not found, then link to the mapped Account.

Handling conversations with no account ID: Front instances that were not integrated with a CRM often have conversations where _account_id is null. This condition is more common than teams expect — it typically affects 10–15% of records in instances that grew organically without enforcing account linkage. For these records, you have three options:

  • Attribute to requestor only: Create the ticket without accountId. Thena allows this; SLA policies based on account tier won't apply until backfilled.
  • Infer account from email domain: Parse the requestor's email domain, match against existing Thena accounts, and link if a confident match exists. Flag ambiguous matches for manual review.
  • Create a placeholder account: Useful when you want clean reporting immediately. Create an "Unattributed" account in Thena and assign all orphaned tickets to it, then let the team reclassify post-migration.

If your Front instance used custom fields to fake account hierarchy, this is the moment to decide whether to keep the flat model or upgrade into Thena's native parent-subsidiary account structure.

HTML to Markdown Conversion

Front stores message bodies as HTML. Thena, being Slack-native, relies on Slack's mrkdwn format or plain text. Pushing raw HTML into Thena renders as broken code in the Slack interface.

Your transformation script must parse Front's body (HTML) and convert it to clean markdown. Python's html2text or Node.js's turndown handle the basics. Watch for:

  • Inline images referenced as cid: attachments — these need separate download and re-upload
  • Email signatures and inline CSS that inflate ticket descriptions
  • Tracking pixels that should be stripped entirely
  • Front-specific formatting artifacts in internal comments

Resolving Assignees

When you extract a message from Front, the author is identified by a Front Teammate ID or a raw email address. Map this to a Thena User ID before constructing the payload.

If a historical agent has left the company and does not exist in Thena:

  1. Provision a placeholder user in Thena to attribute historical actions to.
  2. Or attribute actions to a generic system user and prepend the original author's name to the message body (e.g., [Originally sent by alice@company.com]).

Handling Attachments

Front attachments are returned via GET /messages/{id}/attachments. These URLs are often authenticated. To migrate them:

  1. Download the attachment from Front using your API token (counts against your rate limit).
  2. Store temporarily — local disk or S3 staging bucket.
  3. Upload to Thena via their attachment API or use attachmentUrls in the ticket create payload.
  4. Replace the Front attachment URL in the message body with the new accessible URL.

For large-volume migrations, stage attachments in batches during off-peak hours. A 50K-conversation dataset with an average of 1.5 attachments per conversation means ~75K file transfers — plan storage and bandwidth accordingly.

Conversation-to-Ticket Transformation Example

def transform_conversation_to_ticket(front_conv, account_map, user_map, tag_map):
    messages = sorted(front_conv["_messages"], key=lambda m: m["created_at"])
    first_msg = messages[0] if messages else {}
 
    # Detect snoozed conversations before applying status map
    is_snoozed = bool(front_conv.get("scheduled_reminders"))
 
    # Status mapping
    if is_snoozed:
        thena_status = "On hold"  # Deferred, not completed
    else:
        status_map = {
            "open": "Open" if not front_conv.get("assignee") else "In progress",
            "archived": "Closed",
            "deleted": "Closed",
            "spam": None  # Skip
        }
        thena_status = status_map.get(front_conv.get("status"), "Open")
 
    if thena_status is None:
        return None
 
    return {
        "title": front_conv.get("subject") or first_msg.get("body", "")[:100],
        "description": html_to_markdown(first_msg.get("body", "")),
        "status": thena_status,
        "account_id": account_map.get(front_conv.get("_account_id")),
        "assigned_agent_id": user_map.get(
            front_conv.get("assignee", {}).get("id")
        ),
        "tags": [
            tag_map[t["id"]] for t in front_conv.get("tags", [])
            if t["id"] in tag_map
        ],
        "metadata": {
            "frontConversationId": front_conv["id"],
            "frontPrimaryInboxId": front_conv.get("_inbox_id"),
            "originalCreatedAt": unix_to_iso(front_conv["created_at"]),
            "wasSnoozed": is_snoozed
        },
        "comments": [
            {
                "body": html_to_markdown(msg.get("body", "")),
                "author_id": user_map.get(msg.get("author", {}).get("id")),
                "is_private": not msg.get("is_inbound", True),
                "created_at": unix_to_iso(msg["created_at"])
            }
            for msg in messages[1:]
        ]
    }

Loading Data into Thena

Thena's Platform API v2 handles the write side. Authentication is via an x-api-key header, with API keys generated from Dashboard → Organization Settings → Security and Access.

Warning

API access requires the Standard plan at minimum ($79/user/month billed annually, verified June 2025). The Free plan does not include API access. Verify your Thena plan before starting migration development.

Rate Limits and Throughput

Thena's standard-tier rate limit is 60 requests per minute (per user, org, and IP). Enterprise plans offer custom limits. Confirm current limits against Thena's API documentation before building — this value has changed across Thena's API versions.

# Load throughput estimate at 60 rpm:
# Creating 1 ticket = 1 API call
#   + 1 per comment (N messages - 1)
#   + 1 for tag assignment
#   + 1 per attachment upload
#
# A conversation with 8 messages and 2 attachments:
#   1 + 7 + 1 + 2 = 11 API calls
#   At 60 rpm → ~5.4 such tickets per minute
#   10,000 tickets ≈ 31 hours of load time

This is the primary bottleneck. For large migrations (10K+ tickets), the combined extraction + load time can stretch to 3–5 days of continuous operation.

Load Sequence

Order matters. Thena enforces referential integrity on some entities:

  1. Accounts — Create all accounts first. Capture {front_account_id: thena_account_id} mapping.
  2. Contacts — Create or match contacts. Link to accounts.
  3. Tags — Create all tags. Capture name-to-ID mapping.
  4. Agents/Users — Build {front_teammate_id: thena_user_id} from existing Thena users. Invite agents manually first — don't create via API.
  5. Tickets — Create tickets with full metadata: title, description, status, assignee, account, tags, custom fields.
  6. Comments — Append conversation history as comments on each ticket, preserving chronological order and author attribution.
  7. Attachments — Upload and link to the relevant ticket or comment.
import requests
import time
 
THENA_BASE = "https://platform.thena.ai/v1"
THENA_HEADERS = {
    "x-api-key": "YOUR_THENA_API_KEY",
    "Content-Type": "application/json"
}
 
def create_thena_ticket(ticket_data):
    resp = requests.post(
        f"{THENA_BASE}/tickets",
        headers=THENA_HEADERS,
        json=ticket_data
    )
    if resp.status_code == 429:
        time.sleep(60)  # Wait full minute on rate limit
        return create_thena_ticket(ticket_data)  # Retry
    resp.raise_for_status()
    return resp.json()

A practical Thena ticket payload that preserves source context:

{
  "title": "Payment failed after renewal",
  "requestorEmail": "customer@example.com",
  "teamId": "SUPPORT",
  "statusName": "On hold",
  "description": "[Imported from Front cnv_123]\n[Original: 2026-05-14T09:22:11Z]\n\nCustomer reports renewal payment failure after invoice update.",
  "metadata": {
    "frontConversationId": "cnv_123",
    "frontTicketIds": ["TICKET-9831"],
    "frontAssigneeId": "tea_456",
    "frontPrimaryInboxId": "inb_789"
  }
}
Danger

Timestamp override limitation: Thena's documented ticket-create parameters do not expose a createdAt override (verified against Thena Platform API v2, June 2025). Historical tickets will carry the migration date as their creation timestamp. Preserve original timestamps in metadata, a dedicated custom field, or as a prefix in the message body (e.g., [Original Date: 2024-03-12 14:00 UTC]). Re-verify this constraint against Thena's current API before starting — endpoint parameters may be added in future releases. (docs.thena.ai)

Tip

Preserve source IDs everywhere. Store frontConversationId, original assignee, source channel, original timestamps, and any Front ticket_ids in Thena custom fields or metadata. This single decision makes reconciliation, retries, and support escalations dramatically easier. (dev.frontapp.com)

Edge Cases and Failure Modes

These are the issues that consistently surface in Front-to-helpdesk migrations, documented with their root causes and resolution paths:

Multi-Inbox Conversations

A single Front conversation can appear in multiple inboxes. A Thena ticket needs one owning teamId. You need a deterministic rule for primary ownership — typically the first inbox the conversation appeared in, which is accessible via the inboxes array sorted by created_at. Preserve secondary inbox membership as tags or metadata fields.

Resolution path: Build your canonical-inbox logic during the transformation phase, not at load time. If you defer this decision to load time, you get inconsistent routing and broken SLA reporting. A safe default rule: if a conversation appears in exactly one inbox, that inbox owns it; if it appears in multiple, use the inbox with the most recent message activity.

Conversations With No Account ID (Silent 10–15% Problem)

Front instances that were deployed without CRM integration, or where account linking was inconsistently enforced, often have a significant share of conversations where _account_id is null. This condition is invisible until you hit it during transformation.

Resolution path: Before writing transformation code, query GET /conversations with a filter and count records where the embedded _links.related.contact leads to a contact with no associated account. If this number exceeds 5% of your total conversation volume, design your account attribution strategy upfront rather than treating it as an exception handler.

Deleted and Merged Conversations

Front's deleted and spam statuses usually indicate data you don't want in the new system. Merged conversations are trickier — the merge target has a conversation trail, but the source may still exist as a redirect. Export only the merge target to avoid duplicates.

Snoozed Conversations

As noted in the status mapping section, snoozed conversations can surface as archived in the API. Check for scheduled_reminders in the conversation payload to detect them explicitly. Without this check, you will close work that was only deferred.

Channel Mismatch

Front message types include email, SMS, WhatsApp, Intercom, calls, Facebook, Google Play, Front Chat, and X/Twitter. Thena's native channels are Slack, MS Teams, email, web chat, Discord, forms, and API-created tickets. If your Front history contains voice or social conversations, you can preserve them only as historical transcript data inside Thena tickets — not as native live channel objects. (dev.frontapp.com)

X/Twitter Content Redaction

Front explicitly redacts Twitter/X content in API responses for tweet and tweet_dm messages: body, text, blurb, and handles are replaced with redacted placeholders. This is a Front platform-level constraint tied to X/Twitter's API terms, not a bug you can work around. If that data matters, capture it from another compliant source before starting — Front's API alone won't give you full-fidelity X history. (dev.frontapp.com)

Export Scope Mismatch

Teams sometimes assume Front's support export is a full tenant dump. It isn't. Shared-inbox content is available; individual inbox content, tags, and contact data are not. If account managers worked customer threads in personal inboxes, you need an API strategy that explicitly covers those inboxes. (help.front.com)

Custom Field Type Mismatches

Front's boolean custom fields don't have a direct equivalent if Thena treats them as checkbox vs. dropdown. Front enum fields must map to Thena dropdown or single_select — verify option lists match exactly before load, or option values will create orphaned records. Test every custom field type mapping in a sandbox environment against real data samples before running the full migration.

Historical Tickets Won't Be Slack-Native

Thena's strength is Slack-native support. Historical Front conversations imported via API will not have native Slack thread references — they'll appear as standard tickets in Thena's web interface. New conversations will be Slack-native; old ones won't. Set agent expectations about this before cutover.

Rate Limit Stacking

Both APIs rate-limit independently. If you run extraction and load in parallel (which you should, using a queue-based architecture), monitor both rate-limit headers separately. A 429 from Front doesn't mean you need to pause Thena writes, and vice versa. Use separate rate-limit buckets in your pipeline controller for each API.

Migration Timeline and Effort Estimate

Dataset Size Extraction Time Transform (Dev) Load Time QA & Validation Total Elapsed
1K–5K conversations 2–6 hrs 4–8 hrs 4–12 hrs 4–8 hrs 3–5 days
5K–25K conversations 6–24 hrs 8–16 hrs 1–3 days 1–2 days 1–2 weeks
25K–100K conversations 1–4 days 16–40 hrs 3–7 days 2–3 days 2–4 weeks
100K+ conversations 4+ days 40+ hrs 7+ days 3–5 days 4–8 weeks

These estimates assume a single engineer working at standard API rate limits on both sides (50 rpm Front Starter, 60 rpm Thena Standard). Parallelism helps on the extraction side — paginate by inbox and run multiple inbox extractions concurrently — but load throughput is gated by Thena's 60 rpm limit unless you're on an Enterprise plan with custom rate limits.

The dominant time variable is message density, not conversation count. A dataset of 10K conversations with an average of 12 messages each requires 120K+ API calls on the Front extraction side alone. Audit your average messages-per-conversation before committing to a timeline.

Cutover Strategy

The cleanest approach:

  1. Freeze date. Pick a cutover date 1–2 weeks out. Communicate to all agents.
  2. Historical migration. Run the full ETL pipeline for all conversations created before the freeze date. This runs in the background while your team continues working in Front.
  3. Delta sync. On cutover day, re-extract conversations created or updated after your initial extraction started. Use Front's Events endpoint — filter by types and after timestamp. Key nuance: event filtering works on emitted_at, not the target object's created_at. Event IDs are sequential and never reused, so your delta-sync watermark should be based on event ID or emitted_at, not message timestamps. (dev.frontapp.com)
  4. Validation. Run reconciliation counts: total conversations exported vs. tickets created. Spot-check 50–100 tickets for correct assignee, tags, status, full message history, and attachment presence. Thena's entity search API supports filter_by, sort_by, and streaming=true (capped at 250 per page, verify current limit before use), which is efficient for reconciliation. (docs.thena.ai)
  5. Switch. Point communication channels (email forwarding, chat widgets, Slack integrations) to Thena. Disable active processing in Front.
  6. Parallel read period. Keep Front in read-only mode for 2–4 weeks so agents can reference historical context if something didn't transfer.
Tip

Don't skip the delta sync. Conversations created during the migration window typically account for 3–8% of total volume. Missing them means your agents start on Thena with gaps in their most recent customer interactions — the ones they're most likely to need.

What You Lose in This Migration

Be upfront with stakeholders about what doesn't survive:

  • Front rules and macros — Must be rebuilt as Thena workflows
  • Front Chat widget config — Thena uses its own web chat widget; reconfigure from scratch
  • Analytics history — Front's analytics data does not export in a format Thena can ingest
  • Message templates / canned responses — Export manually from Front, recreate in Thena
  • Collision detection state — Real-time collaboration metadata does not transfer
  • AI-generated Topics and Copilot history — Not exportable; Thena generates its own AI metadata for new tickets
  • Shared drafts — Draft state doesn't survive; finalize or discard all in-progress drafts before cutover
  • Granular routing history — Front tracks events like "Teammate A moved this to Inbox B." Thena's API does not support importing arbitrary historical audit logs. You retain messages, comments, and final state — not the routing breadcrumb trail.
  • Original creation timestamps on tickets — Thena's ticket-create API does not accept a createdAt override. All imported tickets will show the migration date as their creation date unless you embed original timestamps in metadata or description fields.

When to Use a Custom Pipeline vs. Alternatives

A custom API pipeline is appropriate in most cases, but the decision depends on specific signals:

Use a custom API pipeline when:

  • Dataset exceeds 500 conversations with meaningful message history
  • You have engineering resources available for 2–4 weeks of build and monitoring
  • Historical context in Thena is required for active account management or SLA reporting

Consider a manual approach when:

  • Dataset is under 500 conversations with shallow message histories
  • Conversations are predominantly closed — historical read access in Front is acceptable
  • Engineering resources are unavailable or cost-prohibitive for a short migration window

Consider a clean-start approach when:

  • Your primary motivation is Slack-native support for new conversations, not preserving history
  • Front conversation history is primarily closed/resolved with no ongoing SLA implications
  • Team is willing to keep Front as a read-only archive for 6–12 months while Thena handles new volume

The clean-start approach eliminates all ETL risk and gets your team productive on Thena immediately. The cost is losing the ability to search historical context from Thena's interface — agents must switch to Front for pre-migration records. This is an acceptable operational trade-off for many teams.

The break-even point for engineering effort: At Thena's 60 rpm load rate, building and operating a custom pipeline costs roughly 40–80 hours of engineering time across scoping, development, testing, cutover, and validation. At $150–200/hour fully loaded, this is a $6,000–$16,000 investment. For datasets under 1,000 conversations, manual recreation is often faster and cheaper. For datasets over 5,000 conversations, the API pipeline pays for itself in reduced error rate and auditability.

For related migration paths, see our Front to Zendesk, Front to Freshchat, Front to Intercom, and Front to HubSpot Service Hub guides. For pre-migration preparation, our Front Migration Checklist covers the full sequence.

Getting This Migration Done

This migration is technically straightforward but operationally demanding — the API constraints on both sides turn a logically simple ETL into a multi-day operation requiring monitoring, retries, and careful validation. The most common failure modes are not technical: they're decisions deferred until load time (canonical inbox selection, account attribution for orphaned conversations, custom field type mismatches) that should have been resolved during the transformation design phase.

If you're building this pipeline yourself: resolve the schema decisions before writing extraction code, instrument your pipeline with per-entity success/failure counters from day one, and run a 100-conversation sample load against a Thena sandbox before committing to the full dataset.

Frequently Asked Questions

Is there a native migration tool to move from Front to Thena?
No. Neither Front nor Thena provides a built-in migration tool for this path, and no third-party connector currently supports it. You must build a custom ETL pipeline using Front's Core API and Thena's Platform API. Datasets under 500 conversations may work with a manual CSV approach.
What data is lost when migrating from Front to Thena?
Rules, macros, message templates, analytics history, Front Chat widget configuration, AI Topics, Copilot history, shared drafts, collision detection state, and granular routing history do not transfer. These must be rebuilt manually in Thena or accepted as lost.
How long does a Front to Thena migration take?
For a 10K-conversation dataset on default API rate limits, expect 10+ hours of extraction and 30+ hours of loading, plus development and validation time. Total elapsed time is typically 1–2 weeks. Datasets over 25K conversations can take 2–4 weeks or more.
Can I use Front's analytics export for a historical migration?
No. Front's analytics conversation export is capped at 31 days per export and 100,000 rows, and only covers inboxes with ticketing enabled. Use the Core API for primary extraction.
Does Thena's free plan support API-based data import?
No. Thena's API access requires the Standard plan ($79/user/month billed annually) or higher. The Free plan does not include API access, so you cannot run a programmatic migration against it.

More from our Blog

Front Migration Checklist
Checklist/Front

Front Migration Checklist

Master your Front migration with this step-by-step checklist. Learn what can move via API, what requires manual setup, and how to protect your ticket history and workflows.

Tejas Mondeeri Tejas Mondeeri · · 11 min read