Skip to content

Enchant to Missive Migration: A Technical Guide

Technical guide to migrating from Enchant to Missive. Covers API constraints, data model mapping, migration approaches, edge cases, and validation.

Raaj Raaj · · 22 min read
Enchant to Missive Migration: A Technical Guide
TALK TO AN ENGINEER

Planning a migration?

Get a free 30-min call with our engineers. We'll review your setup and map out a custom migration plan — no obligation.

Schedule a free call
  • 1,500+ migrations completed
  • Zero downtime guaranteed
  • Transparent, fixed pricing
  • Project success responsibility
  • Post-migration support included

Migrating from Enchant to Missive means moving from a traditional ticket-based helpdesk to a conversation-centric shared inbox built around email collaboration. The two platforms have fundamentally different data models: Enchant organizes work around Tickets with discrete states and Inboxes, while Missive organizes work around Conversations tied to Team Inboxes and Labels. This structural difference shapes every decision in the migration — from data extraction to workflow rebuilds on the other side.

There is no clean one-click migration path. Missive has no native bulk import tool for conversations. For most teams, the safest approach combines API-based extraction of Enchant-specific data (internal notes, labels, assignments, custom fields) with provider-layer email migration if the original mail still lives in Gmail, Microsoft 365, or IMAP. Since Enchant ingests email via forwarding, the raw messages often still exist in the underlying mail account — and Missive can connect directly to those accounts to pull native email history.

This guide covers the full technical path: API constraints on both sides, object mapping, migration approaches, edge cases, and the validation process that ensures nothing gets lost.

Last verified against Enchant API v1 and Missive API v1: June 2025. API details change — always cross-reference the Enchant API documentation and Missive API documentation before implementing.

Why Teams Move from Enchant to Missive

Enchant is a solid shared inbox for small and mid-size support teams, covering email, chat, phone, and social channels. But teams migrate for specific structural reasons:

  • Collaboration model: Missive's internal chat lives inside each conversation, enabling real-time collaborative drafting and @mentions. Enchant's collaboration is limited to internal notes on tickets — no live co-editing.
  • Unified personal + shared inboxes: Missive combines personal email and team inboxes in one interface. Enchant agents work exclusively in the helpdesk — personal email stays separate.
  • Rules engine: Missive's rules auto-route, label, assign, and trigger webhooks based on content, sender, domain, or keywords. Enchant has triggers and macros, but they're narrower in scope and lack webhook support.
  • Multi-channel consolidation: Missive natively supports email, SMS, WhatsApp, Instagram, and custom channels as first-class conversation types. Enchant supports similar channels but with a more traditional ticket model where each channel creates a discrete ticket.
  • API and integration depth: Missive's API supports posts, drafts, contacts, conversations, and UI/iFrame integrations for embedding external app data in the sidebar. Enchant's API is more limited — focused on tickets, messages, customers, and attachments with no iFrame or sidebar integration support.

The migration is not a drop-in replacement. The two platforms think about support differently, and the migration requires thoughtful mapping — not a data dump.

Core Data Model Differences

Before writing any migration code, understand what maps and what doesn't:

Enchant Concept Missive Equivalent Notes
Ticket Conversation 1:1 mapping, but Missive conversations are broader (can include chat, posts)
Message (reply/note) Message / Comment Replies map to messages; internal notes map to comments within conversations
Inbox Team Inbox Enchant Inboxes map to Missive Team Inboxes
User (agent) User / Team Member Users in Enchant map to Missive organization members
Customer Contact Enchant customers map to Missive contacts
Contact (email/phone/twitter) Contact Info (email/phone) Missive contacts use an infos array for multiple identifiers
Label Label Direct mapping — both use labels for categorization
Attachment Attachment Must be downloaded and re-uploaded per message
Ticket Custom Fields No native conversation equivalent Missive supports custom fields on Contacts and Organizations only
Customer Satisfaction (CSAT) No native equivalent Must be stored as metadata in conversation posts or notes
Knowledge Base articles No native equivalent Missive is not a KB platform; migrate KB content elsewhere
Canned Responses Response Templates Must be manually recreated
Triggers / Macros Rules Must be manually rebuilt; Missive Rules are more powerful but structurally different
Warning

Missive has no native Knowledge Base. If you use Enchant's KB, plan a separate migration path — to a tool like Notion, GitBook, Help Scout Docs, or a dedicated KB platform like Document360.

Migration Approaches

There are several viable ways to move data from Enchant to Missive. The right approach depends on your data volume, engineering capacity, and tolerance for fidelity trade-offs.

1. CSV Export + Provider-Layer Email Migration

How it works: Export contact data from Enchant as CSV and import into Missive. For email history, migrate at the provider layer — if your original mail still lives in Gmail, Microsoft 365, or IMAP, connect those accounts to Missive and import the needed history window.

When to use: Small, email-centric teams (<500 tickets) who can accept losing Enchant-specific metadata (internal notes, labels, assignments, custom fields).

Pros:

  • Zero engineering effort
  • Fast for contact-only migrations
  • Provider-layer migration preserves native email threading

Cons:

  • Enchant's CSV export is limited to report data — not full ticket/message bodies
  • No conversation history preservation for Enchant-only data (notes, labels, states)
  • No attachment migration
  • No relationship preservation (customer ↔ ticket links)

Complexity: Low Scalability: Small datasets only

2. API-Based Migration (Enchant REST API → Missive REST API)

How it works: Build a custom script that extracts data from the Enchant API, transforms it to match Missive's schema, and loads it via the Missive API. This is the most reliable method for preserving conversation history, relationships, and attachments.

When to use: Any team that needs full-fidelity migration with conversation history, internal notes, and metadata intact.

Pros:

  • Full control over data mapping
  • Preserves conversation threading, customer relationships, and attachments
  • Can handle custom transformations (label remapping, state conversion)

Cons:

  • Requires engineering effort (Python, Node.js, or similar)
  • Constrained by API rate limits on both sides
  • Must handle pagination, retries, and error logging

Complexity: High Scalability: Handles enterprise volumes with proper batching

3. Middleware Platforms (Zapier, Make)

How it works: Use Zapier or Make to connect Enchant webhooks to Missive actions. Missive has a native Zapier integration.

When to use: Ongoing sync of new conversations or contacts during a transition period — not suitable for historical data migration.

Pros:

  • No code required
  • Good for forward-looking sync after migration

Cons:

  • Cannot backfill historical data
  • Limited transformation logic
  • Prohibitively expensive for bulk data — Zapier's Professional plan ($49/mo) includes 2,000 tasks; at 3–5 tasks per ticket, a 10K ticket migration would consume 30K–50K tasks, costing $300+ in overage
  • High failure rate on large payloads or attachments
  • No batch processing

Complexity: Medium Scalability: Not suitable for bulk migration

4. Custom ETL Pipeline

How it works: Deploy a dedicated Extract, Transform, Load pipeline using tools like Airbyte, custom Python/Node.js, or cloud infrastructure (AWS Lambda, GCP Cloud Functions). Land Enchant data in staging storage (S3/GCS or a PostgreSQL staging database), transform and deduplicate outside the destination, then load Missive with idempotent jobs and retry queues.

When to use: Enterprise environments with massive datasets (100K+ tickets) requiring complex transformations, data warehousing, or audit requirements.

Pros:

  • Highly resilient and auditable
  • Supports replay and reconciliation
  • Best control and QA capabilities

Cons:

  • Significant infrastructure and engineering overhead
  • Risk of over-engineering for a one-time event

Complexity: Very High Scalability: Enterprise-grade

5. Managed Migration Service

How it works: Engage a team that specializes in helpdesk migrations to handle the full ETL pipeline, including edge cases, validation, and rollback planning.

When to use: When you can't afford data loss, need to move fast, or lack internal engineering bandwidth.

Pros:

  • Fastest time-to-completion
  • Handles edge cases (attachments, threading, deduplication)
  • Includes validation and rollback planning
  • No engineering team distraction

Cons:

  • External cost
  • Requires sharing API credentials with the provider

Complexity: Low (for you) Scalability: Enterprise-grade

Approach Comparison

Factor CSV + Provider API-Based Middleware Custom ETL Managed Service
Conversation history Partial (email only)
Attachments
Internal notes
Customer relationships Partial
Engineering effort None High Low Very High None
Data fidelity Low High Low High High
Best for <500 contacts Dev teams Post-migration sync Enterprise Everyone else

Recommendations by Scenario

  • Small team, email-only: Provider-layer email migration plus contact CSV or API import.
  • Small team, no dev resources: Managed migration service, or accept a fresh start.
  • Mid-size with dev team: API-based script with careful rate limit handling.
  • Enterprise: Custom ETL pipeline or managed service, especially for multi-channel history.
  • One-time migration: Managed service — avoid building infrastructure you'll use once.
  • Ongoing sync needed: Middleware or webhook-driven delta sync for new data only.

Pre-Migration Planning

A migration succeeds or fails in the planning phase. Audit both the helpdesk layer and the mail-provider layer before writing any extraction logic — Enchant email channels are forwarding-based, and Missive ingests history from connected accounts.

Data Audit Checklist

  • Tickets: Total count by state (open, hold, closed, archived). Decide how many years of history to migrate.
  • Customers: Total count. Check for duplicates (multiple customer records with the same email).
  • Users/Agents: Active vs. inactive. Inactive Enchant agents should map to a "Legacy User" in Missive to preserve history without paying for unnecessary seats.
  • Labels: Full list with usage counts. Consolidate or retire unused labels before migration.
  • Inboxes: Map each Enchant Inbox to a Missive Team Inbox.
  • Attachments: Estimate total size. Large attachment volumes significantly slow migration. Note: Enchant attachment URLs may become inaccessible after account cancellation — download all attachments before deprecating your Enchant account.
  • Custom Fields: Document all ticket-level custom fields. Decide whether to map them to Contact custom fields or append as internal comments (Missive has no conversation-level custom fields).
  • Knowledge Base: Decide the target platform — Missive has no KB.
  • Canned Responses / Macros / Triggers: Document everything — these must be manually rebuilt in Missive as Rules and Response Templates.

GDPR and Data Privacy Considerations

If you serve EU customers or process EU personal data, the migration involves data processing considerations:

  • Data processing agreement (DPA): Ensure you have DPAs in place with both Enchant and Missive. Missive's DPA is available on request.
  • Data in transit: API calls to both platforms use TLS encryption. If using a managed migration service, verify they also encrypt data at rest in any staging environment.
  • Data minimization: Use the migration as an opportunity to purge data you no longer need. Don't migrate 7 years of closed tickets if your retention policy requires only 2 years.
  • Third-party processors: If using a managed migration service, they become a sub-processor under GDPR. Document this in your records of processing activities.

Define Migration Scope

  • Full history or rolling window? Migrating 7+ years of tickets is often unnecessary. Consider a 2–3 year window for operational data and a static JSON export for the rest.
  • All inboxes or selective? If some Enchant Inboxes are deprecated, skip them.
  • Spam and trash? Almost never worth migrating.

Migration Strategy

  • Big bang: Migrate everything in one go. Best for small-to-mid datasets (<50K tickets). Requires a maintenance window.
  • Phased: Migrate one Inbox at a time. Reduces risk but extends the transition period.
  • Phased big bang (recommended): Run a complete historical migration of all closed tickets. Run a delta migration of tickets updated since the historical pull. Cut over MX records and email forwarding to Missive. Run a final delta migration to catch any tickets created during the DNS propagation window (typically 24–48 hours for MX record changes).
Tip

Run a pilot first. Migrate a single Inbox (100–500 tickets) to validate your mapping, identify edge cases, and estimate total migration time before committing to the full run.

Migration Architecture

Enchant API Constraints

The Enchant REST API is the primary extraction path. Key constraints:

  • Base URL: https://{site}.enchant.com/api/v1
  • Authentication: Bearer token (generated from the API app in Enchant settings)
  • Rate limit: 100 credits per minute, account-wide. Each request costs 1 credit; embedding and counting cost extra.
  • Burst limit: 6 requests per second
  • Pagination: 0–100 results per page, default 10. For more than 10,000 records, you must use since_created_at instead of page-based pagination — Enchant's page-based pagination caps at 10,000 records. Exceeding this cap returns an empty result set with no explicit error code.
  • Key endpoints: Tickets, Messages (embedded on tickets), Customers, Contacts, Users, Attachments
  • Common error responses: 401 Unauthorized (invalid or expired token), 429 Too Many Requests (rate limit exceeded — includes Retry-After header), 404 Not Found (deleted or merged ticket)

Missive API Constraints

The Missive REST API is the loading target. Key constraints:

  • Base URL: https://public.missiveapp.com/v1
  • Authentication: Personal Bearer token (requires Productive plan at $18/user/month or higher)
  • Rate limit: 5 concurrent requests, 300 requests per minute, 900 requests per 15 minutes
  • Pagination: Conversations limited to max 50 per page, using until cursor based on last_activity_at
  • Conversation message limit: 400 messages per conversation. Attempting to add a 401st message returns a 422 Unprocessable Entity error.
  • Key endpoints: Contacts (create/update/list), Drafts (create with send), Posts (inject data into conversations), Messages, Conversations (list/get)
  • Contacts require a contact_book ID when creating records.
  • Common error responses: 401 Unauthorized (invalid token), 403 Forbidden (token user lacks access to the target inbox/org), 422 Unprocessable Entity (validation error — malformed payload or limit exceeded), 429 Too Many Requests (rate limit hit — Retry-After header provided)
Warning

Missive API tokens are personal. There is no organization-level API token. The token inherits the user's access scope — make sure your migration token belongs to an admin with full access to all Team Inboxes and the organization's Contact Book.

Info

Conversation update endpoint: Historically, Missive had no PATCH /v1/conversations/:id. State changes required Posts, Messages, or Drafts endpoints with action parameters. Missive's 11.30.1 changelog indicates a newer endpoint now exists for closing, reopening, assigning, labeling, and moving conversations. Verify the current API reference before coding your loader.

Data Flow

┌─────────────┐     ┌──────────────┐     ┌─────────────┐
│  Enchant API │────▶│  Transform   │────▶│ Missive API │
│  (Extract)   │     │  (Map/Clean) │     │  (Load)     │
└─────────────┘     └──────────────┘     └─────────────┘
       │                    │                    │
    Tickets              Remap IDs           Conversations
    Messages             Clean HTML           Messages
    Customers            Merge dupes          Contacts
    Attachments          Resize/encode        Attachments
    Labels               Map names            Labels

Step-by-Step Migration Process

Step 1: Extract Data from Enchant

Order matters. Extract in dependency order:

  1. UsersGET /api/v1/users
  2. Labels — Document from Enchant UI (no dedicated API endpoint for full label management)
  3. CustomersGET /api/v1/customers?per_page=100&sort=created_at&since_created_at={timestamp}
  4. Tickets with embedded messagesGET /api/v1/tickets?per_page=100&sort=created_at&since_created_at={timestamp}&embed=messages,customer,labels
  5. AttachmentsGET /api/v1/attachments/{id} (per attachment referenced in messages)

For large datasets (10K+ tickets), use since_created_at-based iteration. Track the last-seen created_at timestamp and use it as the cursor for the next batch.

curl -H 'Authorization: Bearer ENCHANT_TOKEN' \
  'https://SUBDOMAIN.enchant.com/api/v1/tickets?per_page=100&sort=created_at&since_created_at=2023-01-01T00:00:00Z'

Step 2: Transform Data

Customer → Contact mapping:

def transform_customer_to_contact(enchant_customer):
    contact = {
        "first_name": enchant_customer.get("first_name", ""),
        "last_name": enchant_customer.get("last_name", ""),
        "infos": []
    }
    for c in enchant_customer.get("contacts", []):
        if c["type"] == "email":
            contact["infos"].append({
                "type": "email", "label": "Work", "value": c["value"]
            })
        elif c["type"] == "phone":
            contact["infos"].append({
                "type": "phone", "label": "Work", "value": c["value"]
            })
    return contact

Ticket state → Conversation state mapping:

Enchant State Missive Action
open Leave conversation open (default)
hold Apply a "Hold" label (no native equivalent in Missive)
closed Close conversation via post action
snoozed Snooze conversation (if timestamp available; requires snooze_until parameter)
archived Archive conversation

Label remapping: Create all Enchant labels in Missive first, then build an enchant_label_id → missive_label_id lookup map. Missive has two label types: email labels (sync with the mail server) and organization labels (do not sync). For migration purposes, organization labels are typically the right choice — they don't pollute the underlying mailbox with label changes.

ID mapping: Store mappings of Enchant_User_ID → Missive_User_ID, Enchant_Customer_ID → Missive_Contact_ID, and Enchant_Label_ID → Missive_Label_ID in a local database or key-value store (SQLite works well for one-time migrations). You'll need these for every ticket and message you migrate.

Step 3: Prepare Missive

Before loading any data, create the target structures:

  • Create Team Inboxes matching your Enchant Inboxes
  • Create all Labels (organization labels for categorization)
  • Set up User accounts for active agents
  • Create a "Legacy User" account for tickets assigned to inactive Enchant agents
  • Generate an API token from a Productive-plan admin account (Settings → API → Generate Token)
  • Note the Contact Book ID required for contact creation (retrieve via GET /v1/contact_books)

Step 4: Load Contacts

Create contacts first. Every subsequent conversation needs a linked contact.

import requests
import time
import logging
 
MISSIVE_API = "https://public.missiveapp.com/v1"
HEADERS = {
    "Authorization": "Bearer {your_missive_token}",
    "Content-Type": "application/json"
}
 
logger = logging.getLogger("migration")
 
def create_missive_contact(contact_data, contact_book_id, max_retries=3):
    payload = {
        "contacts": [{
            "contact_book_id": contact_book_id,
            "first_name": contact_data["first_name"],
            "last_name": contact_data["last_name"],
            "infos": contact_data["infos"]
        }]
    }
    for attempt in range(max_retries):
        try:
            resp = requests.post(
                f"{MISSIVE_API}/contacts",
                json=payload,
                headers=HEADERS,
                timeout=30
            )
            if resp.status_code == 429:
                retry_after = int(resp.headers.get("Retry-After", 5))
                logger.warning(f"Rate limited. Retrying after {retry_after}s (attempt {attempt+1})")
                time.sleep(retry_after)
                continue
            elif resp.status_code == 401:
                raise Exception("Authentication failed — check API token")
            elif resp.status_code == 403:
                raise Exception("Permission denied — token user lacks access")
            elif resp.status_code >= 500:
                logger.error(f"Server error {resp.status_code}. Retrying (attempt {attempt+1})")
                time.sleep(2 ** attempt)
                continue
            resp.raise_for_status()
            time.sleep(0.5)
            return resp.json()
        except requests.exceptions.Timeout:
            logger.error(f"Timeout on contact creation (attempt {attempt+1})")
            time.sleep(2 ** attempt)
    raise Exception(f"Failed to create contact after {max_retries} attempts")

Step 5: Load Conversations

For each Enchant ticket, recreate the conversation in Missive. The Posts endpoint lets you inject historical data into conversations:

def create_conversation_post(ticket, messages, label_ids, max_retries=3):
    body_html = ""
    for msg in messages:
        sender = msg.get("from_name", "Agent")
        timestamp = msg.get("created_at", "")
        content = msg.get("body", "")
        msg_type = "Note" if msg.get("type") == "note" else "Reply"
        body_html += f"<p><strong>{sender}</strong> ({timestamp}) [{msg_type}]:</p>{content}<hr>"
 
    payload = {
        "posts": {
            "conversation_subject": ticket["subject"],
            "organization": "{your_org_id}",
            "add_shared_labels": label_ids,
            "username": "Migration Bot",
            "text": body_html,
        }
    }
    for attempt in range(max_retries):
        try:
            resp = requests.post(
                f"{MISSIVE_API}/posts",
                json=payload,
                headers=HEADERS,
                timeout=30
            )
            if resp.status_code == 429:
                retry_after = int(resp.headers.get("Retry-After", 5))
                time.sleep(retry_after)
                continue
            elif resp.status_code == 422:
                logger.error(f"Validation error for ticket {ticket['id']}: {resp.text}")
                return None  # Log and skip — don't retry validation errors
            elif resp.status_code >= 500:
                time.sleep(2 ** attempt)
                continue
            resp.raise_for_status()
            time.sleep(0.5)
            return resp.json()
        except requests.exceptions.Timeout:
            time.sleep(2 ** attempt)
    raise Exception(f"Failed to create conversation for ticket {ticket['id']}")

Link conversations to the correct Team Inbox using the team parameter when creating posts or drafts. Associate conversations with contacts by matching email addresses in the from/to fields.

Info

Rate limit math for Missive: At 300 requests per minute (the documented limit), migrating 10,000 conversations with 3 API calls each (contact lookup + post + state change) would take roughly 100 minutes in theory. In practice, factor in retries, error handling, attachment uploads, and conservative pacing — plan for 8–10 hours for a dataset that size. For 50K+ tickets, plan for multi-day migration windows.

Step 6: Handle Attachments

Enchant stores attachments as secure URLs. You cannot pass the Enchant URL to Missive — those URLs will almost certainly break once you cancel your Enchant account (Enchant has not publicly documented a URL expiry policy, so assume they become inaccessible immediately upon account closure). Your script must:

  1. Download the file from Enchant into temporary memory or local disk
  2. Re-upload it to Missive's attachment endpoint
  3. Attach it to the correct Missive message

Large attachment volumes significantly slow migration. Budget extra time accordingly — a dataset with 5,000 attachments averaging 2MB each adds roughly 10GB of download + upload I/O.

Step 7: Validate

See the Validation and Testing section below.

Edge Cases and Challenges

Duplicate Customer Records

Enchant can have multiple customer records with the same email (created via different channels). Deduplicate before loading into Missive by merging on email address. Decide which record's name and metadata wins — typically the most recently updated record.

HTML Message Bodies

Enchant messages can contain raw HTML. Missive posts accept HTML, but formatting may render differently. Test a sample batch and strip any Enchant-specific CSS or inline styles that break rendering. Common issues: <style> blocks, absolute-positioned elements, and width: 100% on nested tables.

Multi-Channel Tickets

Enchant tickets can be of type email, chat, sms, whatsapp, fb_messenger, instagram_dm, phone, and call. Missive supports email, SMS, WhatsApp, and Instagram natively. Chat transcripts and phone call records will need to be imported as posts (text records) rather than native conversation types. Prefix these with a clear marker (e.g., [Imported Chat Transcript]) so agents can distinguish them from native conversations.

CSAT Ratings

Enchant tracks customer satisfaction per ticket. Missive has no native CSAT system. Export CSAT data separately for reporting (a CSV or database export), or inject it as a note/post on the migrated conversation for agent visibility.

Merged Tickets

Enchant merges copy replies and notes into the destination ticket and archives the source. During extraction, track which tickets were merged (check for archived tickets with merge metadata) so you don't create duplicate conversations in Missive.

Private Note Fidelity

Enchant internal notes should map to Missive comments. However, the public Missive API documentation for bulk comment creation is limited. If historical private notes must land as native comments (not just embedded in post bodies), prove that path works in a pilot before committing. The fallback is to embed notes within the post body, visually distinguished with a [Internal Note] prefix and styling.

Custom Fields

Enchant allows custom fields on Tickets. Missive does not support custom fields on Conversations — only on Contacts and Organizations. Your options:

  1. Map Enchant ticket custom fields to Missive Contact custom fields (risky if a contact has multiple tickets with different field values — the last write wins and you lose historical variance)
  2. Append custom field data as an internal comment on the Missive conversation during import (preserves per-ticket data but loses structured queryability)

Missing or Deleted Users

If an Enchant ticket is assigned to an agent who was deleted, the API may return a null or invalid User ID. Your script must catch these exceptions and route them to a fallback "Legacy User" in Missive. Log every instance for audit purposes.

Pagination Ceiling

Enchant's page-based pagination caps at 10,000 records. Beyond that, the API returns an empty result set without an explicit error. You must use since_created_at to iterate chronologically. Your script needs to track the last-seen created_at timestamp as a cursor for the next batch.

400-Message Conversation Limit

Missive enforces a 400-message limit per conversation. Tickets with extremely long threads (common in enterprise support with ongoing customer relationships) will hit a 422 Unprocessable Entity when attempting to add the 401st message. Options:

  1. Consolidate the entire thread into a single post body (loses individual message metadata)
  2. Split into multiple linked conversations with a cross-reference note
  3. Truncate to the most recent 400 messages and archive the rest as a JSON export

Limitations and Constraints

Be realistic about structural compromises in this migration:

  • No 1:1 ticket state mapping: Enchant's hold state has no direct Missive equivalent. Use labels as a workaround.
  • No Knowledge Base in Missive: Enchant KB articles need a separate destination.
  • No native CSAT in Missive: Satisfaction data must be stored externally or as metadata.
  • No ticket numbers in Missive: If your team relies on Enchant ticket numbers for reference, store the original ID in a label, comment, or mapping table.
  • No conversation-level custom fields: Missive only supports custom fields on Contacts and Organizations.
  • Personal API tokens only: Missive doesn't offer organization-level tokens. All API operations run under a single user's permissions.
  • Tight rate limits for bulk operations: 900 requests per 15 minutes means large migrations need careful pacing or multi-day windows.
  • 400-message conversation limit: Missive enforces a 400-message limit per conversation. Tickets with extremely long threads need special handling (see Edge Cases above).
  • SLA management: Enchant has native SLA rules with escalation timers. Missive handles SLAs differently, relying on Rules and internal timers. Rebuild SLA logic from scratch — there is no automated migration path.
  • Reporting: Missive's built-in reporting focuses on response times and workload distribution. If you rely on complex custom reports in Enchant (e.g., CSAT trends by label, resolution time by custom field), you will need to pipe Missive data to a BI tool like Metabase, Looker, or export via API.

Validation and Testing

Never execute a production migration without a validation phase.

Record Count Comparison

Object Enchant Count Missive Count Match?
Customers / Contacts ___ ___
Tickets / Conversations ___ ___
Messages ___ ___
Attachments ___ ___
Labels ___ ___

A variance of <0.5% is acceptable (typically caused by spam filters or deduplication). Anything above 1% requires investigation.

Field-Level Validation

For a random sample of 50–100 conversations across different years and inboxes:

  • Subject line matches
  • Message count per conversation matches
  • Message content (first 100 characters) matches
  • Correct label applied
  • Correct Team Inbox assignment
  • Attachment count matches
  • Contact linked correctly
  • Timestamps preserved (within 1-second tolerance for timezone handling)
  • Internal notes appear as comments (not customer-visible messages)

UAT Process

  1. Have 2–3 agents review their most recent 20 migrated conversations
  2. Verify customer history is accessible from the contact sidebar
  3. Confirm internal notes appear as comments, not customer-visible messages
  4. Test search — find a specific old conversation by keyword
  5. Verify that attachment downloads work correctly on migrated conversations

Rollback Planning

Missive doesn't have a "bulk delete" API. If validation fails:

  • For contacts: delete individually via API (rate-limited, plan accordingly)
  • For conversations: trash and permanently delete
  • Best approach: run the pilot migration into a separate Missive organization and only switch once validated
  • Keep a tag-based isolation strategy during testing — apply a "Migration-Test" label to all imported data so you can identify and wipe imported data if needed

Post-Migration Tasks

Rebuild Automations

Enchant triggers, macros, and canned responses do not transfer. In Missive:

  • Recreate routing logic as Rules (Settings → Rules)
  • Recreate canned responses as Response Templates
  • Set up assignment rules to replace Enchant's user-based auto-assignment

For more on migrating automations, see Your Help Desk Data Migration's Secret Saboteur: Automations, Macros, and Workflows.

Reconnect Integrations

Reconnect your CRM (Salesforce, HubSpot, etc.) using Missive's native integrations or sidebar/iFrame integrations. If Enchant surfaced external data in its sidebar, Missive offers similar capabilities through its integration framework (Settings → Integrations → Custom).

User Training

Missive's UX is significantly different from Enchant. Budget 1–2 hours per team for:

  • Team Inbox workflow orientation (understanding Inbox, Team Inbox, and All views)
  • Label and assignment conventions
  • Internal chat and @mentions (a new collaboration model for Enchant users)
  • Rules engine training for admins

Monitor for Inconsistencies

For the first 2–4 weeks post-migration:

  • Watch for contacts that didn't link properly (orphaned conversations)
  • Check for HTML rendering issues in migrated messages
  • Verify that email routing is working correctly on Missive Team Inboxes
  • Confirm that no conversations were dropped during the migration window
  • Keep Enchant accessible in read-only mode for 30–90 days so agents can cross-reference data if needed — do not cancel the account until all attachments are confirmed accessible in Missive

Best Practices

  1. Back up everything first. Export all Enchant data to JSON via the API before starting. Store it in a versioned location (S3, GCS). This is your ultimate failsafe — and your only copy of data once Enchant is cancelled.
  2. Run test migrations. At least 2 dry runs on a small subset (100–1,000 tickets) before going live. Use a Missive sandbox or separate organization.
  3. Validate incrementally. Don't wait until all tickets are migrated to check for errors. Validate after the first 1,000 records.
  4. Log everything. Every API call, every error, every ID mapping. Structure logs with source_id, stage, target_id, attempt, http_status, and error. You'll need them for debugging and audit trails.
  5. Don't migrate spam or trash. Dead weight.
  6. Enforce idempotency. If your script fails halfway through and you re-run it, it should not create duplicate records. Use stored ID mappings (keyed on Enchant ticket/customer ID) to skip already-migrated records.
  7. Don't mix backfill and delta-sync jobs. Run them in separate worker queues to avoid race conditions.
  8. Coordinate the cutover tightly. Stop new ticket creation in Enchant → run final delta migration → verify record counts → switch email routing (MX records, forwarding rules) to Missive. Keep the window as short as possible — aim for under 4 hours.

For a complete pre-migration checklist, see our Missive Migration Checklist. For post-migration validation, see our Post-Migration QA checklist.

Sample Data Mapping Table

Enchant Field Missive Field Type Transformation
ticket.id N/A (internal ref) string Store in mapping table; optionally in a label or comment
ticket.number N/A integer No equivalent; log for reference
ticket.subject conversation_subject string Direct copy
ticket.state Conversation state + label string Map hold → label; closed → close action; snoozed → snooze
ticket.type Conversation channel string Map where possible; fallback to post for chat/phone
ticket.inbox_id Team Inbox ID string Use pre-built lookup map
ticket.label_ids add_shared_labels array Remap via label ID lookup
ticket.user_id Assignee string Map via user lookup; fallback to Legacy User
ticket.created_at Post timestamp ISO 8601 Preserve original date
customer.first_name contact.first_name string Direct copy
customer.last_name contact.last_name string Direct copy
customer.contacts [].value contact.infos [].value string Map type: email → email, phone → phone
customer.summary contact.notes or custom field string Inject as contact note
message.body Post/message body HTML Clean and validate HTML; strip Enchant-specific styles
message.type Message or Comment string note → internal comment; reply → message
message.direction Sender context string in = customer; out = agent
attachment.name Attachment filename string Direct copy
attachment.data Attachment upload binary Download from Enchant, re-upload to Missive

When to Use a Managed Migration Service

Building a custom ETL pipeline for an Enchant-to-Missive migration is feasible for teams with engineering bandwidth. But it's rarely the best use of that bandwidth for a one-time event.

DIY becomes costly when:

  • Attachment-heavy datasets: Downloading, re-encoding, and re-uploading thousands of attachments is tedious and error-prone. A dataset with 10K+ attachments can take 2–3 days of I/O alone.
  • Multi-channel history: Tickets spanning email, chat, and phone create deduplication and format-conversion headaches.
  • Tight timelines: Rate limits on both APIs mean large migrations take days. Optimizing throughput requires experience with concurrent request management and backoff strategies.
  • No rollback plan: If something fails mid-migration, you need a team that has handled this before.
  • Compliance requirements: If internal notes or non-email channels are compliance-relevant, the stakes are too high for a first-time script.

The hidden cost of DIY isn't the script — it's the weeks of debugging edge cases, the weekend spent re-running failed batches, and the support tickets from agents who can't find their old conversations. For more on this trade-off, see In-House vs. Outsourced Data Migration.

At ClonePartner, we've completed 1,500+ helpdesk migrations. We handle Enchant's data model and Missive's conversation architecture natively — including attachment extraction, delta syncs, and zero-downtime cutovers. Your team keeps working in Enchant until the switch is flipped.

Frequently Asked Questions

Can I migrate conversation history from Enchant to Missive using CSV?
No. Enchant's CSV export covers report data only — not full ticket bodies or message threads. Missive's native CSV import only supports contacts. To migrate complete conversation history, internal notes, and attachments, you need to extract tickets via the Enchant REST API and recreate them as conversations in Missive using the Posts or Drafts endpoint.
What are the API rate limits for Enchant and Missive?
Enchant allows 100 API credits per minute (account-wide) with a burst limit of 6 requests per second. Missive allows 5 concurrent requests, 300 per minute, and 900 per 15 minutes. Both return HTTP 429 when limits are exceeded.
Does Missive support Knowledge Base articles like Enchant?
No. Missive is a shared inbox and collaboration platform with no native Knowledge Base feature. If you use Enchant's KB, migrate those articles to a separate tool like Notion, GitBook, or a dedicated KB platform.
How do Enchant custom fields map to Missive?
Missive does not support custom fields on conversations. You must either map Enchant ticket custom fields to Missive Contact custom fields (with the caveat that the last write wins if a contact has multiple tickets), or append the data as an internal comment on the Missive conversation during import.
How long does an Enchant to Missive migration take?
For small teams (<5,000 tickets), an API-based migration can be completed in 1–3 days including validation. Larger datasets (50K+ tickets) may take a week or more due to API rate limits. A managed migration service can typically complete the job in 2–5 business days.

More from our Blog

Missive Migration Checklist
Checklist/Missive

Missive Migration Checklist

Planning a move to Missive? Use this comprehensive Missive migration checklist to protect your data, map workflows accurately, and ensure a seamless go-live without downtime.

Tejas Mondeeri Tejas Mondeeri · · 11 min read
Post-Migration QA: 20 Tests to Run After Your Help Desk Data Migration
Help Desk

Post-Migration QA: 20 Tests to Run After Your Help Desk Data Migration

Ensure your help desk migration is a success with this comprehensive 20-point post-migration QA checklist. This expert guide details the 20 essential tests needed to validate your data integrity, system functionality, user-friendliness, and performance . Learn exactly how to check everything from ticket data, attachments, and knowledge base articles to critical workflows, automations, and integrations before you go live. This process is your final line of defense against lost tickets, broken workflows, and unhappy customers.

Raaj Raaj · · 8 min read