How to bulk import tickets using the Zendesk API

Stevia Putri
Written by

Stevia Putri

Reviewed by

Stanley Nicholas

Last edited March 2, 2026

Expert Verified

Banner image for How to bulk import tickets using the Zendesk API

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.

End-to-end workflow ensuring data integrity by importing users before tickets and validating results against your source system
End-to-end workflow ensuring data integrity by importing users before tickets and validating results against your source system

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.

Zendesk Ticket Import API endpoint documentation showing POST request structure and parameters
Zendesk Ticket Import API endpoint documentation showing POST request structure and parameters

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, and solved_at
  • Supports the archive_immediately parameter 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:

  1. Upload files to Zendesk using the attachments endpoint to get upload tokens
  2. 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.

Logic flow for navigating common migration hurdles like suspended requesters or archived tickets
Logic flow for navigating common migration hurdles like suspended requesters or archived tickets

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:

  1. Reactivate the users before import
  2. 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:

  1. Organizations (if using)
  2. Users
  3. 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.

eesel AI platform dashboard for configuring the supervisor agent, an alternative to complex migration tools
eesel AI platform dashboard for configuring the supervisor agent, an alternative to complex migration tools

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

No, the Ticket Import API is specifically for creating new tickets. To update existing tickets, use the standard Tickets API update endpoints.
Zendesk allows 700 requests per minute for most plans. Process tickets in batches of 100, implement exponential backoff when you hit 429 errors, and consider running large imports during off-peak hours.
Triggers and automations do not run on imported tickets. However, they will resume working if the ticket is updated after import. This is by design to prevent spamming users with notifications during migration.
The requester must be an active (non-suspended) user in Zendesk. You have two options: temporarily reactivate the former employee's account, or map their tickets to a placeholder account like 'Former Employee' before import.
No, Zendesk assigns new ticket IDs during import. If you need to maintain references to old ticket IDs (for example, links from your issue tracker), store a mapping table externally that connects old IDs to new Zendesk IDs.
The standard API creates new tickets with current timestamps and triggers business rules. The Import API preserves historical timestamps, bypasses triggers, supports closed/archived status, and is designed specifically for data migration scenarios.

Share this post

Stevia undefined

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.