Help Scout to Deskpro Migration: A Technical Guide
Migrate from Help Scout to Deskpro with this technical guide covering API extraction, data model mapping, thread handling, attachments, rate limits, and validation.
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 Deskpro Migration: A Technical Guide
TL;DR — Help Scout to Deskpro Migration
A Help Scout to Deskpro migration translates Help Scout's mailbox-centric, shared-inbox architecture into Deskpro's department-centric ticket model. Conversations become Tickets, Threads become Messages, Customers become People, and Mailboxes map to Departments. There is no built-in Help Scout importer in Deskpro — you need a Help Scout Mailbox API v2 → Deskpro REST API v2 pipeline. Help Scout's native CSV export strips message bodies, thread content, and attachments, making API extraction mandatory. Workflows, Saved Replies, and Beacon configurations must be rebuilt manually. Realistic timeline: 1–2 weeks for under 20K conversations; 3–4 weeks for larger datasets with custom fields and knowledge base articles.
Verified against Help Scout Mailbox API v2 and Deskpro REST API v2. Rate limit figures are empirically observed; see sourcing notes inline.
What Is a Help Scout to Deskpro Migration?
A Help Scout to Deskpro migration extracts Conversations, Threads, Customers, Companies, Tags, Custom Fields, Users, Teams, and Docs articles from Help Scout and reconstructs them to fit Deskpro's ticket-centric model of Tickets, Messages, People, Organizations, Labels, Custom Fields, Agents, Agent Teams, and Knowledgebase Articles.
The core question before you start: do you need searchable thread history with full message bodies, or just ticket metadata? If agents need to reference historical conversation context after cutover — and they almost always do — this is an API-to-API ETL (Extract, Transform, Load) job, not a CSV shuffle.
Help Scout is an email-first customer support platform built around shared inboxes (Mailboxes). Every customer interaction is a Conversation containing Threads — customer messages, agent replies, internal notes, and forwards. It abstracts away complex ITIL concepts in favor of simplicity. API access requires a paid plan. (Help Scout API documentation)
Deskpro is a full-featured helpdesk platform available as both cloud-hosted and self-hosted (on-premise). It uses a department-centric architecture where Tickets are assigned to Departments, supports complex SLAs, and relies on a hierarchical structure of Departments, Agent Teams, and User Organizations. (Deskpro developer documentation)
Teams typically make this move for Deskpro's on-premise deployment option, its DPQL reporting language, multi-brand support, or when they've outgrown Help Scout's automation capabilities.
This is not a simple lift-and-shift. The two platforms have different enough data models that copy-paste won't work — but they're similar enough that a clean API pipeline handles the translation well.
Help Scout vs. Deskpro: Data Model Mapping
Before writing any extraction code, map every Help Scout entity to its Deskpro equivalent. This mapping drives the entire migration pipeline.
| Help Scout Entity | Deskpro Equivalent | Migration Notes |
|---|---|---|
| Mailbox | Department | 1:1 mapping. Deskpro supports nested departments (e.g., Support > Technical, Support > Billing). |
| Conversation | Ticket | Status mapping requires translation (see below). |
| Thread (customer, reply, note) | Message / Note | Thread type field determines message direction. |
| Customer | Person | De-duplicate by email before import. |
| Company | Organization | Help Scout companies are loose associations; Deskpro orgs are first-class entities with formal membership. |
| Tag | Label | Direct 1:1 mapping. |
| Custom Field | Custom Field | Must be pre-created in Deskpro with matching types. Note the field IDs for API writes. |
| User (agent) | Agent | Create agents in Deskpro first; map by email. |
| Team | Agent Team | Rebuild team membership manually. |
| Saved Reply | Snippet | No bulk export API — must be recreated manually. |
| Workflow | Trigger / Automation | No export — must be rebuilt from scratch. |
| Docs Article | Knowledgebase Article | Separate API (Docs API v1) required for extraction. |
The migration order matters: create Organizations before People (so you can link them), create People before Tickets (so you can assign them), and create Agents before anything that needs an assignee.
Status Mapping
Help Scout conversations have four statuses: active, pending, closed, and spam. Deskpro's core ticket statuses are Awaiting Agent, Awaiting User, and Resolved.
| Help Scout Status | Deskpro Status | Rationale |
|---|---|---|
active |
Awaiting Agent | Needs agent action. |
pending |
Awaiting User | Waiting on customer response. |
closed |
Resolved | Completed tickets. |
spam |
(skip or archive) | Don't migrate spam into a clean system. |
Deskpro does not support arbitrary custom ticket statuses. Its status model is deliberately constrained to three core states. If your team relied on Help Scout's pending status in a non-standard way (e.g., as an internal hold state), you'll need to use a Deskpro custom field or workflow state to replicate that behavior.
Why Help Scout's Native Export Won't Work
Many teams try to use Help Scout's built-in export before realizing it won't get the job done. Whether you are moving to Deskpro or performing a Help Scout to HubSpot Service Hub migration, the native export (under Reports → Export) generates CSV/XLSX files, but it does not include message bodies, thread replies, internal notes, or attachments. If you import this data into Deskpro, your agents will see thousands of tickets with subject lines like "Need help with my account" — but the ticket bodies will be entirely empty.
The native export is useful for reporting snapshots — it is not a migration tool. For a migration-ready dataset, you must use the Help Scout Mailbox API v2.
Deskpro offers a built-in Zendesk importer, but there is no equivalent Help Scout importer. The migration path is exclusively: Help Scout API → your transformation layer → Deskpro API.
Extraction: Getting Data Out of Help Scout
Authentication Setup
Help Scout's Mailbox API v2 uses OAuth 2.0 client credentials flow — there is no static API key option for server-to-server access. Full documentation: developer.helpscout.com/mailbox-api/overview/authentication/.
- Go to Your Profile → My Apps in Help Scout
- Create a new OAuth application
- Note the
App IDandApp Secret - Exchange credentials for a bearer token — tokens expire after 48 hours
curl -X POST https://api.helpscout.net/v2/oauth2/token \
-d "grant_type=client_credentials" \
-d "client_id=YOUR_APP_ID" \
-d "client_secret=YOUR_APP_SECRET"The response includes access_token, expires_in (seconds), and token_type: bearer.
Cache your token and handle 401 responses by refreshing automatically. Implement 429 handling by honoring the X-RateLimit-Retry-After header. For bulk extraction spanning multiple hours, implement a checkpoint/resume pattern that persists the last successfully processed conversation ID to disk. Token expiry mid-extraction — and the silent data loss it causes when retry logic isn't implemented — is the most common cause of failed DIY migrations.
Checkpoint pattern (pseudocode):
load last_conversation_id from checkpoint.json
resume pagination from that cursor
on successful batch: write updated cursor to checkpoint.json
on 401: refresh token, retry current batch
on 429: sleep X-RateLimit-Retry-After seconds, retry
Rate Limits by Plan
Help Scout's API rate limits are per-account (shared across all tokens and apps on the same account), not per-token. The following figures are empirically observed in bulk extraction workloads and not explicitly published in Help Scout's documentation — treat them as operational estimates, not contractual guarantees:
| Plan | Observed Rate Limit | Notes |
|---|---|---|
| Standard | ~200 requests/min | Write operations count double against quota. |
| Plus | ~400 requests/min | Write operations count double against quota. |
| Pro | ~800 requests/min | Best for large extractions. |
When you receive a 429 response from Help Scout, the X-RateLimit-Retry-After header specifies the number of seconds to wait before retrying. The response body is:
{
"message": "Too Many Requests",
"retryAfter": 30
}For a 50K-conversation account on the Plus plan: extracting conversations, then threads per conversation (one API call each), then customers, then attachments at ~400 req/min takes roughly 4–6 hours of sustained API calls assuming no retries. Token refresh will occur at least twice during this window, making checkpoint/resume non-optional.
Extraction Order
Extract in this sequence to preserve relational integrity:
- Mailboxes —
GET /v2/mailboxes(provides department mapping IDs) - Users —
GET /v2/users(agents — needed for assignee mapping) - Customers —
GET /v2/customers(paginated via HAL-style_links.next) - Tags —
GET /v2/tags(flat list) - Custom Fields —
GET /v2/mailboxes/{id}/fields(per-mailbox) - Conversations —
GET /v2/conversations?status=all&mailbox={id}&sortField=createdAt&sortDirection=asc(include all statuses; usesortFieldandsortDirectionfor deterministic ordered extraction) - Threads —
GET /v2/conversations/{id}/threads(per-conversation — this is where the actual message content lives) - Attachments — Download from thread attachment URLs before Help Scout access expires
- Docs articles — Docs API v1:
GET https://docsapi.helpscout.net/v1/collections/{id}/articles(uses HTTP Basic auth with your API key as the username and "X" as the password — not OAuth)
Performance optimization: The conversations list endpoint supports an embed=threads parameter that returns thread summaries inline, reducing round trips for low-thread-count conversations. For conversations with many threads, you still need the dedicated threads endpoint to get past the summary truncation.
The List Conversations endpoint returns a preview field containing only a truncated text snippet of the first message — not the full message body. You must call GET /v2/conversations/{id}/threads for each conversation to retrieve actual content. This is the single most common cause of empty ticket bodies in Help Scout migrations. Skipping the threads call produces tickets with correct metadata and subject lines but zero message content.
Handling Merged Conversations
Help Scout allows conversations to be merged. When you request a merged (source) conversation via the API, it returns HTTP 301 Moved Permanently with a Location header pointing to the target conversation URL. Your extraction script must follow these redirects automatically, or you'll receive a silent 404 on the subsequent request and lose that conversation's data entirely.
# Python example: always allow redirects
response = requests.get(
f"https://api.helpscout.net/v2/conversations/{conv_id}",
headers={"Authorization": f"Bearer {token}"},
allow_redirects=True # critical
)
if response.history:
# log the redirect chain for auditing
log_redirect(conv_id, response.url)Thread Type Mapping
Help Scout threads carry a type field that determines how they should be imported into Deskpro:
| Help Scout Thread Type | Deskpro Equivalent | Notes |
|---|---|---|
customer |
Message (from person) | Inbound customer message. |
reply |
Message (from agent) | Agent reply — map createdBy.id to agent. |
note |
Note (internal) | Internal-only; not visible to customer. |
message |
Message (from agent) | Agent-initiated outbound (proactive). |
forwardparent |
(metadata only) | Log as internal note with forward context. |
forwardchild |
(new ticket reference) | Handle as a linked ticket or note. |
phone |
Message | Treat as inbound; tag with "phone" channel. |
chat |
Message | Treat as inbound; tag with "chat" channel. |
Help Scout enforces a maximum of 100 threads per conversation. Verify thread counts post-import for any conversations near this limit — pagination behavior at the boundary is a known edge case.
Loading Data Into Deskpro
Authentication
Deskpro's API v2 uses API key authentication. Create a key under Admin → Apps & Integrations → API Keys. Full documentation: support.deskpro.com/en/guides/developers/api.
curl -H "Authorization: key 2:YOUR_API_KEY" \
https://your-instance.deskpro.com/api/v2/ticketsFor migrations, create a superuser API key to use the X-DeskPRO-Agent-ID header for agent impersonation on write operations. This attributes migrated replies to the correct original agent rather than having every message appear as sent by the migration account.
Cloud vs. self-hosted authentication note: Both deployment types use the same API key format. For self-hosted instances, ensure your API key is created against the correct base URL (your internal hostname or external domain) and that SSL termination is configured correctly if you're running the migration pipeline externally.
Common Deskpro API Error Responses
Understanding the error taxonomy prevents wasted debugging time:
| HTTP Status | Typical Cause | Resolution |
|---|---|---|
400 Bad Request |
Field type mismatch (e.g., sending string to integer custom field), missing required field, or malformed JSON | Check response body — Deskpro returns a errors array with field-level detail |
401 Unauthorized |
Invalid or expired API key | Verify key format: key {key_id}:{key_secret} |
403 Forbidden |
Agent lacks permission for the target department | Use superuser key or verify department access |
404 Not Found |
Referencing a Department, Person, or Agent ID that doesn't exist | Check entity creation order; verify IDs from creation responses |
409 Conflict |
Duplicate email address on Person creation | Fetch the existing Person by email, use their ID |
429 Too Many Requests |
Rate limit exceeded | Back off per Retry-After header; request limit increase from Deskpro support for cloud instances |
A field type mismatch 400 response body looks like:
{
"status": 400,
"code": "invalid_input",
"errors": {
"fields": [
{
"id": 42,
"error": "Field value must be one of: enterprise, growth, starter"
}
]
}
}Load Sequence
Create entities in dependency order:
- Departments — Create departments matching Help Scout mailboxes (or redesign hierarchy now — Deskpro's nested departments support structures Help Scout cannot express)
- Organizations —
POST /api/v2/organizations - People —
POST /api/v2/people(match customers by email; link to organizations;409on duplicate email means the Person already exists — fetch their ID withGET /api/v2/people?primary_email=email@example.com) - Agents — Create via admin UI or invite flow (Deskpro's API does not expose direct agent creation on standard cloud plans; confirm with Deskpro support for your tier)
- Labels — Create labels matching Help Scout tags
- Custom Fields — Pre-create under Admin → Ticket Structure → Ticket Fields with matching field types; note the integer field IDs — these are required in ticket payloads
- Tickets with Messages —
POST /api/v2/ticketswith initial message, thenPOST /api/v2/tickets/{id}/messagesfor subsequent threads in chronological order - Attachments — Upload as blobs via
POST /api/v2/blobs, then reference blob IDs in message payloads - Knowledgebase Articles —
POST /api/v2/knowledgebase/articles
Disable outbound email before importing. Under Admin → Emails → Email Settings, disable all outbound triggers before starting the load phase. If you skip this step, Deskpro will send email notifications to every customer whose ticket is created or updated during import — including new-account welcome emails for every Person record created. There is no unsend. Undo means manually contacting affected customers. Re-enable only after QA validation is complete.
Creating Tickets with Historical Threads
Create the ticket with its first thread, then append subsequent threads in chronological order using POST /api/v2/tickets/{id}/messages. Always include date_created — omitting it causes every migrated ticket to show the migration run date as its creation timestamp, destroying all historical context.
POST /api/v2/tickets
{
"subject": "Original Help Scout Subject",
"person": "customer@example.com",
"department": 5,
"agent": 12,
"status": "resolved",
"date_created": "2022-03-15T09:23:11Z",
"message": {
"message": "<p>First customer message body (HTML)</p>",
"format": "html",
"person": "customer@example.com",
"date_created": "2022-03-15T09:23:11Z"
},
"fields": [
{ "id": 42, "value": "enterprise" }
]
}Map Help Scout createdBy.id to the corresponding Deskpro Agent ID for each thread using your agent email-to-ID lookup table. If the original agent no longer exists in Deskpro, map those threads to a dedicated "Legacy Agent" account — do not silently drop the createdBy attribution.
Delta sync implementation: For the final cutover delta, use Help Scout's modifiedSince query parameter on the conversations endpoint: GET /v2/conversations?modifiedSince=2024-01-15T00:00:00Z. This returns all conversations created or updated after the specified timestamp. Clock skew risk between your migration server and Help Scout's servers is typically under 1 second — use a 60-second buffer on your cutover timestamp to be safe (i.e., set modifiedSince to 60 seconds before your actual initial sync end time).
Deskpro accepts HTML in message bodies, and Help Scout thread bodies are already HTML. You can pass them through directly — but you must sanitize <img> tags that reference Help Scout's CDN (secure.helpscout.net). Those URLs are authenticated and will return 403 errors after you cancel your Help Scout subscription. See the attachment section below for the correct handling pattern.
Handling Attachments and Inline Images
Attachments are the most common point of failure in help desk migrations. Help Scout returns attachment metadata (filename, MIME type, size, URL) within the thread payload under _embedded.attachments.
Standard attachment migration to Deskpro:
- Download the file from the Help Scout attachment URL (authenticated — include your bearer token)
- Upload to Deskpro:
POST /api/v2/blobswithContent-Type: multipart/form-data - Capture the returned
blob_idinteger - Include
"attachments": [{"blob_id": 12345}]in the message payload when creating the ticket thread
Inline image migration:
Thread HTML often contains <img src="https://secure.helpscout.net/..."> tags for images pasted directly into email bodies. These are authenticated CDN URLs that will return 403 after migration.
- Parse the HTML thread body with an HTML parser (not regex)
- Extract all
<img src="...">values matchingsecure.helpscout.netorattachments.helpscout.netdomains - Download each image with your Help Scout bearer token
- Upload to Deskpro via
POST /api/v2/blobs - Replace the original
srcattribute value in the HTML with the new Deskpro blob URL:https://your-instance.deskpro.com/api/v2/blobs/{blob_id}/content - Use the rewritten HTML as the message body in the Deskpro ticket creation payload
Skipping step 1–5 produces broken image placeholders across every historical ticket that contained inline images.
Deskpro Rate Limits
For cloud instances, Deskpro enforces a default global rate limit. 429 responses include a Retry-After header. Contact Deskpro support to request a temporary rate limit increase for your migration window — this is a standard request and typically approved with a few days' notice.
For self-hosted Deskpro, you control the infrastructure. Rate limits are configurable at the application layer. For bulk import performance, consider:
- Increasing PHP-FPM worker count (default is often 5–10; increase to 20–30 for migration)
- Adjusting MySQL/PostgreSQL connection pool limits to match worker count
- Using the Deskpro CLI import tools if available for your version, which bypass the HTTP API entirely and write directly to the database
Self-hosted deployments also allow you to temporarily disable background job processing during import to reduce database contention, then re-enable it after load is complete.
Knowledge Base Migration: Docs to Deskpro Knowledgebase
Help Scout's knowledge base (Docs) uses a separate API — the Docs API v1 — with its own authentication (HTTP Basic: API key as username, "X" as password — not OAuth). Base URL: https://docsapi.helpscout.net/v1/. Documentation: developer.helpscout.com/docs-api/.
The hierarchy mapping:
- Help Scout: Site → Collection → Category → Article
- Deskpro: Knowledgebase → Category → Article
The mapping is straightforward, but watch for these edge cases:
- Article slugs and URLs change. Set up 301 redirects from old Help Scout Docs URLs to new Deskpro Knowledgebase URLs, or you'll lose organic search traffic. For Apache:
Redirect 301 /docs/old-article-slug /kb/new-article-path. For nginx:return 301 /kb/new-article-path;inside a location block matching the old Docs URL pattern. - Embedded images in articles reference Help Scout CDN URLs. Download and re-upload to Deskpro, then rewrite
srcattributes using the same pattern as inline images above. If you leave the original URLs in place, those images break the moment you cancel your Help Scout subscription. - Article status — Help Scout articles can be
publishedornotpublished. Map to Deskpro's published/draft states respectively. - Docs API rate limits are scoped per 10-minute window and tied to the number of Docs sites on your account, not your plan tier.
What Cannot Be Migrated Automatically
Some Help Scout data has no API export path and must be rebuilt manually in Deskpro:
| Help Scout Feature | Why It Can't Be Migrated | Deskpro Rebuild Approach |
|---|---|---|
| Workflows | No export API. Stored as platform-internal configuration. | Rebuild as Deskpro Triggers and Automations. Deskpro's automation engine separates by event type: New Ticket Triggers, Ticket Update Triggers, and Time-based Escalations. |
| Saved Replies | Not accessible via API in bulk. | Recreate as Deskpro Snippets or Macros. |
| Satisfaction Ratings | Exportable as aggregate metrics only — no per-conversation CSAT data via API. | Migrate as custom field values (e.g., integer rating) or internal notes appended to each ticket, if the data is worth preserving. |
| Beacon Configuration | Widget config, not data. | Configure Deskpro Messenger from scratch; deploy new JavaScript snippet. Beacon and Deskpro Messenger are functionally equivalent (embedded chat + help widget), but configuration is not portable. |
| Report Dashboards | Platform-specific metric calculations not exportable. | Rebuild using Deskpro's DPQL report builder. DPQL only calculates metrics on tickets processed by Deskpro — migrated tickets will have timestamps but no SLA breach history. |
Before migration, export every active Help Scout Workflow and Saved Reply to a structured spreadsheet: trigger conditions, matching criteria, actions taken, and frequency of use. This document becomes your Deskpro rebuild checklist and also gives you a chance to prune automations that are no longer serving a purpose.
Historical reporting: If SLA compliance history, CSAT scores, or time-to-resolution metrics matter for compliance or business review, export them from Help Scout's Reports section before cutover. Deskpro cannot retroactively calculate these metrics for migrated tickets.
Migration Timeline and Planning
Realistic Timeline Estimates
| Dataset Size | Estimated Duration | Phase Breakdown |
|---|---|---|
| Under 10K conversations | 1–2 weeks | 2–3 days extraction, 2–3 days transformation, 3–5 days loading + validation |
| 10K–50K conversations | 2–3 weeks | 3–5 days extraction, 3–4 days transformation, 1 week loading + validation |
| 50K+ conversations | 3–5 weeks | Add time for rate limit pacing, attachment volume, checkpoint/resume implementation, and extended QA |
Knowledge base migration adds 2–4 days depending on article count and embedded media volume. Attachments are the primary driver of extraction time — a 10K conversation dataset with 3 attachments per conversation takes significantly longer than a 50K conversation dataset with no attachments.
Pre-Migration Checklist
- Audit your Help Scout data. Count conversations by status, customers, tags, custom fields, and Docs articles. Count attachment-bearing conversations separately — this drives the bulk of extraction time.
- Set up Deskpro departments. Mirror your Help Scout mailbox structure — or redesign it now. Deskpro supports nested departments, so this is your opportunity to add hierarchy that Help Scout couldn't express.
- Pre-create custom fields in Deskpro. Match field types (text, dropdown, date, checkbox) exactly. Integer field IDs from the Admin UI are required for API writes. Type mismatches produce
400errors on every affected ticket. - Create agents and map emails. Build an email → Deskpro Agent ID lookup table. Agents must exist before tickets can be assigned to them. Create a "Legacy Agent" placeholder for departed staff.
- Disable all outbound email in Deskpro before importing.
- Set up a delta sync window. Agree on a freeze time for Help Scout — the point at which agents stop making changes. Your delta script will use this timestamp as the
modifiedSinceparameter. - Test the pipeline on a single mailbox. Migrate one Help Scout mailbox completely before starting the full run. Verify entity counts, timestamps, attachments, and inline images in that subset.
Cutover Strategy
A zero-downtime cutover requires a delta migration approach:
- Initial Sync: Migrate all historical data while your team continues working in Help Scout. Depending on volume, this runs for days. Use checkpoint/resume; do not attempt this as a single-run script.
- Delta Sync: Schedule a cutover window (typically over a weekend). Pause incoming mail to Help Scout, run a final delta script using
GET /v2/conversations?modifiedSince={freeze_timestamp}to catch everything created or updated since the initial sync completed, and load those tickets into Deskpro. - DNS / Email Routing Cutover: Update your email forwarding rules and MX records (or Help Scout → Deskpro inbox forwarding) to route mail to Deskpro.
- Go Live: Agents log into Deskpro. All historical context is present; new mail routes correctly.
The delta sync is what separates a clean cutover from an ugly one. Without it, you either lose recent tickets or force agents to work in both systems simultaneously while you reconcile the gap.
Validation and Post-Migration QA
Run these checks after loading before re-enabling email notifications:
- Conversation count match. Total tickets in Deskpro should equal total conversations exported from Help Scout (minus spam, if excluded). A discrepancy means missed conversations or redirect-following failures on merged conversations.
- Thread count per ticket. Spot-check 50+ tickets: does each have the correct number of messages and notes? Pay special attention to tickets with forwarded threads.
- Attachment integrity. Download a random sample of migrated attachments; compare file size and SHA-256 checksum against the originals downloaded during extraction.
- Customer-to-ticket linkage. Verify tickets are associated with the correct Person record — not a duplicate created by a casing difference in the email address.
- Custom field values. Spot-check dropdown selections, date values, and text fields against source data. Type mismatches during import silently zero out field values rather than erroring in some Deskpro versions.
- Timestamp accuracy. Confirm
date_createdon migrated tickets matches the original Help Scout conversation creation date — not the import run date. - Agent assignment. Verify tickets show the original assigned agent, not the migration superuser account.
- Inline image rendering. Open historical tickets with known embedded images and confirm images render from Deskpro blob URLs, not broken Help Scout CDN references.
Re-enable outbound email only after all checks pass.
Common Edge Cases and Failure Modes
Merged conversations. API returns 301 Moved Permanently for source conversations. Scripts that don't follow redirects receive 404 and silently drop the conversation. Always set allow_redirects=True (or equivalent) and log the redirect chain for audit purposes.
Thread limit. Help Scout enforces a maximum of 100 threads per conversation. Verify thread counts match post-import for any conversations that approached this limit during extraction.
Inline images in thread bodies. Thread HTML contains authenticated <img src="https://secure.helpscout.net/..."> tags. These return 403 post-migration. Download, re-upload to Deskpro blobs, and rewrite src attributes. HTML parsing required — regex is not sufficient for this.
Duplicate customers. Help Scout allows multiple Customer records with different email addresses for the same person. Deskpro de-duplicates People by primary email. Run a de-duplication pass before import, or you'll create orphaned Person records that agents cannot easily merge.
Company-to-Organization mismatch. Help Scout Companies are loosely associated with Customers via a reference field. Deskpro Organizations are first-class entities requiring explicit People membership. Create each Organization first, then explicitly set the organization_id on each Person record during import. Implicit association does not transfer.
Clock skew on delta sync. Help Scout's modifiedSince filter compares against server time. Use a 60-second buffer on your cutover timestamp (i.e., set modifiedSince to 60 seconds before your actual freeze time) to avoid edge cases where tickets modified in the final seconds of the initial sync window are missed.
Docs API authentication. The Docs API uses HTTP Basic authentication (API key as username, literal string "X" as password), not the OAuth bearer tokens used by the Mailbox API. Attempting OAuth on Docs API endpoints returns 401.
DIY vs. Managed Migration: When to Get Help
DIY is viable when:
- Fewer than 10K conversations
- No custom fields or minimal custom field usage
- No knowledge base to migrate
- An engineer available to commit 1–2 weeks full-time
- Comfortable implementing OAuth token refresh, HAL-style pagination, checkpoint/resume, and
301redirect following
Managed migration makes sense when:
- Dataset exceeds 20K conversations
- Complex custom field schemas, multiple mailboxes, or a large Docs site
- Agents cannot afford extended downtime or a botched cutover requiring re-migration
- You need a tested delta sync implementation
- You're encountering rate limits that extend extraction beyond your cutover window
The failure modes that burn DIY teams on first attempts are consistently: merged conversations dropping silently due to 301 handling, OAuth tokens expiring mid-extraction without checkpoint/resume, and inline images left as broken CDN references because the HTML rewriting step was skipped.
Making the Decision
A Help Scout to Deskpro migration is fundamentally a data model translation problem. The biggest risks are data loss from using the conversation preview field instead of calling the threads endpoint, notification floods from skipping the email-disable step, and broken inline images from unresolved Help Scout CDN URLs.
Treat it as an engineering project. Map your data model before writing any code. Implement checkpoint/resume before running against production data. Respect the API rate limits. Disable outbound email before the load phase. And verify the output against source counts before you flip the switch.
Frequently Asked Questions
- Does Deskpro have a built-in Help Scout importer?
- No. Deskpro offers a built-in Zendesk importer but has no equivalent for Help Scout. You must build a custom pipeline using the Help Scout Mailbox API v2 for extraction and the Deskpro REST API v2 for loading.
- Can I use Help Scout's CSV export to migrate to Deskpro?
- No. Help Scout's native CSV export does not include message bodies, thread replies, internal notes, or attachments. It only covers reporting-level metadata. You must use the Mailbox API v2 to extract full conversation data.
- How long does a Help Scout to Deskpro migration take?
- For under 10K conversations, expect 1–2 weeks. For 10K–50K conversations, plan for 2–3 weeks. Datasets over 50K conversations with attachments and knowledge base articles can take 3–5 weeks, largely driven by API rate limits and QA time.
- How do Help Scout statuses map to Deskpro statuses?
- Help Scout's 'active' maps to Deskpro's 'Awaiting Agent', 'pending' maps to 'Awaiting User', and 'closed' maps to 'Resolved'. Deskpro does not support arbitrary custom statuses — it uses a fixed three-state model. Spam conversations should be skipped.
- What Help Scout data cannot be migrated to Deskpro automatically?
- Workflows, Saved Replies, Beacon configurations, per-conversation satisfaction ratings, and report dashboards cannot be exported via API. These must be manually recreated in Deskpro as Triggers, Snippets, Messenger config, and DPQL reports.


