Bulk Import Users in Zendesk

To bulk import users, Zendesk gives you two routes: a CSV upload and a job-based API. They suit different problems, and a completed job never means every record worked.

Bulk import users into Zendesk: pick the route first

CSV upload. Admin Center takes a file of users and organisations and imports them. No code, and the right answer for a one-off load at the start of a project or a list somebody exported from another system.
The bulk API. Job-based endpoints that take up to 100 records per request. The right answer for anything repeating, anything driven by another system, and anything you need to run again next month without a human.

The test is honestly just this: will you do it more than twice? If yes, write the code. If no, upload the file and get on with your day.

A third option people forget: for an ongoing sync where users arrive one at a time, you do not need bulk at all. The upsert endpoint handles a single user per call perfectly well, and a steady trickle is easier to reason about than a nightly batch.

The CSV route to bulk import users into Zendesk

The importer lives in the admin side of the product rather than in the agent interface, and it takes a file with a header row. The columns it accepts are documented, and they map onto the same fields the API uses: name, email, external id, organisation, role, and your custom user fields by key.

Three things that trip people up.

It matches on email. An existing address updates the existing user rather than creating a second one. That's usually what you want, and it also means a typo in a column header can rewrite several thousand records.
Row limits and processing time. Large files are processed in the background and the result arrives by email. Don't sit and watch it. Split genuinely enormous files rather than finding out at the end.
There is no undo. A bad import is corrected by another import, if you're lucky, or by hand if you are not. Test on a sandbox with twenty rows first. The Zendesk CSV import guide covers the file format in more detail.

The API route to bulk import users into Zendesk

Two endpoints matter. create_many creates users and fails on any that already exist. create_or_update_many upserts, matching on email or external id, which is what you almost always want.

Both take an array wrapped in users, and both cap at 100 per request.

{
  "users": [
    { "name": "Ada Bell", "email": "ada@example.com", "external_id": "crm-88213" },
    { "name": "Grace Poole", "email": "grace@example.com", "external_id": "crm-88214" }
  ]
}

Neither returns users. Both return a job.

{ "job_status": { "id": "8b726e606741012ffc2d782bcb7848fe", "status": "queued" } }

Set skip_verify_email where the reference supports it, or your import will send verification mail to everyone in the file. That's the single most expensive mistake available in this whole area, and it's entirely silent until the replies start.

Checking the job, properly

The job ID goes to the job statuses endpoint.

curl -u "you@acme.com/token:$ZD_TOKEN" \
  https://acme.zendesk.com/api/v2/job_statuses/8b726e606741012ffc2d782bcb7848fe.json

You get a status, a total, a progress count and, once it finishes, a results array with one entry per record. That array is the whole point.

A job status of completed means the job ran. It doesn't mean every user was created. Individual records can fail, for a duplicate email, an invalid address, a bad organisation reference, and the job still reports as done. Read the results, count the successes, and log the failures somewhere a person will see them.

Poll with a sensible interval, a second or two, with a timeout. Job statuses are retained for a limited period, so fetch the result while it exists rather than planning to look tomorrow.

Preparing the data is most of the work

The import is the easy part. Getting a clean list is not.

Normalise email addresses. Lowercase them, trim whitespace, and pick one canonical address per human. Zendesk matches exactly, so Ada@Example.com with a trailing space becomes a second person.

Set external_id on everything. It's the only stable link back to your own system, and adding it later means matching by email all over again.

Decide the role explicitly. Omit it and you get an end user, which is right for customers and wrong for the fifteen colleagues buried in the middle of your file. Promoting people accidentally consumes agent seats.

Run a sample first. Twenty rows, then check them in the interface. Not two thousand rows and a hope.

Expect duplicates that Zendesk can't see. Two rows, same human, different addresses. The import creates two users, both legitimate, and they'll go on raising tickets independently for years.

FAQ

Frequently asked questions

What does the create_many endpoint do?

Zendesk create_many users is the job-based endpoint behind any Zendesk user import API work: you POST up to a hundred users, get a job back, then poll it. Zendesk bulk create users this way scales far better than CSV.

How many users can I create in one API request?

Up to 100, using create_many or create_or_update_many. Both run asynchronously and return a job ID rather than the created users.

Which route should I use to bulk import users into Zendesk?

CSV for a one-off load with no code. The API for anything repeatable, scheduled or driven by another system.

How do I check whether a bulk import worked?

Poll the job statuses endpoint with the returned job ID and read the results array. A completed job can still contain individually failed records.

Will a bulk import email everyone?

It can, through identity verification. Use the skip verification option where the endpoint supports it, and test on a small sample before running the full file.

What happens if a user in my import already exists?

With create_many that record fails. With create_or_update_many it's matched on email or external id and updated instead.

Clean users, and then the duplicate tickets they raise

Ticket Merger merges duplicate Zendesk tickets on requester, subject keywords and ticket fields within a time window, with exclusions for the cases you want left alone.

Start free trial

14-day free trial. No credit card required.