Macha

Zendesk Organization Cleanup: Finding the Dead Ones

Abbas, Customer Support & AI, Macha

Written by

Ankeet Guha, Co-founder & CTO, Macha

Reviewed by

Published September 9, 2026

Updated September 9, 2026

Zendesk organization cleanup is one of those jobs nothing prompts you to do. An organization that nobody belongs to and that has no tickets is close to invisible. It costs nothing, breaks nothing, and shows up in exactly the places where a wrong choice is expensive: the picker an agent uses when reassigning a ticket, the condition list when somebody builds a routing rule, and the grouping on a report that a manager reads once a quarter.

Zendesk Organization Cleanup: Finding the Dead Ones

That's the argument for auditing them, and it's a smaller argument than "clean data is good". The specific harm is misselection, and it compounds quietly.

A disclosure before the numbers

Our developer instance had one organization. One isn't enough to demonstrate an audit, so we created nine more to give the query something to return.

That means the empty organizations in the screenshots below are new-and-empty rather than genuinely abandoned, and any ratio you could compute from them describes our seeding. We're showing the method and the signature, not a finding about how many organizations go stale in the wild.

The one real data point is the original organization, which has 3 users and 140 tickets.

Zendesk Organizations: all 10 rows, nine we created for this demo with no domain or tags, plus one real org from 2023
Zendesk Organizations: all 10 rows, nine we created for this demo with no domain or tags, plus one real org from 2023

Why the columns don't tell you

The obvious move is to read the list. Domain and Tags are empty on all nine seeded rows, and it is tempting to call that the signature of an abandoned organization.

Our own screenshot is the argument against doing that. The macha organization has no domain and no tags either, and it has 3 users and 140 tickets attached to it. Blank columns mean unconfigured. They do not mean unused, and on this instance the single busiest organization looks identical to the nine empty ones.

A domain matters because that is how end users get mapped in automatically, and tags matter because that is how an organization feeds routing and business rules. An organization with neither is not participating in either mechanism. That is still worth knowing, and it is still not a reason to delete anything.

Which is the whole case for the audit below: the only columns that separate a dead organization from a busy one are the two the list page does not show you.

Dates help a little more than the other columns, though not enough to act on alone. An organization whose last update is years old and whose ticket count is zero has been dormant since somebody made it, and that is a different situation from one that used to be busy and went quiet. Separating those two still needs the counts.

The audit

Two counts per organization: how many users belong to it, and how many tickets reference it. Both are single API calls, and the whole thing fits in a short script. Our Zendesk API guide covers authentication if you have not scripted against it before.

Here is the whole thing:

// audit-orgs.js — rank organizations by how little they contain.
const { execFileSync } = require('child_process');
const get = p => JSON.parse(execFileSync('node', ['scripts/zd-fetch.js', p], { maxBuffer: 1e8 })
  .toString().split('\n')[0]);
// List endpoints return at most 100 records per page. Follow next_page or you will
// silently audit only the first 100 organizations, which is the failure this post warns about.
function all(path, key) {
  const out = [];
  let url = path;
  while (url) {
    const page = get(url);            // must surface 429 + Retry-After, see below
    out.push(...(page[key] || []));
    url = page.next_page ? page.next_page.replace(/^https:\/\/[^/]+/, '') : null;
  }
  return out;
}

const rows = all('/api/v2/organizations.json?per_page=100', 'organizations').map(o => ({
  name: o.name,
  users: all(`/api/v2/organizations/${o.id}/users.json?per_page=100`, 'users').length,
  tickets: get(`/api/v2/organizations/${o.id}/tickets.json?per_page=1`).count ?? null,
  created: o.created_at.slice(0, 10),
}));
rows.sort((a, b) => (a.users + a.tickets) - (b.users + b.tickets));
const pad = (s, n) => String(s).padEnd(n);
console.log(pad('ORGANIZATION', 24) + pad('USERS', 8) + pad('TICKETS', 9) + 'CREATED');
console.log('-'.repeat(55));
for (const r of rows) console.log(pad(r.name, 24) + pad(r.users, 8) + pad(r.tickets, 9) + r.created);

Swap scripts/zd-fetch.js for whatever you use to make an authenticated GET. Running it against our instance:

ORGANIZATION            USERS   TICKETS  CREATED
-------------------------------------------------------
Aster Labs              0       0        2026-08-27
Bluepeak Logistics      0       0        2026-08-27
Cedar & Co              0       0        2026-08-27
Dunmore Retail          0       0        2026-08-27
Evergreen Health        0       0        2026-08-27
Fairline Media          0       0        2026-08-27
Gantry Software         0       0        2026-08-27
Halcyon Foods           0       0        2026-08-27
Northwind Traders       0       0        2026-08-27
macha                   3       140      2023-09-14

Sort ascending by users plus tickets and the dead ones surface at the top. On a real instance this is the whole audit: the organizations worth attention are the ones at the top of that list, and the ones at the bottom are the ones actually doing work.

One caution that cost us time. If you sample tickets to estimate this rather than querying per organization, you'll get a wrong answer, and it will look plausible:

Terminal: the same organization counted two ways, 6 from a 100-ticket sample versus 140 queried directly
Terminal: the same organization counted two ways, 6 from a 100-ticket sample versus 140 queried directly

Six versus a hundred and forty, for the same organization, on the same instance, a second apart. The six is an artifact of the sample: the tickets endpoint returns oldest first, and this instance's organization-linked tickets sit at higher ticket ids, so the first page misses almost all of them.

Count per organization. Don't extrapolate from the first page of anything.

What to do with what you find

There are three outcomes. Only one is deletion.

Merge. Two organizations for the same company is the most common real finding, usually from a domain change or a slightly different spelling. Zendesk has a native organization merge: users, tickets and domains move into the surviving organization and the merging one is deleted when it completes. That keeps the history and removes the ambiguity, and it's usually the right call when both have tickets.

It is not free, though, and this article has been careful about warning before deletion so it should be careful here too. Zendesk documents that "organization merges are permanent and can't be undone", and that the merging organization loses its tags, notes, details, custom organization fields, external ID, group mapping, shared-organization setting and related records. Tickets, users and domains carry over; the configuration around them does not. There is also a ceiling: the merging organization must have 10,000 or fewer tickets and 10,000 or fewer users, or the merge is blocked.

So decide which organization survives before you start, because the one you merge away is the one that loses its configuration.

Fill in. An organization with users but no domain and no tags is unconfigured. It's doing something, and somebody is going to wonder why routing skips it. Adding the domain is usually a two-minute fix that removes a recurring confusion.

Delete. If your reason for deleting is data hygiene, check whether a deletion schedule is the better instrument, since that removes ticket data on a timer and leaves the organization records alone. Reserve deletion for organizations with no users, no tickets, and no configuration, which is to say the ones that were created and never used. If you do not write code, this is not a dead end. Zendesk's own guidance on bulk deleting organizations and users points at marketplace apps built for exactly this, and they are the right answer when the alternative is clicking through several hundred rows. What they generally will not do is the diagnosis: the counts that tell you which organizations are safe to remove. Read this article for the audit and use an app for the removal.

At any real scale the removal is a scripted job: the API exposes a bulk delete that takes up to 100 organization ids per request, and the list endpoints page at 100 records, so both halves of the work want a loop. Deleting an organization that has tickets changes what those tickets look like. Treat any ticket count above zero as a reason to stop and think.

Before deleting anything, check whether the name is referenced in a view or a trigger. A business rule pointing at an organization that no longer exists is a quiet failure, and it's much easier to find the reference before you remove the target than after.

Why they accumulate

Organizations get created by more paths than most admins remember, and only one of those paths involves a person deciding an organization should exist.

They come from imports, where a spreadsheet column becomes an organization per unique value including the typos, the same way a careless import multiplies custom field values. They come from integrations that create an organization per account in some other system. They come from the mapping rules that attach end users by email domain, where a one-off domain produces a one-off organization. And they come from people setting something up, changing their mind, and moving on.

None of those paths includes a cleanup step, which is the entire reason this article exists. The rate of creation has a mechanism and the rate of removal does not, so the count only goes up.

That also tells you when to run the audit. Run it after any bulk import, any new integration that writes organizations, and any migration. Those are the events that create dozens at once.

Why nothing tells you to do this

It's worth being clear about where the tooling stops, because the incentive explains the gap better than an oversight would.

Organizations are unlimited and free. They don't appear on your bill, they don't consume a seat, and a thousand of them cost Zendesk essentially nothing to store. The cost of having too many falls entirely on you, and it falls as confusion: a slower picker, a duplicated report line, a routing rule that misses.

The tooling position is more interesting than "they built nothing", which is what we assumed before checking. There is a documented bulk delete endpoint for organizations, so the removal half is solved if you are willing to script it. Zendesk also shipped a bulk-delete organizations app, now archived. Its last commit was September 2016, which tells you how long it went unmaintained before somebody flipped the archive switch.

What does not exist is the half that would prompt you. No staleness flag, no badge for an organization with no users and no tickets, nothing in managing organizations that surfaces the problem at all. A vendor builds detection where the pain shows up in their own metrics or their own support queue, and organization sprawl shows up in neither.

Deletion is a supported operation. Noticing you need it is your job, so put the audit in your own calendar.

A note on scale

At ten organizations, none of this matters much and you can eyeball the list.

At several hundred, the picker becomes genuinely hard to use, and misselection stops being hypothetical. At a few thousand, reporting by organization becomes unreliable in a way that's hard to trace, because the long tail of near-duplicate names splits a single customer's tickets across several rows and nobody notices the total is spread out.

The audit does not take the same time at every size, and it is worth being precise about that because the script above is the thing that breaks.

It makes two calls per organization plus one to list them, so a hundred organizations is around 201 requests and two thousand is around 4,020 once the paged listing is counted. Zendesk's rate limits are 200 requests a minute on Team and 400 on Growth and Professional, so the large case is ten to twenty minutes of sustained calling even if you never exceed the limit, and in practice you will meet a 429.

There is an optimization worth naming before you accept that number. The user half does not have to be per-organization: one paged pass over /api/v2/users.json, grouped by organization_id, gets the same counts in about a twentieth of the calls. The version above stays per-organization because it is easier to read and easier to stop halfway, which is the right trade at a hundred organizations and the wrong one at two thousand.

Either way, handle the 429 or the script dies partway through a job you then have to restart. On a 429 Zendesk returns a Retry-After header telling you how many seconds to wait; sleep for that long and repeat the request rather than treating it as a failure. The version above deliberately leaves that out to stay readable, which is fine on a small instance and not fine on the ones this article is aimed at.

Common questions

Does deleting an organization delete its tickets? No, but it changes them: tickets lose the organization association. Check the ticket count before deleting and treat anything above zero as a reason to merge rather than delete.

How do I find organizations with no users? Query the users endpoint for each organization and count what comes back. Don't infer it from a sample of tickets, since ticket listings are ordered and a first page is not representative.

Can I merge two Zendesk organizations? Yes, and it's usually the right answer when both have history. Merging preserves tickets and users while removing the duplicate name from pickers and reports.

What creates organizations I didn't ask for? Imports, integrations that sync accounts, and automatic domain mapping. Run an audit after any of those, since they create organizations in bulk.

Is an organization with no domain broken? Not broken, just unconfigured. Automatic user mapping relies on the domain, so an organization without one needs users added by hand or by rule, which is often why it looks half-populated.

Where an AI layer fits

Organization data is one of the few things an AI agent can use to change an answer, not merely to find one. Most context an agent reads tells it what to say. Organization membership tells it which policy applies: which terms this customer signed, which SLA governs the reply, which queue the ticket belongs in.

That distinction is why duplicates hurt here more than elsewhere. A wrong article retrieved produces a vague answer somebody notices. A wrong organization produces a confident, specific, well-written answer citing the wrong contract, and it reads exactly like a right one.

The failure is worse than a human's for a structural reason. An agent seeing "Northwind Traders" and "Northwind Traders Ltd" has no way to know they are one customer; a person has met them. So every duplicate in your list is a coin-flip an automation makes silently and a person would not have to make at all.

Which sets the order of work. The audit in this article is not tidying you do before adopting an agent. It is the thing that decides whether the agent's most valuable capability works or misfires, and it costs a few minutes. Macha reads your organizations as they stand, applies no fuzzy matching, and will treat those two Northwinds as two customers, because guessing would be worse. Whether that is the behavior you want depends on which problem you have. If you already maintain the list, strict matching is what you want and fuzzy matching would be the bug. If you were hoping automation would paper over a messy list, nothing here will, and the audit above is the actual prerequisite rather than an optional tidy-up beforehand.

Start your free trial once your organization list is clean enough to be worth reading.

Macha

About Macha

Macha is an AI agent platform that works on top of the help desk you already use — Zendesk, Freshdesk, Gorgias, or Front — and connects to the rest of your stack, even your own internal systems. Its AI agents resolve tickets and automate entire workflows end to end, all set up in plain English, no code. Learn more about Macha →

Zendesk
5.0 on Zendesk Marketplace

Loved by support teams worldwide

See what support teams are saying about Macha AI.

The application seems excellent to me! We are still testing, and we need support for some details and they were extremely efficient too!

Daniela Costa

Daniela Costa

Head of Support, Seabra

Macha has been a great addition to our support toolkit. It generates clear, well-organized responses that fit naturally into our workflow. One feature we particularly appreciate is its ability to automatically reply in the same language as the ticket.

Marius F

Marius F

Support Head, Zentana

We've been using Macha for a little while now and it's been really great addition so far! It's powerful, convenient, and makes getting work done a lot easier for our agents.

Alexander Wedén

Alexander Wedén

Head of Support

Support team is very helpful and responsive. Really enjoy how lightweight this is within Zendesk itself vs other more intrusive tools.

Cathleen Wright

Cathleen Wright

Zendesk Admin, Cortex IO

So far it's pretty good! Our queries are a little nuanced, so we can't always use it, but it's got enough utility for us. It can even incorporate our bilingual country with greetings in a second language.

Jae Oliver

Jae Oliver

Head of Support, Wise

Really enjoying using Macha, it has made a noticeable difference to our support team in a short amount of time. I really like the ticket summary feature, saves us a lot of time.

Harry Jackson

Harry Jackson

Head of Support, Crumb

Macha AI is a great addition to my workspace! It's powerful, convenient, and it really makes productivity so much easier for our agents!

Dave G

Dave G

Head of Support, Cyber Power Systems

Very impressed! AI integration for Zendesk has certainly come a long way and Macha seems to set the standard for now. This will for sure save lot of time in our support team.

Pauli Juel

Pauli Juel

Head of CS, Dokument24

Macha has been working great for us so far! The auto-responses are accurate and our resolution time has dropped significantly.

Lana T

Lana T

Zendesk Admin, Swotzy

Macha AI is a great addition. The knowledge base feature means our agents always have the right answers at their fingertips.

Mischa Wolf

Mischa Wolf

Head of Support, Topi

We're enjoying this integration so far. It's made our support team more efficient and our customers get faster responses.

Paula G

Paula G

Head of Customer Support, Xly Studio

The team enjoys using it. It saves considerable time on common questions and the integration options are excellent.

Kilian Leister

Kilian Leister

Support Head, Didriksons

Ready to supercharge your team with AI?

Get started in minutes. Connect your tools, configure your agents, and let AI handle the rest.

500 free credits · no time limit, no credit card