Importing tickets
Moving to Mantle Helpdesk from another support platform? You can import your existing tickets to preserve conversation history and keep everything in one place.
Import options
There are three ways to get your tickets into Mantle:
Intercom extension
If you're migrating from Intercom, use our dedicated extension to import your conversation history automatically. The extension handles contact matching, message threading, and preserves timestamps from your original conversations.
Help Scout extension
Migrating from Help Scout? Our Help Scout extension imports your tickets, conversations, and customer data with a few clicks.
Core API
For all other platforms—Zendesk, Freshdesk, custom systems, or anything else—use the Mantle Core API to import tickets programmatically. This gives you full control over the import process and works with any data source.
Importing via the API
The Core API lets you create tickets, add message history, and track status changes. Here's how to structure your import.
Authentication
All API requests require OAuth2 authentication with the following scopes:
read:tickets— for fetching ticket datawrite:tickets— for creating and updating tickets
See Integrating with Mantle for authentication setup.
Step 1: Create the ticket
Create a ticket with the basic metadata. The contact will be automatically created or matched by email.
POST /api/core/v1/tickets
{
"subject": "Payment processing issue",
"status": "closed",
"priority": "high",
"tags": ["billing", "imported"],
"contact": {
"email": "[email protected]",
"name": "Jane Customer"
},
"createdAt": "2024-01-10T09:00:00Z"
}
Required fields:
subject— The ticket subject line
Recommended fields:
contact— Object withemailand optionalname. If a contact with that email exists, it will be linked. Otherwise, a new contact is created.contactId— Alternatively, pass an existing contact ID directly
Optional fields:
| Field | Description |
|---|---|
status | One of: open, pending, resolved, closed. Defaults to open. |
priority | One of: low, normal, high, urgent. Defaults to normal. |
tags | Array of tag strings |
customerId | Link to a Mantle customer |
appId | Link to a specific app |
assignedToId | Assign to a team member |
createdAt | Original creation timestamp (ISO-8601) |
updatedAt | When the ticket was last updated (ISO-8601) |
lastMessageAt | When the last message was sent (ISO-8601) |
readOnly | Set to true to mark as managed externally |
managedBy | Name of external system (e.g., "zendesk") |
The response includes the created ticket with its id, which you'll need for adding messages.
Step 2: Import message history
Add the conversation history using the bulk messages endpoint. This replaces any existing messages on the ticket.
PUT /api/core/v1/tickets/{ticketId}/messages
[
{
"actorType": "customer",
"content": "I can't process payments in my store.",
"contentType": "text",
"occurredAt": "2024-01-10T09:15:00Z",
"contact": {
"email": "[email protected]"
}
},
{
"actorType": "agent",
"content": "Thanks for reaching out. I'm looking into this now.",
"contentType": "text",
"occurredAt": "2024-01-10T10:30:00Z",
"agentId": "your-agent-uuid"
},
{
"actorType": "customer",
"content": "Any update on this?",
"contentType": "text",
"occurredAt": "2024-01-11T14:00:00Z",
"contact": {
"email": "[email protected]"
}
},
{
"actorType": "agent",
"content": "Fixed! The payment gateway configuration was missing.",
"contentType": "text",
"occurredAt": "2024-01-12T15:30:00Z",
"agentId": "your-agent-uuid"
}
]
Message fields:
| Field | Description |
|---|---|
actorType | Required. One of: customer, agent, system |
content | Required. The message text |
contentType | One of: text, html, markdown. Defaults to text. |
occurredAt | Original timestamp (ISO-8601). Defaults to now. |
contact | Required if actorType is customer. Object with email. |
contactId | Alternative to contact object—pass existing contact ID |
agentId | Required if actorType is agent. The team member's ID. |
isInternal | Set to true for internal notes not visible to customer |
attachments | Array of attachment objects (see below) |
Attachment format:
{
"url": "https://example.com/file.pdf",
"name": "invoice.pdf",
"contentType": "application/pdf",
"sizeBytes": 102400
}
Step 3: Import status history (optional)
If you want to preserve the history of status changes, assignments, and other events, use the events endpoint:
PUT /api/core/v1/tickets/{ticketId}/events
[
{
"type": "status_changed",
"oldValue": { "status": "open" },
"newValue": { "status": "pending" },
"actorType": "agent",
"agentId": "your-agent-uuid",
"occurredAt": "2024-01-10T10:30:00Z"
},
{
"type": "status_changed",
"oldValue": { "status": "pending" },
"newValue": { "status": "resolved" },
"actorType": "agent",
"agentId": "your-agent-uuid",
"occurredAt": "2024-01-12T15:30:00Z"
}
]
Contact matching
When you include a contact object with an email, Mantle automatically:
Normalizes the email (trim whitespace, lowercase)
Searches for an existing contact with that email
Updates the contact if found, or creates a new one if not
This means you can import tickets multiple times without creating duplicate contacts—the same email always maps to the same contact.
Best practices
Preserve timestamps
Always include createdAt on tickets and occurredAt on messages. This keeps your historical data accurate and ensures tickets appear in the correct order.
Use tags for tracking
Add an "imported" tag or similar to easily identify which tickets came from your migration. This helps if you need to audit or clean up later.
Import in batches
For large imports, process tickets in batches of 50-100 to avoid rate limits and make it easier to resume if something fails.
Test with a small set first
Import 5-10 tickets first and verify they look correct before running the full migration. Check that:
Messages appear in the right order
Contacts are matched correctly
Timestamps are preserved
Attachments are accessible
Mark external tickets as read-only
If you're keeping the original system as the source of truth, set readOnly: true and managedBy: "your-system" on imported tickets. This prevents edits in Mantle and makes it clear the ticket is managed elsewhere.
API reference
For complete API documentation including all available fields and response formats, see the Core API reference.