zendesk ticket import api "external_id already taken"
A guide to fixing the Zendesk "external_id already taken" error on ticket import, in the business-apis-integrations category: external_id uniqueness rules, check-before-create upserts, and idempotent import patterns. Use when bulk imports or agent-created tickets collide on external_id, or when designing idempotent ticket creation. Not for Zendesk deduplication rules, ticket merge, or import file formatting.
TL;DR
Zendesk enforces uniqueness on ticket externalid, so an import that reuses an id from an earlier run fails with "externalid already taken." Make imports idempotent: look up the existing ticket by external_id first, update it if found, create it only if not. The lookup turns a duplicate crash into an upsert.
The query
zendesk ticket import api "external_id already taken"Use this when
- Ticket imports fail on external_id collisions
- A re-run of an import crashes on already-imported tickets
- Agents create tickets with client-supplied external ids
- You are building idempotent ticket creation
Not for
- Zendesk duplicate detection rules
- Merging duplicate tickets
- CSV import column formatting
- Choosing external id schemes
Steps
1. Treat the error as "already imported," not as a failure
This error means the record exists. The correct response is almost never to fail the job; it is to find the existing ticket and decide whether to update it or skip it. Log it as a match, not an error.
Expected output: collisions logged as matches, jobs keep running.
2. Look up by external_id before creating
Query tickets by the external_id first. If a ticket comes back, you have your upsert target. One extra read per create eliminates the entire error class and makes reruns safe.
Expected output: check-before-create on every import path.
3. Decide update versus skip per import type
Initial migrations usually want update-on-match (source of truth may have changed). Incremental syncs usually want skip-on-match (only new records matter). Pick one, document it, and apply it consistently. Mixed behavior corrupts data silently.
Expected output: a documented, consistent match policy.
4. Namespace external ids per source system
Prefix ids with the source: "shopify-12345" not "12345." Two systems with overlapping id spaces collide constantly; namespacing makes collisions meaningful (true duplicates) instead of accidental.
Expected output: source-prefixed external ids on all imports.
5. Make the whole import rerunnable
Design the job so a crash at record 900 of 1000 resumes cleanly: external_id upserts, checkpointed progress, no partial side effects. Rerunnability is what turns "already taken" from a disaster into a no-op.
Expected output: imports that can be re-run safely any number of times.
Template: the checklist
External_id collision handling:
[ ] Lookup by external_id before every create
[ ] Update-vs-skip policy documented per import type
[ ] External ids namespaced per source system
[ ] Collisions logged as matches, not failures
[ ] Full import rerunnable from any checkpointVariant phrasings
duplicate external_id zendesk import
Steps 2 and 3. Lookup, then a consistent match policy.
external id already exists ticket api
Steps 1 and 2. Read it as "already imported."
idempotent zendesk ticket creation
Steps 2 through 5 as the idempotency design.
Why it happens
external_id exists so external systems can own the identity of their tickets, and uniqueness is what makes that ownership reliable. But import jobs are rarely run once: they retry, resume, and overlap. Without a lookup step, every rerun replays creates for records that already exist, and uniqueness does exactly what it was built to do: reject them.
Edge cases
- Race between lookup and create: two workers can both miss and both create. Serialize per external_id or accept rare collisions with retry-as-update.
- external_id on the wrong ticket: a stale mapping can point at a ticket that was repurposed. Validate the match belongs to the expected source.
- Case sensitivity: normalize id casing before lookup. "ABC" and "abc" may or may not match depending on the path.
- Imports that intentionally create duplicates: rare, but if the business wants duplicates, external_id is the wrong field; leave it blank.
Provenance
Resolved from the public thread: https://vectle.com/posts/pst_P2H2KgnM1-qmN57pC5ptcQ