Zendesk: Export All Tickets, Including the Old Ones

Getting some tickets out is easy. To make Zendesk export all tickets, with the conversations, and know you have all of them, is a different job.

"All tickets" is three questions, not one

Before you pick a method, answer these, because they decide the method for you.

How far back? Tickets closed for a long time are archived, and archived tickets behave differently in search and in some exports. If your answer is "since we started", archiving is your main problem.
Do you need the conversation? One row per ticket can't hold a fourteen-message thread. A CSV gives you attributes and the description. The replies live elsewhere.
Once, or forever? A one-off migration and a nightly sync are different builds. Don't start a recurring pipeline with a manual export.

The data export comparison covers what each route includes field by field. This page is about completeness: getting everything and proving it.

The account export, and where Zendesk exports all tickets from

An admin can trigger a full export of tickets, users and organisations. It runs as a background job and emails a download link when it finishes, which on a large account can be hours rather than minutes.

It's the broadest single button Zendesk gives you, and it has three practical catches. The link expires, so download it promptly. The job is rate limited to something like one run per interval, so it is not a scheduling mechanism. And the format you pick changes how much of the conversation comes with it, so choose deliberately rather than defaulting to CSV.

Use it for a genuine one-off. A legal hold, a company sale, an offboarding. Not for anything you'll need again next quarter.

The incremental export API, which is the real answer

For a complete history you can trust, the incremental export endpoints are what you want. They walk the whole account from a starting timestamp and hand you records in batches, with a cursor you can resume from.

GET /api/v2/incremental/tickets/cursor.json?start_time=0
# response contains after_cursor and end_of_stream
GET /api/v2/incremental/tickets/cursor.json?cursor=<after_cursor>
# repeat until end_of_stream is true

Two properties make this the right tool. It enumerates everything rather than matching a query, so it doesn't quietly skip archived tickets the way search can. And it is resumable, so a job that dies at 3am picks up where it stopped instead of starting again.

Things that bite people:

Batch sizes and rate limits are modest, and they differ by endpoint and plan. Build in backoff from the start and check the current Zendesk docs for the current numbers rather than trusting a figure from a blog post.
Comments are a separate call. The ticket record carries the description, not the thread. Pulling every comment for every ticket multiplies your request count by the average thread length, and that's usually what makes a migration take a week.
Attachments are URLs, not files. Downloading them is a second job, authenticated, and measured in gigabytes.
The same ticket appears more than once across a long run, because incremental means changed-since. Deduplicate on ticket ID at the end. Don't assume one row per ticket.

When Explore is enough

If what you want is a shaped extract rather than raw history, build it in Explore and export the result. Row-level reports are possible, and you get to choose the columns instead of taking whatever the account export produces.

The ceiling is real though. Explore exports cap out, and the cap differs between CSV and Excel. For a whole-account history you'll hit it. For "every ticket from the billing form last quarter with these eight fields", it's by far the fastest route, and the Explore guide covers building the report itself.

Proving you got everything

This is the step almost everyone skips, and it's the reason migrations discover missing years after the old instance is cancelled.

Reconcile before you trust the file. Count tickets in the export by month and compare that curve against a volume-by-month report in Explore. Gaps show up instantly as a month that's suspiciously thin.

Check the extremes too. Find the lowest and highest ticket IDs in your export and confirm they match the oldest and newest tickets in the account. Then spot check five tickets you know are old, and five with long threads, and read them.

Write the reconciliation down somewhere. A short note recording the ticket count, the date range, the export method and who checked it turns into the document you will be very glad of when somebody asks, two years later, whether the archive is complete. Nobody ever remembers, and the export file itself carries none of that context.

And keep the old instance alive for a while after the cutover. Cancelling early is the mistake you can't undo.

FAQ

Frequently asked questions

Which export includes full ticket history?

The incremental export API. A Zendesk full ticket export from the account export gives you the ticket rows; Zendesk export ticket history with comments means paging the Zendesk incremental export endpoints.

Does the Zendesk export include archived tickets?

It depends on the route. Search-based approaches can miss archived tickets, while the incremental export endpoints enumerate the account rather than matching a query. Verify by comparing counts by month.

Can I export Zendesk tickets with all comments?

Not from a CSV. You need a full account export in a structured format, or a pass over the comments endpoint per ticket.

How long does a full Zendesk export take?

Hours on a large account for the built-in export, and potentially days for an API pull that fetches every comment, because of rate limits.

Can I schedule a full ticket export?

Not through the account export tool, which is rate limited to occasional runs. Use the incremental export API with a stored cursor for anything recurring.

Why does my export have more rows than I have tickets?

Incremental exports return every change, so a ticket updated many times appears many times. Deduplicate on ticket ID.

Count the duplicates while you are in there

A full export sorted by requester and created date shows how much of your history is the same request arriving more than once.

Start free trial

14-day free trial. No credit card required.