---
title: "Thena to LiveChat Migration: The Complete Technical Guide"
slug: thena-to-livechat-migration-the-complete-technical-guide
date: 2026-08-11
author: Roopi
categories: [Migration Guide, Help Desk]
excerpt: "Technical guide to migrating from Thena to LiveChat/HelpDesk: API endpoints, data mapping, Slack identity resolution, and cutover strategy."
tldr: "Thena to LiveChat is two migrations: historical tickets into HelpDesk via API, future conversations into LiveChat. Slack identity resolution and Thena's 60 req/min rate limit are the main bottlenecks."
canonical: https://clonepartner.com/blog/thena-to-livechat-migration-the-complete-technical-guide/
---

# Thena to LiveChat Migration: The Complete Technical Guide


# Thena to LiveChat Migration: The Complete Technical Guide

> [!NOTE]
> **TL;DR:** Thena is a Slack-native, AI-first B2B ticketing platform. LiveChat is a real-time website chat platform backed by HelpDesk for async ticketing. No native import path exists between them — the data models are structurally different, and Thena's Slack-centric request format must be transformed into HelpDesk's event-driven ticket model (a flat, chronologically ordered array of typed events). Your historical data must be imported into HelpDesk (not LiveChat) via `POST /v1/importedTickets`. The main engineering challenges are Slack user identity resolution, Slack mrkdwn-to-HTML conversion, and working within Thena's 60 req/min standard-tier API rate limit.
>
> **Published:** January 2025. **Last reviewed:** June 2025 against Thena Platform API v2, HelpDesk API v1 (`POST /v1/importedTickets`), and Text Platform Agent Chat API v3.6.

Migrating from [Thena](https://www.thena.ai/) to [LiveChat](https://www.livechat.com/) means leaving a Slack-first, AI-driven B2B support platform and moving to a website-visitor-facing live chat system with a separate ticketing backend. The platforms serve fundamentally different use cases, and the migration is entirely API-driven — there is no built-in connector, no CSV import on HelpDesk that preserves conversation threading, and no third-party tool that supports Thena as a source.

This guide covers the exact API endpoints, data-model mapping, rate-limit math, error responses, attachment handling, and cutover logic you need. If you've already read our [LiveChat vs Thena comparison](https://clonepartner.com/blog/blog/livechat-vs-thena-2026-architecture-tco-migration/), this picks up where the "migration path" section ended.

## What This Migration Actually Involves

**Thena** organizes support around **Requests** — conversations captured from Slack, email, MS Teams, web chat, and Discord. Each Request holds threaded messages, AI-generated metadata (title, summary, tags, sentiment, urgency), custom fields, SLA data, account context, and escalation details. Thena's data model is deeply tied to Slack: messages include thread structures, emoji reactions, Slack user IDs, and channel context. Thena also exposes first-class **accounts** and **customer contacts**, giving it a true B2B account-centric model.

**LiveChat** (by Text, Inc.) is a real-time chat platform for website visitors. Its legacy built-in ticketing was sunset in January 2025 and replaced by **HelpDesk** (helpdesk.com), a separate product that handles all async ticketing. This means your Thena data has two possible targets:

1. **HelpDesk** (`POST /v1/importedTickets`) — the primary target for all ticket and request history. This is where the bulk of your Thena data goes.
2. **LiveChat** (Agent Chat API) — only relevant for future live chat sessions, not historical data import.

For nearly every Thena-to-LiveChat migration, **HelpDesk's Imported Tickets API is your actual target**.

> [!WARNING]
> **API version note:** Text's Agent Chat API v3.6 removed `Create Customer` and `List Customers`, which were present in the legacy v3.5 docs. Do not build bulk customer pre-seeding against the old API surface. Build against the current stable behavior. ([platform.text.com](https://platform.text.com/docs/messaging/agent-chat-api/changelog))

The practical split:

- **Thena tickets, comments, tags, assignees, priorities, status history, attachments** → land in **HelpDesk**
- **Future website chat flows** → land in **LiveChat**
- **Thena accounts and contacts** → keep in your CRM, mirror selectively into HelpDesk custom fields
- **Thena workflows, Slack routing, AI agent configs, internal thread behavior** → redesign from scratch. Do not expect a 1:1 port.

## Thena Data Model: What You're Extracting

Thena's API exposes Requests via `GET https://bolt.thena.ai/rest/v2/requests`. Each Request object contains:

| Thena Field | Type | Notes |
|---|---|---|
| `id` | string | Unique request identifier |
| `status` | enum | `OPEN`, `ASSIGNED`, `CONVERTED_TO_TICKET`, custom sub-statuses |
| `sub_status` | string | Custom workflow states |
| `ai_metadata.title` | string | AI-generated title |
| `ai_metadata.summary` | string | AI-generated summary |
| `ai_metadata.tags []` | array | AI-generated tags |
| `ai_metadata.urgency` | string | `Low`, `Medium`, `High`, etc. |
| `ai_metadata.sentiment` | string | `Neutral`, `Positive`, `Negative` |
| `custom_fields_v2 []` | array | User-defined custom fields |
| `feedback []` | array | CSAT feedback entries |
| `escalation_type` | string | e.g., `automatic` |
| `external_links []` | array | Links to external tools (Jira, Linear, etc.) |

Conversations are fetched separately via `GET /rest/v2/requests/{requestId}/conversations`. This returns the full message thread — including Slack message content, sender info, timestamps, and attachments.

Thena also provides a search API (`GET https://platform.thena.ai/v1/search/tickets`) that supports `filter_by`, `sort_by`, `page`, `per_page`, and `include_fields` parameters. This is useful for date-window delta exports and targeted extraction. ([docs.thena.ai](https://docs.thena.ai/api-reference/platform/search/entity-search))

> [!WARNING]
> **Rate limit constraint:** Thena's standard-tier API allows **60 requests per minute** per user, org, and IP. Extracting 5,000 requests with their conversations requires at minimum ~167 minutes of API time (5,000 list items + 5,000 conversation fetches = 10,000 calls ÷ 60/min). Plan for a multi-hour extraction window, or negotiate Enterprise-tier custom limits before starting.

## HelpDesk Data Model: What You're Loading Into

HelpDesk's `POST /v1/importedTickets` endpoint is purpose-built for migrations. It accepts a complete ticket — subject, requester, tags, priority, custom fields, team assignment, and a chronologically ordered array of typed events — in a single API call. ([api.helpdesk.com](https://api.helpdesk.com/docs#operation/importTicket))

**HelpDesk authentication:** Credentials use HTTP Basic Auth. The format is `license_id:personal_access_token`, base64-encoded. Generate a Personal Access Token (PAT) from the [Developer Console](https://platform.text.com/console/). Your license ID is the numeric identifier visible in the HelpDesk URL after login. The resulting header is: `Authorization: Basic base64("your_license_id:your_PAT")`.

Key constraints on the import endpoint:

- **First event must be type `message`** — its date becomes the ticket's creation date
- **Events must be chronologically ordered** and all dates must be in the past
- **Agent-authored messages require `agentID`, `agentName`, and `isPrivate` parameters** — messages missing these fields are treated as requester-authored. This is where bad migrations silently corrupt authorship.
- **The last `status` event determines the final ticket state**
- **Attachments require a 3-step transaction flow:** create transaction → upload files → reference `transactionID` in the ticket payload
- **Transaction IDs expire after 24 hours**; if an attachment upload partially fails mid-transaction, the entire transaction must be abandoned and restarted from step 1 — partially uploaded files cannot be recovered or completed after expiry
- **All uploaded attachments must be referenced** in the ticket payload or the transaction fails

**HelpDesk ticket statuses:** `open`, `pending`, `onhold`, `solved`, `closed`.

**HelpDesk priorities:** `-10` (low), `0` (medium), `10` (high), `20` (urgent).

**HelpDesk custom fields** are limited to four types: `singleLine` (120 chars), `multiLine` (1,000 chars), `date`, and `url`.

### HelpDesk API Error Responses

Understanding what `POST /v1/importedTickets` returns on failure is essential for debugging. The endpoint returns standard HTTP status codes with a JSON error body:

| Scenario | HTTP Status | Error Body (example) |
|---|---|---|
| Events array out of chronological order | `422 Unprocessable Entity` | `{"error": "Events must be in chronological order"}` |
| First event is not type `message` | `422 Unprocessable Entity` | `{"error": "First event must be of type message"}` |
| `agentID` references a non-existent agent | `422 Unprocessable Entity` | `{"error": "Agent not found"}` |
| `agentID` present but `agentName` missing | `422 Unprocessable Entity` | `{"error": "agentName is required when agentID is provided"}` |
| Transaction ID expired or invalid | `400 Bad Request` | `{"error": "Transaction not found or expired"}` |
| Attachment referenced but not uploaded to transaction | `400 Bad Request` | `{"error": "Attachment not found in transaction"}` |
| Missing or malformed auth header | `401 Unauthorized` | `{"error": "Unauthorized"}` |
| Rate limit exceeded | `429 Too Many Requests` | `{"error": "Too many requests"}` with `Retry-After` header |

If `agentID` is omitted from a message that should be agent-authored, HelpDesk does not return an error — it silently treats the message as requester-authored. This is the most common silent corruption in Thena migrations. Validate authorship in your post-load checks, not just record counts.

## Field Mapping: Thena Request → HelpDesk Imported Ticket

Not everything maps cleanly. Here is the core transformation logic:

| Thena Source | HelpDesk Target | Transformation |
|---|---|---|
| `ai_metadata.title` or first message | `subject` | Use AI title if present; fall back to first 120 chars of first message |
| Request creator email | `requester.email` | Slack user ID → email lookup required if source is Slack |
| Request creator name | `requester.name` | May need Slack API call to resolve display name |
| `status` / `sub_status` | `events [].type: "status"` | See status mapping below |
| `ai_metadata.urgency` | `priority` | `Low` → `-10`, `Medium` → `0`, `High` → `10` |
| `ai_metadata.tags []` | `tagIDs []` | Pre-create tags in HelpDesk via `POST /v1/tags`, then reference UUIDs |
| `custom_fields_v2 []` | `customFields` | Pre-create via `POST /v1/customFields`; note char limits |
| Conversations | `events []` (type: `message`) | Flatten Slack threads into chronological events; convert mrkdwn to HTML |
| `feedback []` (CSAT) | N/A | No import path — HelpDesk has its own post-ticket rating system |
| `external_links []` | N/A | Append to first message body or store in a `url` custom field |
| `ai_metadata.summary` | N/A | Prepend to ticket body or store in a `multiLine` custom field |

### Status Mapping

Thena's statuses don't map 1:1 to HelpDesk. Thena uses free-form sub-statuses alongside core states:

```python
def map_status(thena_status: str, thena_sub_status: str | None) -> str:
    status_map = {
        "OPEN": "open",
        "ASSIGNED": "open",
        "IN_PROGRESS": "pending",
        "WAITING_ON_CUSTOMER": "pending",
        "WAITING_ON_INTERNAL": "onhold",
        "CONVERTED_TO_TICKET": "solved",
        "CLOSED": "closed",
        "RESOLVED": "solved",
    }
    # Check sub_status first for more granular mapping
    if thena_sub_status and thena_sub_status.upper() in status_map:
        return status_map[thena_sub_status.upper()]
    return status_map.get(thena_status.upper(), "open")
```

> [!TIP]
> **Preserve Thena's original status as a tag.** Create a HelpDesk tag like `thena-status:waiting-on-customer` so agents can filter by the original workflow state after migration. This costs nothing and saves debugging time.

## Step-by-Step Migration Process

### Step 1: Extract Thena Data

Generate an API key from **Thena Dashboard → Organization Settings → Security and Access**. All requests use the `x-api-key` header.

```bash
# Fetch all requests (paginated)
curl -X GET "https://bolt.thena.ai/rest/v2/requests?limit=100&page=1&sort_order=asc" \
  -H "x-api-key: YOUR_THENA_API_KEY"
```

For each request, fetch conversations:

```bash
curl -X GET "https://bolt.thena.ai/rest/v2/requests/{requestId}/conversations" \
  -H "x-api-key: YOUR_THENA_API_KEY"
```

Also extract supporting entities:

- **Users:** `GET https://platform.thena.ai/v1/users` — for agent/requester identity mapping
- **Accounts:** `GET https://bolt.thena.ai/rest/v2/accounts` — for company/org context
- **Custom fields:** `GET https://bolt.thena.ai/rest/v2/custom-fields` — for field schema

Store raw JSON locally or in a staging database before any transformation. Run a second pass for tickets updated after the first snapshot to catch changes during extraction.

### Step 2: Resolve Slack User Identities

This is the most common failure point. HelpDesk requires a valid email address to create a customer profile. Thena, however, often stores users by their Slack ID — especially guest users in Slack Connect channels where email visibility is restricted by the external organization.

1. **Extract Thena users** and identify any missing the `email` field.
2. **Query the Slack API** using a bot token with the `users:read.email` scope. Call `users.info` or `users.profile.get` to resolve Slack IDs to email addresses.
3. **Budget for Slack rate limits** — Tier 3/4 endpoints allow ~50–100 requests per minute.
4. **Handle unresolvable users.** If a Slack workspace restricts email sharing or the user is deactivated, generate a fallback email like `unknown-{slack_user_id}@migration.internal` and tag these tickets for manual review. Document this mapping so agents understand the placeholder emails in historical tickets.

### Step 3: Convert Slack mrkdwn to HTML

Thena conversations originating from Slack use Slack's proprietary mrkdwn format. HelpDesk expects plain text or HTML in message events. This conversion must be handled before building ticket payloads.

**Recommended approach:** Use the [`slack-mrkdwn`](https://www.npmjs.com/package/slack-mrkdwn) npm package (Node.js) or implement the conversion directly. Python users can use [`slack-to-html`](https://pypi.org/project/slack-to-html/) as a starting point, but verify output against real Slack payloads — neither library handles all edge cases.

**Core conversion patterns with tested regex:**

```python
import re

def slack_mrkdwn_to_html(text: str, user_map: dict) -> str:
    """
    Convert Slack mrkdwn to HTML for HelpDesk import.
    user_map: dict mapping Slack user IDs to display names, e.g. {"U12345": "Jane Smith"}
    """
    # Resolve user mentions: <@U12345> → Jane Smith (or fallback to Slack ID)
    def resolve_mention(match):
        uid = match.group(1)
        return f"@{user_map.get(uid, uid)}"
    text = re.sub(r'<@([A-Z0-9]+)>', resolve_mention, text)

    # Named links: <https://example.com|Click Here> → <a href="...">Click Here</a>
    text = re.sub(
        r'<(https?://[^|>]+)\|([^>]+)>',
        r'<a href="\1">\2</a>',
        text
    )

    # Bare URLs: <https://example.com> → <a href="...">https://example.com</a>
    text = re.sub(
        r'<(https?://[^>]+)>',
        r'<a href="\1">\1</a>',
        text
    )

    # Bold: *text* → <b>text</b> (must not match mid-word)
    text = re.sub(r'(?<!\w)\*([^*\n]+)\*(?!\w)', r'<b>\1</b>', text)

    # Italic: _text_ → <i>text</i>
    text = re.sub(r'(?<!\w)_([^_\n]+)_(?!\w)', r'<i>\1</i>', text)

    # Strikethrough: ~text~ → <s>text</s>
    text = re.sub(r'(?<!\w)~([^~\n]+)~(?!\w)', r'<s>\1</s>', text)

    # Inline code: `code` → <code>code</code>
    text = re.sub(r'`([^`\n]+)`', r'<code>\1</code>', text)

    # Code blocks: ```code``` → <pre><code>code</code></pre>
    text = re.sub(r'```([^`]+)```', r'<pre><code>\1</code></pre>', text)

    # Newlines → <br>
    text = text.replace('\n', '<br>')

    return text
```

**Known edge cases to test:**

- **Emoji:** Slack encodes custom emoji as `:emoji-name:` — these pass through as-is and render as text in HelpDesk. Unicode emoji (actual codepoints) pass through correctly.
- **Channel references:** `<#C12345|general>` → convert to `#general` using `re.sub(r'<#[A-Z0-9]+\|([^>]+)>', r'#\1', text)`.
- **Bold inside code blocks:** Slack does not render formatting inside backtick spans — ensure your code block regex runs before bold/italic conversions, or use a two-pass approach.
- **Multi-byte Unicode / surrogate pairs:** Slack payloads are UTF-8. HelpDesk accepts UTF-8. No re-encoding is needed, but validate that your JSON serializer does not escape non-ASCII characters as `\uXXXX` sequences, as this produces garbled output in the HelpDesk UI.

### Step 4: Provision HelpDesk Scaffolding

Before loading any tickets, set up the target:

1. **Create teams** via `POST /v1/teams` — map from Thena's groups/boards
2. **Create agents** via `POST /v1/agents` — match by email address. Note: HelpDesk does not allow changing an agent's email after creation; if it changes, you must create a new agent account. Finalize your assignee map before the backfill.
3. **Create tags** via `POST /v1/tags` — each tag requires a `teamID`
4. **Create custom fields** via `POST /v1/customFields` — note the `apiKey` you assign; you'll reference it in ticket payloads

### Step 5: Transform and Load Tickets

For each Thena request, build a HelpDesk imported ticket payload. This is the most engineering-heavy phase.

**Flatten threads:** Thena captures Slack threads as nested conversations. HelpDesk expects a flat chronological event array. Merge parent + reply messages into a single ordered sequence. Consider prefixing replies with `[Thread reply]` to preserve context.

Example transformed payload:

```json
{
  "subject": "Cannot access dashboard after SSO migration",
  "teamIDs": ["team-uuid"],
  "requester": {
    "email": "customer@acme.com",
    "name": "Jane Smith"
  },
  "tagIDs": ["tag-uuid-1", "tag-uuid-2"],
  "assignment": {
    "team": { "ID": "team-uuid" },
    "agent": { "ID": "agent-uuid" }
  },
  "priority": 10,
  "customFields": {
    "thena-request-id": "req_abc123",
    "original-account": "Acme Corp"
  },
  "events": [
    {
      "date": "2025-03-15T10:30:00Z",
      "type": "message",
      "message": {
        "text": "I can't log into the dashboard since the SSO migration yesterday.",
        "html": "<p>I can't log into the dashboard since the SSO migration yesterday.</p>"
      }
    },
    {
      "date": "2025-03-15T11:15:00Z",
      "type": "message",
      "message": {
        "text": "We're looking into this now. Can you try clearing your browser cache?",
        "html": "<p>We're looking into this now. Can you try clearing your browser cache?</p>"
      },
      "agentID": "agent-uuid",
      "agentName": "Alex Support",
      "isPrivate": false
    },
    {
      "date": "2025-03-15T14:00:00Z",
      "type": "status",
      "status": "solved"
    }
  ]
}
```

Post to HelpDesk, constructing auth as `base64("license_id:PAT")`:

```bash
curl -X POST "https://api.helpdesk.com/v1/importedTickets" \
  -H "Authorization: Basic $(echo -n 'YOUR_LICENSE_ID:YOUR_PAT' | base64)" \
  -H "Content-Type: application/json" \
  -H "User-Agent: thena-migration/1.0" \
  -d @ticket_payload.json
```

> [!WARNING]
> **Always include the `User-Agent` header.** HelpDesk's docs note that requests missing it may be blocked by intermediary services.

### Step 6: Handle Attachments

Attachments are the silent killers of migration timelines. Thena references files hosted in Slack, and those URLs are authenticated — HelpDesk cannot download them directly.

HelpDesk requires a three-step transaction flow for attachments:

```bash
# 1. Create import transaction
curl -X POST "https://api.helpdesk.com/v1/importedTickets/transactions" \
  -H "Authorization: Basic $(echo -n 'YOUR_LICENSE_ID:YOUR_PAT' | base64)"
# Response: { "transactionID": "uuid" }

# 2. Upload attachment files
curl -X POST "https://api.helpdesk.com/v1/importedTickets/attachments" \
  -H "Authorization: Basic $(echo -n 'YOUR_LICENSE_ID:YOUR_PAT' | base64)" \
  -F "transactionID=uuid" \
  -F "attachments=@screenshot.png"
# Response: [{ "attachmentID": "att-uuid" }]

# 3. Include transactionID in the importedTickets POST
```

The full pipeline:

1. Read the `file_url` from the Thena message payload.
2. Download the file using an authenticated Slack token. Use a **User Token** (not a Bot Token) if files were uploaded by human users — Bot Tokens cannot access files uploaded by humans in some workspace configurations.
3. Upload to HelpDesk via the transaction flow above.
4. Reference the attachment IDs in the ticket payload's event `files` array.

**Partial failure behavior:** If any individual file upload fails mid-transaction (network error, file too large, unsupported MIME type), the transaction is not automatically invalidated — but the missing attachment ID will cause the final `POST /v1/importedTickets` call to return `400 Bad Request` with `{"error": "Attachment not found in transaction"}`. You must then abandon the transaction and restart from step 1. Transaction IDs expire after **24 hours** regardless of upload state.

If you skip attachment handling entirely, every historical screenshot and log file shared in Slack will return a 404 when agents view imported tickets.

## Rate Limits and Throughput Planning

| Platform | Rate Limit | Practical Throughput |
|---|---|---|
| Thena (Standard) | 60 req/min per user/org/IP | ~50 req/min with backoff |
| Thena (Enterprise) | Custom | Negotiate before migration |
| HelpDesk | 1,000 req/10 min per license | ~90 req/min sustained |
| Slack (user lookup) | Tier 3: ~50 req/min | ~40 req/min with backoff |

For a dataset of **3,000 Thena requests** with conversations and attachments:

- **Extraction:** 3,000 (list pages) + 3,000 (conversations) + ~1,000 (Slack lookups) = ~7,000 calls → **~140 minutes** at Thena's standard rate
- **Loading:** 3,000 ticket imports + ~1,500 attachment transactions = ~4,500 calls → **~50 minutes** at HelpDesk's rate
- **Total estimated runtime:** ~3–4 hours for a clean run

Implement exponential backoff on 429 responses. Both Thena and HelpDesk return rate-limit headers (`Retry-After` on HelpDesk, `X-RateLimit-Reset` on Thena) — read and honor them rather than using fixed sleep intervals.

> [!WARNING]
> **Idempotency is your responsibility.** HelpDesk's import API does not natively prevent duplicate ticket creation. Store the Thena request ID as a HelpDesk custom field and maintain a local mapping (SQLite works fine) of `thena_request_id` → `helpdesk_ticket_id`. If your script crashes mid-migration, this map lets you resume without creating duplicates.

## Migration Complexity Decision Matrix

Use this matrix to estimate scope before committing to an approach:

| Factor | Low Complexity | Medium Complexity | High Complexity |
|---|---|---|---|
| Request volume | < 500 | 500–5,000 | > 5,000 |
| Slack threading depth | Flat (≤ 2 levels) | Moderate (3–5 levels) | Deep (> 5 levels) |
| Attachment volume | None or minimal | < 500 files | > 500 files or large files |
| Slack identity resolution | All users have email | < 10% missing emails | > 10% missing or restricted |
| Custom field complexity | ≤ 5 fields, simple types | 6–15 fields, mixed types | > 15 fields or long-text values |
| Data freshness requirement | Point-in-time snapshot OK | Short delta window (< 1 day) | Live sync required during cutover |
| Validation strictness | Count-level checks | Field-level sampling | Full record-by-record audit |

**Low complexity:** One engineer, 2–4 days scripting plus 1 day validation.
**Medium complexity:** One to two engineers, 1–2 weeks including edge-case handling and delta sync.
**High complexity:** Dedicated team, 3–6 weeks — primarily driven by Slack identity resolution at scale, attachment pipeline, and validation coverage.

## Edge Cases and Failure Modes

**AI metadata loss.** Thena's AI-generated fields (summary, sentiment, urgency source, category) have no structural equivalent in HelpDesk. Decide upfront: discard them, store them in custom fields (limited to `singleLine` at 120 chars and `multiLine` at 1,000 chars), or append them as a formatted header block in the ticket body.

**CSAT and feedback data.** Thena's `feedback []` array doesn't map to HelpDesk's rating system. HelpDesk has its own `rating` object (`good`/`neutral`/`bad`), but it's tied to post-ticket rating requests — there's no way to import historical ratings. Export this data separately for analytics continuity.

**SLA policies.** Thena's SLA configurations don't transfer. HelpDesk doesn't have a native SLA engine in its API — recreate time-based rules using HelpDesk's Rules automation post-migration.

**Custom field truncation.** HelpDesk's `singleLine` custom fields cap at 120 characters and `multiLine` at 1,000 characters. If your Thena custom fields hold longer values, they will be **silently truncated** — HelpDesk does not return a warning or error. Audit field lengths before loading; values longer than the cap should be stored in ticket body text instead.

**Platform events for delta sync.** Thena's platform events are useful for a short cutover window. They provide `eventId` for idempotency and support retries with exponential backoff. However, Thena documents a **256KB payload limit** — large comment payloads are truncated to "Payload too large. Use API instead." Use events for change detection, then re-fetch the full ticket or comment through the API. ([docs.thena.ai](https://docs.thena.ai/platform/platform-events/overview))

**HelpDesk post-import validation via webhooks.** HelpDesk's webhook system can be used to confirm that imported tickets are being created correctly in near-real-time. Configure a webhook on the `ticket_created` event (`POST /v1/webhooks`) pointing to a local listener during your test runs. Compare the webhook payload's `ticketID`, `subject`, `requester.email`, and `priority` against your source data to catch transformation errors before running the full backfill.

**Silent authorship corruption.** As noted above: omitting `agentID` from agent-authored events does not produce an error. The message imports successfully but is attributed to the requester. This produces incorrect conversation histories that cannot be fixed after import without deleting and re-importing the ticket. Add an authorship validation step to your pre-import checks.

## What Won't Survive the Move

Be explicit with stakeholders about what doesn't transfer:

- **Slack channel associations** — Thena's channel-to-request mapping has no HelpDesk equivalent
- **AI agent configurations** — Thena's AI studio, MCP integrations, and workflow automations are platform-specific
- **Account-level B2B context** — Thena's account model (account → contacts → requests) doesn't map to HelpDesk's flat requester model. Keep this data in your CRM.
- **Historical CSAT scores** — no import path exists
- **Workflow automations** — rebuild from scratch using HelpDesk Rules
- **Escalation chains** — manual recreation required
- **Real-time Slack sync** — LiveChat's Slack integration is notification-only, not bidirectional
- **AI-generated summaries and sentiment scores** — no structured equivalent in HelpDesk; store in custom fields with character-limit caveats or discard

## Cutover Strategy and Validation

A low-risk runbook:

1. **Freeze config drift.** Export Thena field definitions, statuses, priorities, tags, and workflow references before anyone "cleans up" the source.
2. **Create the target skeleton.** Stand up HelpDesk teams, tags, custom fields, agents, and LiveChat widget settings before loading history.
3. **Backfill historical tickets into HelpDesk.** Store the original Thena request ID in a custom field for reconciliation.
4. **Run a delta sync.** Re-export tickets updated after the first snapshot and upsert them before cutover.
5. **Cut over entry points.** Switch the website widget to LiveChat. If Slack Connect is your current front door, set channels to read-only or deploy an auto-responder directing customers to the new support channel.
6. **Leave Thena read-only** for a short window. Keep it available for audit until sample checks pass.

### Validation Checklist

Do not stop at record counts. Check:

- [ ] Ticket counts match by status, team, and week
- [ ] First message dates and last update dates are correct
- [ ] Agent-authored messages display correct agent names (not requester-attributed)
- [ ] Attachments download without errors from HelpDesk ticket view
- [ ] Public vs. private message visibility is preserved (`isPrivate` flag)
- [ ] Custom field values are not truncated (singleLine: 120 chars, multiLine: 1,000 chars)
- [ ] Thena request IDs stored in custom fields are unique — no duplicates
- [ ] mrkdwn conversion output is valid HTML — no raw `<@U12345>` tokens or unconverted `*bold*` patterns visible in HelpDesk
- [ ] Unicode characters and emoji render correctly in HelpDesk ticket view
- [ ] Spot-check 20+ Slack-heavy tickets. These are where data-model mismatches surface.
- [ ] Webhook-confirmed ticket counts match your local `thena_request_id → helpdesk_ticket_id` map

> [!TIP]
> **LiveChat plan consideration:** LiveChat's Starter plan currently offers only 60-day chat history. If long-term historical access matters, you need Team plan or above for unlimited chat history. ([livechat.com](https://www.livechat.com/pricing/))

## The Two-Migration Frame

The mistake is treating Thena → LiveChat as a single import job. It's two migrations with one cutover: historical records into HelpDesk, future conversations into LiveChat. These require separate scripts, separate API credentials, and separate validation passes.

For source-side export details, see our guide on [how to export data from Thena](https://clonepartner.com/blog/blog/how-to-export-data-from-thena-methods-api-limits-formats/). For a deeper look at the HelpDesk import API, the [Zendesk to LiveChat migration guide](https://clonepartner.com/blog/blog/zendesk-to-livechat-migration-the-complete-technical-guide/) covers that side in more detail.

> Need help migrating from Thena to LiveChat? Our team handles the API extraction, Slack identity resolution, data transformation, and validation — typically completed in days, not weeks. Book a 30-minute call to scope your migration.
>
> [Talk to us](https://cal.com/clonepartner/meet?duration=30)

## Frequently asked questions

### Can I import Thena data directly into LiveChat?

No. LiveChat handles real-time chat sessions, not historical ticket imports. LiveChat's legacy ticketing was sunset in January 2025. Historical Thena data must be imported into HelpDesk via the POST /v1/importedTickets endpoint.

### How do I handle Slack users without email addresses during the migration?

HelpDesk requires an email address for every requester. Query the Slack API (users.info with users:read.email scope) to resolve Slack IDs to emails. For users whose workspaces restrict email visibility or who are deactivated, generate a fallback email like unknown-{slack_user_id}@migration.internal and tag those tickets for manual review.

### Can I preserve original timestamps from Thena in HelpDesk?

Yes. HelpDesk's imported tickets API lets you set historical dates on events — the first message's date becomes the ticket creation date. Events must be chronologically ordered and all dates must be in the past. LiveChat chat events, by contrast, use server-generated timestamps that cannot be overridden.

### Can I preserve Thena's AI-generated metadata in HelpDesk?

Not natively. HelpDesk has no fields for AI summaries, sentiment, or urgency sources. Store them in HelpDesk custom fields (singleLine: 120 chars, multiLine: 1,000 chars), append them to the ticket body, or discard them.

### How long does a Thena to LiveChat migration take?

For 3,000 requests with conversations: roughly 3-4 hours of API runtime. Thena's 60 req/min rate limit is the bottleneck. Add development time for scripting, Slack user resolution, and validation — typically 3-7 days of total engineering effort.
