Migrating ticket data into Zendesk is a common challenge for teams switching platforms, consolidating instances, or importing historical records. While Zendesk offers several import methods, the Ticket Import API is the only option that preserves historical timestamps and handles large datasets properly.
This guide walks you through the complete process of bulk importing tickets using the Zendesk API. You'll learn how to structure your data, handle edge cases, and avoid the pitfalls that can turn a weekend project into a multi-week headache.
What you'll need
Before you start, make sure you have the following in place:
- Zendesk admin access only administrators can use the import API
- API token password authentication alone won't work; you need a proper API token from your Zendesk admin settings
- Existing users requesters must already exist in Zendesk before you import their tickets
- JSON knowledge you'll be working with REST API requests and JSON payloads
- Scripting environment Python or Node.js will make batch processing much easier
If you're looking for a simpler way to handle support workflows without complex migrations, modern AI solutions like eesel AI can integrate directly with your existing setup.
Understanding the Zendesk API bulk import tickets endpoint
The Ticket Import API differs from the standard Tickets API in several important ways. Here's what you need to know.
Key endpoint differences
The import endpoint is POST /api/v2/imports/tickets (or /api/v2/imports/tickets/create_many for batches up to 100 tickets). Unlike the standard ticket creation API, the import endpoint:
- Preserves historical timestamps including
created_at,updated_at, andsolved_at - Supports the
archive_immediatelyparameter for closed tickets - Does not trigger business rules or automations on import
- Sends no notifications to CC'd users
- Allows you to set custom comment timestamps
Source: Zendesk Ticket Import API Documentation
Rate limits and batch sizes
Zendesk allows up to 100 tickets per bulk import request. For larger datasets, you'll need to implement batching logic in your script. Standard API rate limits apply (700 requests per minute for most plans), so plan your migration accordingly.
Authentication requirements
All import requests require Basic Authentication using your email address combined with an API token (not your password). The format is {email_address}/token:{api_token} encoded in Base64.
Step 1: Prepare your data
Data preparation is where most migrations succeed or fail. Take time to get this right.
Required and optional fields
At minimum, each ticket needs a requester_id and subject. Here's a complete example:
{
"ticket": {
"requester_id": 827,
"subject": "Help with account access",
"description": "Initial ticket description",
"assignee_id": 19,
"tags": ["migration", "account-issue"],
"created_at": "2023-06-25T10:15:18Z",
"comments": [
{
"author_id": 827,
"created_at": "2023-06-25T10:15:18Z",
"value": "I can't log into my account"
}
]
}
}
User prerequisites
The requester and any comment authors must already exist in Zendesk as active users. The API will reject tickets with suspended or non-existent requesters. Import your users first using either the bulk CSV import (up to 2,000 rows) or the Users API.
Handling attachments
Attachments require a two-step process:
- Upload files to Zendesk using the attachments endpoint to get upload tokens
- Include those tokens in your ticket import payload
For inline images (screenshots in comments), note that the API documentation doesn't fully cover these. Real-world migrations reveal that inline attachments have different handling than standard attachments.
Step 2: Structure your API request
With your data prepared, you can start building the actual API requests.
Basic request structure
Here's a Python example showing how to structure a basic import request:
import requests
import base64
email = 'your-email@example.com'
api_token = 'your_api_token_here'
auth_string = base64.b64encode(f"{email}/token:{api_token}".encode()).decode()
headers = {
'Content-Type': 'application/json',
'Authorization': f'Basic {auth_string}'
}
ticket_data = {
"ticket": {
"requester_id": 827,
"subject": "Help",
"description": "A description",
"created_at": "2023-06-25T10:15:18Z",
"comments": [
{
"author_id": 827,
"created_at": "2023-06-25T10:15:18Z",
"value": "This is a comment"
}
]
}
}
response = requests.post(
'https://your-subdomain.zendesk.com/api/v2/imports/tickets',
headers=headers,
json=ticket_data
)
Including historical comments
The comments array supports multiple entries with individual timestamps. This is crucial for preserving the full conversation history from your source system.
Custom fields and tags
Map your source system's custom fields to Zendesk custom fields using the custom_fields array with id and value pairs. Tags can be passed as a simple string array.
Step 3: Handle special cases
Real-world migrations always involve edge cases. Here's how to handle the most common ones.
Importing closed tickets
For tickets with closed status, use the archive_immediately query parameter:
POST /api/v2/imports/tickets?archive_immediately=true
This bypasses the normal ticket lifecycle and creates tickets directly in your archive. Zendesk recommends this approach when importing 750,000 or more historical tickets to avoid impacting the performance of your active ticket queue.
Managing large datasets
For large migrations, implement these practices:
- Process tickets in batches of 100 (the API maximum)
- Log each batch's results for error tracking
- Build retry logic for failed requests
- Consider running imports during off-peak hours
Dealing with suspended users
The API requires requesters to be active users. If your source data includes tickets from suspended or deleted users, you have two options:
- Reactivate the users before import
- Map deleted users to a placeholder "former employee" account
One migration team discovered this the hard way: "The API will balk if requesters and submitters are suspended. We had to reactivate ex-employees temporarily during the import process."
Source: Zendesk Community Migration Experience
Empty comment bodies
The API rejects comments with empty bodies, even though Zendesk's UI allows this (such as when someone emails an attachment without text). You'll need to add placeholder text like "(No comment text)" for these cases.
Step 4: Execute and validate
With your data prepared and edge cases handled, it's time to run the import.
Sending requests in batches
Loop through your ticket data in chunks of 100, sending each batch to the bulk import endpoint. Log the response from each batch, including any ticket IDs that were successfully created.
Error handling
Common HTTP status codes you'll encounter:
- 200 OK Ticket created successfully
- 422 Unprocessable Entity Validation error (check your JSON structure)
- 429 Too Many Requests Rate limit hit; implement exponential backoff
- 401 Unauthorized Authentication issue; verify your API token
Verification strategies
After import, verify success by:
- Checking ticket counts match your source data
- Sampling tickets to verify timestamps and comments imported correctly
- Confirming attachments are accessible
- Testing that tags and custom fields appear correctly
Common pitfalls and how to avoid them
Learning from others' mistakes can save you significant time. Here are the biggest issues migration teams encounter.
Requesters must be active
As mentioned, suspended users cause import failures. Reactivate them first or use placeholder accounts.
Import order matters
You must import in this sequence:
- Organizations (if using)
- Users
- Tickets
Tickets reference users and organizations by ID, so those records must exist first.
Metrics and SLAs won't calculate
Zendesk metrics and SLAs are not calculated for imported tickets. If you need reporting on historical data, consider adding a tag like "imported" to exclude these tickets from current metrics.
No ticket ID reservation
You cannot preserve ticket ID relationships from your source system. Merged tickets and cross-references will need to be handled manually or through external mapping tables.
Side conversations aren't supported
If your source system has side conversations or collaborative threads, these cannot be imported via the API. Convert them to internal comments or accept that this data won't transfer.
JSON parsing quirks
One migration team using PowerShell encountered unexpected JSON parsing issues: "Zendesk balked that it cannot parse the JSON. The JSON I generated was syntactically correct, but I handed over the PowerShell object directly. Saving the JSON to a file first, then feeding it to Zendesk worked without problems."
Source: Zendesk Community Migration Experience
Alternative approaches: eesel AI and other options
Sometimes the API isn't the right choice. Consider these alternatives.

When to use CSV import instead
Zendesk's bulk CSV import works for users and organizations (not tickets) and handles up to 2,000 rows per file. It's simpler than the API but has significant limitations: no timezone import, no photos, no language preferences, and no ticket support.
Third-party migration services
For complex migrations, professional services like zendesk-import.com or the Zenplates Import App can handle the technical complexity. These services typically charge based on data volume but save significant development time.
Modern AI-powered alternatives
If you're migrating because your current help desk isn't meeting your needs, consider whether a modern AI solution might be a better fit than a traditional platform migration. eesel AI integrates with Zendesk to add AI-powered ticket handling, automated responses, and intelligent routing without requiring a full platform switch.
Start building better support workflows
Bulk importing tickets via the Zendesk API gives you precise control over historical data migration, but it requires careful planning and attention to edge cases. The key steps are simple: prepare your data thoroughly, handle suspended users, process in batches, and verify everything afterward.
If you're considering a migration because your current support tools aren't keeping up with your needs, explore how eesel AI's Zendesk integration can enhance your existing setup with AI-powered capabilities. Or if you're evaluating entirely new approaches to customer support, check out eesel AI's pricing to see how modern AI solutions compare to traditional platform migrations.
Frequently Asked Questions
Share this post

Article by
Stevia Putri
Stevia Putri is a marketing generalist at eesel AI, where she helps turn powerful AI tools into stories that resonate. She’s driven by curiosity, clarity, and the human side of technology.



