Help Scout to Dixa Migration: A Technical Guide
Technical guide to migrating from Help Scout to Dixa. Covers API extraction, data mapping, conversation import, workflow redesign, and edge cases.
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
Help Scout to Dixa Migration: A Technical Guide
A Help Scout to Dixa migration moves your support operation from an email-centric shared inbox to a conversation-centric, push-based routing platform. The data transfer is well-defined: Help Scout's Mailbox API 2.0 exports conversations, threads, customers, and tags. Dixa's conversation import endpoint accepts historical records with original timestamps. The hard part is the workflow and routing redesign — translating Help Scout's folder-based organization and IF/THEN workflows into Dixa's visual Flow Builder and queue-based routing engine.
TL;DR Conversation history, contacts, tags, and custom fields extract cleanly from Help Scout via the Mailbox API 2.0 and load into Dixa via POST /v1/conversations/import. Help Scout's API rate limit is 400 requests per minute per OAuth token; Dixa's import API allows 10 requests per second per token (864,000/day). The routing redesign (Help Scout mailboxes + workflows → Dixa Flows + Queues) is the most time-consuming task. Help Scout's Docs knowledge base must be migrated separately into Dixa Knowledge. Realistic timelines range from 2–3 weeks for a simple email-only migration to 5–8 weeks for complex multi-channel setups with heavy workflows.
For Help Scout extraction details, see How to Export Data from Help Scout: Methods, API Limits & Formats. For Dixa export mechanics, refer to How to Export Data from Dixa: Methods, API Limits & Data Mapping. For zero-downtime migration strategy, see Zero-Downtime Help Desk Data Migration.
Architectural Differences: Mailboxes vs. Real-Time Routing
Before mapping fields, understand how data behaves in both systems. Three architectural differences make this migration non-trivial.
Pull Model vs. Push Model
Help Scout uses a pull model. Emails arrive in a Mailbox. Agents open the Mailbox, view a list of active conversations, and select what to work on. Workflows can assign conversations to specific users, but the system does not enforce real-time presence — it doesn't know whether the agent is actually at their desk.
Dixa uses a push model. Conversations arrive, hit a Flow (a visual routing program), and are assigned to a Queue. Dixa then offers the conversation to the most appropriate available agent in real-time based on skill level, availability status, and priority weighting. If the agent does not accept within a defined timeout interval, Dixa offers it to the next eligible agent.
If your team spends time cherry-picking from a shared queue, Dixa's offer-based model eliminates that overhead. But it also means agents accustomed to self-selecting work need explicit retraining on how offers function before go-live.
Threads vs. Messages
Help Scout structures communication as a Conversation containing Threads. A thread can be a customer reply, an agent reply, or an internal note. Thread type is stored in the type field: customer, reply, note, phone, chat, email.
Dixa structures communication as a Conversation containing Messages (inbound/outbound) with a declared channel type. The conceptual model is similar, but Dixa places heavier emphasis on channel origin (email, widgetchat, phone, whatsapp) because it natively supports voice and messaging, whereas Help Scout is optimized for asynchronous email.
Mailbox-Centric vs. Queue-Centric
Help Scout organizes work into mailboxes mapped to email addresses. Agents switch mailboxes to view different work streams. Dixa organizes work into Queues fed by Flows. A Queue is a holding area; a Flow is the routing logic that decides which Queue a conversation enters. You cannot copy a mailbox into a queue — the routing logic must be redesigned from scratch.
Other Platform Differences
- Native voice support. Help Scout has no built-in phone channel — integrations like Aircall, JustCall, or Dialpad are required. Dixa includes phone, IVR, callback, and call recording natively as first-class channel types.
- Visual Flow Builder vs. flat workflows. Help Scout workflows are simple conditional rules: if [condition], then [action], executing sequentially. Dixa's Flow Builder is a visual, drag-and-drop canvas supporting queue assignment, priority branching, IVR routing, auto-replies, chatbot handoffs, and multi-step escalation.
- Custom fields vs. custom attributes. Help Scout supports up to 10 custom fields per inbox across 5 types:
dropdown,single-line text,multi-line text,number, anddate. Dixa uses custom attributes at the conversation level with its own type system. Field types do not map 1:1, and dropdown option values require manual recreation in Dixa.
Data Model Mapping: Help Scout → Dixa
Before writing any code, map every Help Scout entity to its Dixa equivalent. This table covers the core objects and their migration behavior:
| Help Scout Entity | Dixa Equivalent | Notes |
|---|---|---|
id |
external_id |
Store the Help Scout ID in Dixa for audit trails and delta syncs |
| Mailbox | Queue + Contact Endpoint | Mailboxes map to email integration endpoints; routing logic moves to Flows and Queues |
| Conversation | Conversation | 1:1 mapping; channel type (email, widgetchat) must be specified |
subject |
subject |
Direct string mapping |
status |
status |
Help Scout: active, pending, closed, spam. Dixa: open, pending, closed. No spam equivalent — filter or discard |
createdAt |
created_at |
Must use Dixa's historical import endpoint to preserve original timestamp |
Thread (type: customer) |
Inbound message | Author = end user (requester) |
Thread (type: reply) |
Outbound message | Author = agent; requires valid agentId UUID in Dixa |
Thread (type: note) |
Internal note | Separate API call: POST /v1/conversations/{id}/notes |
| Customer | End user | Create via POST /v1/endusers before importing conversations |
firstName + lastName |
name |
Concatenate with a space separator for Dixa's single name field |
emails [] |
email |
Help Scout supports multiple emails per customer; Dixa supports multiple contact endpoints per end user |
phones [] |
phone_number |
Normalize to E.164 format (+15551234567) before import |
| User (agent) | Agent | Must exist in Dixa before import; match by email address to obtain Dixa UUID |
| Tags | Tags | Create tags in Dixa first via API or UI; then apply via import payload |
| Custom fields | Custom attributes | Type conversion required; see field-type matrix below |
| Saved replies | Templates | No automated migration; recreate manually in Dixa |
| Docs articles | Dixa Knowledge articles | Separate migration via Help Scout Docs API v1 |
| Satisfaction ratings | Conversation ratings | Help Scout Great/Okay/Not Good (3-point) → no direct equivalent in Dixa's CSAT (1–5 scale). Apply a mapping convention before import |
| Workflows | Flows | Complete redesign required; no import path exists |
Custom Field Type Compatibility Matrix
Help Scout and Dixa use different type systems for structured conversation data. This table shows the recommended mapping:
| Help Scout Field Type | Dixa Custom Attribute Type | Conversion Notes |
|---|---|---|
dropdown |
select (single-value) |
Option IDs must be resolved to label text first (via GET /v2/mailbox-fields/{id}); recreate option values in Dixa |
single-line text |
text |
Direct string mapping |
multi-line text |
text (multi-line) |
May need HTML stripping if field contains formatted content |
number |
numeric |
Validate min/max if Dixa attribute has range constraints |
date |
date |
Standardize to ISO 8601 (YYYY-MM-DD) before import |
No direct mapping for: Help Scout folders (Dixa uses Flows + queue filters), Help Scout Beacon widget (Dixa has its own widget SDK), Help Scout spam status (Dixa has no spam queue — decide whether to import these as closed or exclude them), and Help Scout reporting views (Dixa analytics are structured differently and cannot import historical metric aggregates).
Extraction: Getting Data Out of Help Scout
Help Scout has no bulk export button for conversation content. As we noted in our Help Scout to Deskpro migration guide, the built-in UI export covers reporting metrics only — conversation volume, response times, happiness scores — and explicitly excludes message bodies, thread content, and satisfaction comments. You need the Mailbox API 2.0 for a migration-grade export. Official documentation is at developer.helpscout.com/mailbox-api.
Authentication and Rate Limits
Help Scout uses OAuth 2.0 (client credentials flow). Tokens expire after 48 hours. The API enforces a hard rate limit of 400 requests per minute per OAuth token. Exceeding this returns HTTP 429 Too Many Requests. Response headers X-RateLimit-Remaining and X-RateLimit-Reset let you throttle dynamically. Your extraction script must implement exponential backoff with jitter on 429 responses.
If running multiple integrations concurrently during migration (e.g., your Salesforce CRM sync and your migration pipeline), provision a separate OAuth app and token per integration. Rate limits are enforced per token, not per account, so token isolation prevents starvation.
Pagination Strategy
Help Scout uses HAL (Hypertext Application Language) for pagination. Responses contain a _links.next.href URL. Follow this URL to retrieve the next page. Do not attempt to construct page URLs manually or guess cursor IDs — HAL pagination URLs may contain query parameters that vary per request.
Extraction Sequence
Run these calls in order to build a complete dataset before beginning import:
- List mailboxes —
GET /v2/mailboxes— identify which mailboxes to include in the migration scope. - List conversations —
GET /v2/conversations?mailbox={id}&status=all— paginated at 25 conversations per page. The default returns onlyactiveconversations;status=allis required to retrieve historical closed/pending records. Use themodifiedSinceparameter for incremental passes during the delta sync phase. - Get threads per conversation —
GET /v2/conversations/{id}/threads— message bodies live here, not in the list response. This requires one API call per conversation, which is the primary rate limit bottleneck. - Get customers —
GET /v2/customers— paginated. Includes emails, phones, and profile data. - Get custom fields —
GET /v2/mailbox-fields/{mailboxId}— returns field definitions including dropdown option IDs and display labels. Required to decode option IDs stored in conversation records. - Get attachments —
GET /v2/attachments/{id}/data— returns base64-encoded file content. Run as a separate background pass to avoid consuming rate limit budget during conversation extraction. - Get Docs articles — via Help Scout Docs API v1 (separate auth endpoint, separate rate limits — limits vary by the number of Docs sites on your account).
curl -X GET 'https://api.helpscout.net/v2/conversations?status=all' \
-H 'Authorization: Bearer YOUR_TOKEN'Extraction Volume Math
For 50,000 conversations at Help Scout's 400 req/min rate limit:
| Operation | Request Count | Time at 400 req/min |
|---|---|---|
| List conversations (25/page) | 2,000 | ~5 minutes |
| Fetch threads (1 per conversation) | 50,000 | ~125 minutes |
| Fetch customers | ~5,000–10,000 | ~15–25 minutes |
| Fetch attachments (variable) | 10,000–100,000+ | 25–250 minutes |
| Total (excluding attachments) | ~57,000–62,000 | ~145–155 minutes |
Attachments are the wildcard. A single conversation thread with 10 emails, each containing a company logo signature image, generates 10 separate attachment API calls. For support teams with high email volume and image-heavy templates, attachment calls can exceed conversation thread calls in total volume.
# Simplified extraction loop (Python)
import requests, time, random
BASE = "https://api.helpscout.net/v2"
headers = {"Authorization": f"Bearer {access_token}"}
def extract_conversations(mailbox_id):
page = 1
while True:
resp = requests.get(
f"{BASE}/conversations",
params={"mailbox": mailbox_id, "status": "all", "page": page},
headers=headers
)
if resp.status_code == 429:
# Exponential backoff with jitter
wait = int(resp.headers.get("Retry-After", 10)) + random.uniform(0, 2)
time.sleep(wait)
continue
data = resp.json()
for conv in data["_embedded"]["conversations"]:
threads = fetch_threads(conv["id"])
yield {**conv, "threads": threads}
if page >= data["page"]["totalPages"]:
break
page += 1
time.sleep(0.15) # ~400 req/min ceiling with bufferThe Attachment Bottleneck
The /v2/conversations endpoint returns thread metadata, but not actual file data for attachments — only an attachment id. Retrieving file content requires a separate call to GET /v2/attachments/{id}/data, which returns base64-encoded binary.
Best practice: Extract conversation metadata and log all attachment IDs to a separate database table or job queue. Run a background worker that downloads attachments at ~300 requests/minute (leaving headroom), stores them in AWS S3 or GCS with their original filenames, and records the resulting public URL. During the Dixa import phase, pass the hosted URL as the attachment reference rather than attempting to stream base64 content directly through the import API.
Merged conversation gotcha: Help Scout returns HTTP 301 for merged conversations for 60 days after merging, then returns 404. If your dataset includes recently merged conversations, complete your extraction before the 60-day window expires or you will lose access to the redirected conversation thread permanently.
Loading: Importing Conversations into Dixa
Dixa provides POST /v1/conversations/import specifically for loading historical records. This is distinct from POST /v1/conversations, which creates live conversations, triggers agent notifications, updates current SLA timers, and stamps records with the current timestamp rather than preserving the original createdAt. Always use the import endpoint for migration; never use the live endpoint for historical data.
Full API reference: docs.dixa.io/openapi.
Prerequisites Before Import
Complete all of the following before importing a single conversation:
- Create end users. Every requester must exist as an end user in Dixa. Use
POST /v1/endusers. If the end user is missing, the import call returns a400or422error. Deduplicate by email address before bulk creation — Dixa will reject duplicate email entries. - Map agents. Outbound messages require a valid Dixa
agentId(UUID). Provision agents in Dixa via the UI or SCIM before import. Match Help Scout agent email addresses to Dixa agent UUIDs and store the mapping in a lookup table. - Create tags. Tags must exist in Dixa before they can be referenced in import payloads. Create them via the UI or
POST /v1/tagsAPI endpoint. - Set up email integration endpoints. Email conversations require a valid
emailIntegrationId— the Dixa-side email address that serves as the channel identity for that mailbox. Configure these in Dixa's channel settings before import. - Pre-create custom attributes. All Help Scout custom field definitions must have a corresponding custom attribute configured in Dixa (matching type and, for dropdowns, matching option values) before import payloads reference them.
Dixa API Rate Limits
Per the Dixa API documentation, rate limits are enforced per token: 10 requests per second with a burst allowance, and a daily ceiling of 864,000 requests per token. On 429 Too Many Requests responses, Dixa does not consistently return a Retry-After header — your client must implement its own exponential backoff with jitter rather than relying on header-driven throttling.
Because limits are per token rather than per account, you can distribute import workload across multiple API tokens to increase total throughput. For migrations exceeding 100K conversations, this parallelization is practical and significantly reduces calendar time.
Import Payload Structure
{
"requesterId": "<dixa-enduser-uuid>",
"emailIntegrationId": "support@email.dixa.io",
"subject": "Original Help Scout subject",
"createdAt": "2024-06-15T10:30:00Z",
"externalId": "hs-conv-12345",
"message": {
"content": {
"value": "Original message body (HTML or plain text)",
"_type": "Text"
},
"attachments": [
{
"url": "https://your-s3-bucket.amazonaws.com/attachments/file.pdf",
"filename": "file.pdf",
"mimeType": "application/pdf"
}
],
"_type": "Inbound"
},
"language": "en",
"_type": "Email"
}After creating the conversation with the initial message, subsequent messages and notes are added via:
- Agent replies:
POST /v1/conversations/{id}/messageswith_type: "Outbound" - Customer follow-ups:
POST /v1/conversations/{id}/messageswith_type: "Inbound" - Internal notes:
POST /v1/conversations/{id}/notes - Custom attributes:
PATCH /v1/conversations/{id}/custom-attributes - Tags:
PATCH /v1/conversations/{id}/tags
Common Import Failure Modes
Dixa's import endpoint does not return detailed error messages for all failure conditions. Understanding what responses correspond to what problems reduces debugging time:
| Failure Condition | Typical HTTP Response | Resolution |
|---|---|---|
| End user does not exist | 400 or 422 with vague body |
Create end user first via POST /v1/endusers; retry |
Invalid emailIntegrationId |
422 Unprocessable Entity |
Verify integration endpoint is active in Dixa channel settings |
| Agent UUID not found | 422 or silent message omission |
Re-fetch agent list; update mapping table |
| Malformed timestamp (non-ISO 8601) | 400 Bad Request |
Normalize all timestamps to UTC ISO 8601 before import |
Duplicate externalId |
200 with no-op (idempotent) or 409 depending on API version |
Safe to retry; use externalId to detect already-imported records |
| Tag not pre-created | 422 or tag silently ignored |
Create all tags before import; validate tag IDs in payload |
| Oversized attachment URL | 400 |
Ensure attachment URLs are publicly accessible and < 2048 chars |
Channel type constraint: The Dixa import endpoint currently supports email and widgetchat channel types. Phone conversations from Help Scout integrations (Aircall, etc.) must be imported as email-type records with metadata in the subject or a custom attribute indicating the original channel, or stored in an external data warehouse.
Import Sequence
- Batch-create all end users in Dixa (deduplicate by email address first)
- Build agent email → Dixa UUID lookup table
- Create all tags in Dixa
- For each conversation (ordered by
createdAtascending):- POST the initial message to create the conversation
- POST subsequent messages in strict chronological order
- POST internal notes
- PATCH tags
- PATCH custom attributes
- Validate record counts; spot-check thread content in Dixa UI
Handling Inline Images
Help Scout frequently embeds images directly into email thread HTML using <img src="https://storage.helpscout.net/..."> tags pointing to Help Scout's CDN. When you cancel your Help Scout subscription, these URLs become inaccessible.
During migration: parse every thread's HTML body, extract all src attribute values pointing to Help Scout domains, download the referenced images, upload them to your own S3 or CDN, and rewrite the src attributes in the payload before posting to Dixa. This step is non-optional if you intend to cancel Help Scout — skipping it produces broken images in every affected historical conversation.
Workflow Redesign: Help Scout Workflows → Dixa Flows and Queues
Whether you are moving from Help Scout or performing a Zendesk to Dixa migration, this is the most labor-intensive part of the process. It is also where most teams underestimate effort. Unlike data migration, workflow redesign cannot be automated — it requires understanding both platforms deeply and making explicit product decisions about how your team should work.
Mailboxes to Queues
In Help Scout, a Mailbox represents an inbound email address (e.g., support@company.com). Agents switch between Mailboxes to view different work streams. Assignment is mostly passive — conversations sit until someone picks them up.
In Dixa, you connect the email address as a channel endpoint, but routing is handled by a Flow. The Flow evaluates the incoming message and routes it to a Queue. Queues have agents attached to them with defined skill levels. Dixa then actively offers conversations to available agents.
Action Item: Before rebuilding workflows, audit your Help Scout Mailboxes for actual routing intent. In most teams, 10 mailboxes can collapse into 3–4 Queues with tag-based differentiation. Dixa's push routing performs better with fewer, well-defined Queues than with many narrow Queues that leave agents idle.
Workflow-to-Flow Decision Framework
Use this framework to translate each Help Scout workflow into Dixa architecture:
Step 1: Classify the workflow's purpose
- Routes conversations to a team or person → Dixa Flow routing node
- Adds metadata (tag, custom field) → Dixa Flow action node
- Sends an automated reply → Dixa Flow auto-reply node
- Closes or moves conversations on a schedule → Dixa's SLA or timeout rules
- Triggers on agent action (button click) → Dixa Quick Action or macro
Step 2: Identify the trigger condition
- Conversation created → Flow entry point condition
- Conversation updated (tag added, status changed) → Dixa event-based Flow trigger
- Time-based (e.g., no reply in 24h) → Dixa SLA breach action
Step 3: Map the condition logic
| Help Scout Workflow Condition | Dixa Flow Equivalent |
|---|---|
| Subject contains [text] | Message content condition node |
| From email domain = [domain] | Requester attribute condition |
| Tag = [tag] | Tag condition node |
| Assigned to [agent] | Agent assignment condition |
| Mailbox = [mailbox] | Channel/queue condition |
| Time of day | Business hours condition node |
| Language detected | Language detection node (Dixa native) |
Step 4: Map the action
| Help Scout Workflow Action | Dixa Flow Equivalent |
|---|---|
| Assign to [agent] | Route to Queue + agent preference setting |
| Assign to [team] | Route to Queue mapped to that team |
| Add tag | Tag action node |
| Send auto-reply | Auto-reply node with template |
| Move to mailbox | Route to different Queue |
| Close conversation | Close action node |
| Round-robin assignment | Built into Queue-level agent distribution (automatic) |
| Load-based assignment | Built into Dixa's offer-based routing by default |
What you gain: Dixa's push-based routing eliminates many Help Scout workflows whose sole purpose was distributing work across agents. The platform handles load balancing, availability awareness, and skill-based routing natively. Workflows that existed to compensate for Help Scout's passive pull model become unnecessary.
What you lose: Help Scout's simplicity. Dixa Flows are more powerful but have a steeper learning curve. Plan at minimum one week of Flow Builder training for your operations team before go-live, and allocate time for iterative testing of each Flow path.
Knowledge Base Migration: Help Scout Docs → Dixa Knowledge
Help Scout Docs uses a hierarchy of Sites → Collections → Categories → Articles. Dixa Knowledge uses a similar hierarchy. Articles extract via Help Scout's Docs API v1, which uses separate authentication from the Mailbox API and has its own rate limits (which vary based on the number of Docs sites on your account — check your plan limits in Help Scout's account settings).
Extraction Steps
GET /v1/collections— list all collections for each Docs siteGET /v1/collections/{id}/articles— list articles per collection (paginated)GET /v1/articles/{id}— fetch full article content (HTML body, metadata, publish status)
Key fields to extract per article: id, collectionId, name (title), text (HTML body), slug, status (published vs. draft), publicUrl, lastPublishedAt.
Import to Dixa Knowledge
Create the category hierarchy in Dixa Knowledge first, then import articles preserving the original slug where possible (for SEO continuity if your Help Scout Docs were publicly indexed). Article HTML bodies require the same inline image treatment as conversation threads — extract all src references, re-host images, and rewrite URLs before import.
Image dependency risk: Images in Help Scout Docs articles are hosted on Help Scout's CDN. Canceling Help Scout without re-hosting these images produces broken images in every migrated article. This step is consistently underestimated in effort — a Docs site with 200 articles and average 5 images each means 1,000 images to download, re-host, and rewrite.
Migration Strategy: Delta Sync for Zero Downtime
Support teams cannot pause operations during a migration. A delta sync strategy handles the gap between initial extraction and go-live.
Phase 1: Initial Sync
Extract all historical data from Help Scout up to a defined cutoff timestamp. Record that cutoff timestamp. Import into Dixa. This process takes hours to days depending on volume and rate limits.
Phase 2: Configuration Freeze
Lock all configuration changes in Help Scout: no new tags, custom fields, or mailboxes. This prevents schema drift between your initial sync and delta.
Phase 3: Go-Live
Update DNS MX records and email forwarding rules to route new inbound messages to Dixa endpoints. Have agents log into Dixa to handle incoming volume from this point forward.
Phase 4: Delta Sync
Query Help Scout's /v2/conversations endpoint using modifiedSince={initial_sync_cutoff}. This returns all conversations modified after your initial extraction — including conversations that were active during migration and received replies. Import these delta records into Dixa, using externalId to update existing records or create new ones. Run the delta sync multiple times (every 30–60 minutes during the transition window) until conversation modification rates drop to near-zero.
# Delta sync query
resp = requests.get(
f"{BASE}/conversations",
params={
"mailbox": mailbox_id,
"status": "all",
"modifiedSince": initial_sync_cutoff.isoformat() # ISO 8601 UTC
},
headers=headers
)Phase 5: Cutover Validation
After delta sync completes, verify that conversations modified in Help Scout after the initial sync are present and current in Dixa. Check status, latest message content, and tag state. Then disable Help Scout's email forwarding and declare migration complete.
Pre- and Post-Migration Validation
While our general Help Scout migration checklist covers moving data into the platform, extracting data to Dixa requires its own specific validation steps.
Pre-Migration Validation Checklist
- All Help Scout custom fields have a corresponding Dixa custom attribute with correct type and options
- Total conversation count per mailbox documented (active, pending, closed separately)
- Total customer count documented
- All agent emails confirmed to exist in Dixa with correct UUIDs
- All tags created in Dixa
- All email integration endpoints active in Dixa
- Test batch of 500–1,000 conversations imported into sandbox; timestamps, thread order, and attachments verified
Post-Migration Validation Checklist
- Total conversation count in Dixa matches Help Scout export count (±0.5%)
- Total message count per conversation matches for 50 sampled conversations
- Total customer count in Dixa matches Help Scout export
- 20 random attachments downloaded successfully (no 404 errors)
- Help Scout
pending→ Dixapendingverified on 10 conversations - Help Scout
closed→ Dixaclosedverified on 10 conversations; none accidentally reopened - Every Flow path tested with a real inbound message; conversations land in correct queues with correct priority
- 50–100 conversations manually reviewed for thread completeness, internal note presence, and agent attribution
- Custom attribute values verified on 20 conversations with populated fields
- CSAT ratings present on conversations where Help Scout satisfaction was recorded
Post-Cutover Monitoring (First 14 Days)
Watch for: conversations that don't route correctly (wrong queue, wrong agent), attachments that fail to render, customers replying to old Help Scout threads via forwarded email (set up email forwarding catch-all to detect these), and agents who accidentally continue working in Help Scout rather than Dixa.
Edge Cases and Failure Modes
These issues consistently surface in Help Scout migrations:
- Merged conversations returning 404. Help Scout redirects merged conversations via HTTP 301 for 60 days. After that, they return 404 with no data. Time your extraction within the 60-day window, or accept that merged conversation history before that cutoff may be irrecoverable.
- Attachments as base64. Help Scout's API returns attachment file data as base64-encoded strings. Dixa's import endpoint accepts attachment URLs, not base64 content. Re-host all attachments to S3/GCS and pass URLs.
- Custom field dropdown option IDs. Help Scout stores dropdown selections as option IDs (integers), not display labels. The raw conversation export contains
fieldId: 42, value: 7. Without callingGET /v2/mailbox-fields/{mailboxId}to resolve7→"Enterprise", the data is unreadable. Always resolve option IDs to labels before transformation. - Inline image breakage. Help Scout embeds images in thread HTML with
srcURLs pointing tostorage.helpscout.net. These become inaccessible after account cancellation. Parse and re-host during extraction. - Help Scout
spamstatus. Dixa has no spam queue. Decide pre-migration whether to import spam conversations asclosedwith aspamtag, or exclude them entirely. The exclusion approach is simpler but loses the historical record. - Chat conversations via Beacon. Help Scout Beacon chat conversations have a different thread structure than email (no subject, different author fields). Map them to Dixa's
widgetchatchannel type, but validate that the thread structure renders correctly — the interaction model differs significantly. - Satisfaction rating scale mismatch. Help Scout Great/Okay/Not Good (3-point) → Dixa's CSAT (1–5). Recommended mapping: Great → 5, Okay → 3, Not Good → 1. Store the original rating in a custom attribute to preserve raw data.
- Timezone inconsistencies. Help Scout's UI export uses company timezone for CSV and UTC for XLSX. The Mailbox API 2.0 returns UTC. Dixa's import endpoint expects ISO 8601 with timezone offset. Standardize all timestamps to UTC during extraction regardless of source format.
- Empty end user lookup responses. Dixa's
GET /v1/endusers?email={email}returns an emptydata: []array (HTTP 200) when no match is found — not a 404. Your deduplication logic must checkdata.length === 0rather than catching an error status. - Agent deactivation. If Help Scout agents have been deactivated but their conversations are in scope, their email addresses may not exist in Dixa. Create placeholder inactive agents in Dixa or map deactivated agents to a generic "Former Agent" account to avoid broken
agentIdreferences.
Timeline and Effort Estimates
| Scenario | Conversations | Agents | Channels | Estimated Timeline |
|---|---|---|---|---|
| Simple (email only, ≤5 workflows, no KB) | < 20K | < 10 | 2–3 weeks | |
| Medium (email + chat, custom fields, 5–15 workflows, small KB) | 20K–100K | 10–30 | Email, chat | 3–5 weeks |
| Complex (multi-channel, heavy workflows, large KB, integrations) | 100K+ | 30+ | Email, chat, phone | 5–8 weeks |
Week-by-Week Breakdown (Medium Migration)
- Week 1: Audit Help Scout data (mailboxes, conversation volumes, custom field definitions, workflow inventory). Stand up Dixa sandbox instance. Design queue structure, Flow architecture, and agent skill model. Complete custom field type mapping decisions.
- Week 2: Build extraction scripts. Run first test migration with the smallest mailbox. Validate timestamp accuracy, thread ordering, attachment rendering, and custom attribute values. Identify and fix mapping issues.
- Week 3: Full test migration of all mailboxes into Dixa sandbox. QA data integrity against the validation checklist. Rebuild all Help Scout workflows as Dixa Flows. Test every Flow path with synthetic conversations.
- Week 4: Final migration run. Parallel operation period (agents work in both systems temporarily). Agent training on Dixa's offer-based model, Flow interactions, and Queue management.
- Week 5: DNS/MX cutover. Email forwarding redirected to Dixa. Delta sync runs. Monitor for routing failures, missing conversations, and attachment errors. Keep Help Scout active (read-only access) for 30 days post-cutover.
When to DIY vs. Use a Migration Service
DIY makes sense when:
- Fewer than 10K conversations
- Email-only, no chat or phone channels
- Fewer than 5 Help Scout custom fields, all simple types (no complex dropdown hierarchies)
- Fewer than 5 workflow rules to redesign as Flows
- An engineer comfortable with REST APIs, pagination, and JSON transformation available for 2–3 weeks of focused work
A migration service makes sense when:
- Volume exceeds 50K conversations
- Multiple channels including voice (requires Help Scout CTI integration data extraction)
- Custom dropdown fields with many option values requiring manual resolution and recreation
- Docs knowledge base with embedded images at scale (200+ articles)
- Zero-downtime requirement with a delta sync window measured in hours, not days
- Engineering team is at capacity and cannot absorb 3–5 weeks of migration work
The extraction side is manageable for any engineer comfortable with REST APIs and pagination. The import side has more failure modes — end user deduplication, attachment re-hosting, agent UUID mapping, and Dixa's opaque error responses on certain failure conditions. The workflow redesign is where most teams lose time: it requires understanding Dixa's Flow Builder deeply enough to express your existing routing logic in a new visual paradigm, and then testing every path before you cut over live traffic.
Much like a Help Scout to HubSpot Service Hub migration, moving to Dixa is a systems engineering project. The data transfer requires strict adherence to API rate limits, careful attachment handling, and rigorous timestamp normalization. The workflow transition requires making explicit product decisions about how your team operates — decisions that will affect agent experience, first response time, and CSAT from day one in Dixa. Treat this as an infrastructure migration, not a software switch, and staff it accordingly.
Frequently Asked Questions
- Can I migrate Help Scout conversations to Dixa with original timestamps?
- Yes. Dixa's POST /v1/conversations/import endpoint accepts a createdAt field, allowing you to preserve the original Help Scout conversation timestamps during import. If you use the standard conversation creation endpoint instead, all imported tickets will reflect the date of the migration.
- What are the API rate limits for a Help Scout to Dixa migration?
- Help Scout allows 400 API requests per minute per OAuth token. Dixa allows 10 requests per second per API token (864,000 per day). Both return HTTP 429 when limits are exceeded, though Dixa does not include a Retry-After header.
- Can I migrate Help Scout attachments to Dixa?
- Yes, but it requires extracting attachment files from Help Scout's API (returned as base64), hosting them on S3 or another accessible URL, and passing the new URLs to Dixa during import. If you skip re-hosting, attachment links break when you cancel Help Scout.
- How long does a Help Scout to Dixa migration take?
- A small migration (under 20K conversations, email only) takes 2–3 weeks. Medium complexity (20K–100K conversations, multiple channels, custom fields) takes 3–5 weeks. Complex migrations with large volumes, knowledge base content, and workflow redesign can take 5–8 weeks.
- Can I migrate Help Scout Docs articles to Dixa Knowledge?
- Yes, but it's a separate process. Extract articles via Help Scout's Docs API v1, then create them in Dixa Knowledge via the Dixa API. Download and re-host any embedded images before decommissioning Help Scout, or they will break.



