This week I tried to do the single most pro-Anthropic thing a paying customer can do: measure my engineering team's adoption of Claude Code so I could grow it. I wanted a live dashboard, sitting next to our other operating metrics, that answered one question every week — are more of my engineers getting more value out of Claude Code than they did last week? I wanted to celebrate the power users, spot the colleagues who hadn't started yet, and put a real number in front of leadership to justify expanding our investment.
I could not build it. Not because the data doesn't exist — Anthropic has it, and renders it beautifully inside the Claude app. I couldn't build it because Anthropic does not let a Team-plan administrator query their own team's data programmatically. The numbers are right there on my screen. The door to them is locked, and the key is sold separately, under a different plan, in a different organisation, behind a URL that redirects to nowhere.
I want to write this up the way I'd write any serious product escalation: lead with the conclusion, show the evidence, separate fact from opinion, and end with what "good" looks like. I've spent twenty-five years in and around engineering and product leadership, and I've learned that the most useful feedback a vendor can get is from a customer who wants them to win and is willing to be specific about where they're getting in their own way. So, candidly and with respect: Anthropic, this is a miss, and you can do better.
Act 1: Working backwards from what I actually wanted
Start with the customer, not the API. The customer here is me — an engineering leader trying to drive a behaviour change. Adoption of a new tool is never a snapshot; it's a trend. "We have eight seats" tells you nothing. "Weekly active engineers went from two to six over a month, acceptance rate is holding above 90%, and here are the two people who haven't logged a session yet" tells you everything. That second sentence is a management tool. The first is a procurement receipt.
So the brief was concrete: a tab in our internal platform showing active engineers over time, sessions, lines of code accepted, tool-acceptance rate, and cost per active engineer — framed end to end around that one adoption question. We already do exactly this for our delivery metrics out of Jira, so the pattern was proven and the appetite was a single afternoon. We don't use GitHub, so I was happy to drop the pull-request metrics and keep the rest.
This is the behaviour Anthropic wants from a customer. I was about to instrument my own team to use their product more. Hold that thought.
Act 2: The build was the easy part (it always is now)
I didn't write the integration by hand. I drove; Claude Code wrote it. In one pass it produced a clean server-side module against Anthropic's documented Claude Code Analytics API — windowed daily fetch, cursor pagination, exponential backoff, a circuit breaker, an hour-long cache with stale-while-revalidate. Good, defensive, production-shaped code. I created an Admin API key in the Console exactly as the docs instruct, wired it into our backend, and shipped it.
Then we did the one thing that separates engineering from wishful thinking: before rendering a single chart, we ran the integration against the real API and looked at what came back. Insist on the highest standards isn't a poster on a wall — it's the discipline of validating the write/read path against production data instead of trusting that green tests mean a correct system. That discipline is exactly what caught the problem.
Act 3: Dive deep — the smoke test that told the truth
Ninety-day window. The API returned four records. Zero of them were engineers. The only usage it reported was our own application's API key making headless calls — useful to know, but not a single human developer in the result set.
Now, I know my team uses Claude Code. I'd seen the dashboard the day before: heavy, healthy usage. So either every engineer had quietly stopped overnight, or the API was answering a different question than the one I was asking. A green pipeline returning a confident, precise, wrong answer is the most dangerous artefact in software. Had we skipped the validation step and wired the charts straight up, I'd have walked into a leadership review with a dashboard declaring "zero adoption" of a tool my team was using daily. That's not a bug report; that's a credibility event.
200 OK and an empty truth. Everything that followed was the work of figuring out why the truth was empty.
Act 4: Two organisations, one name, no link
So we interrogated the credential itself. We pointed the same Admin API key at the Admin API's other endpoints and asked it, in effect, "who are you?" The answer was the whole story:
| What I expected the key to see | What the key actually saw |
|---|---|
| My 8-person engineering team | One member — me |
| Engineers' Claude Code usage | Zero records for every date I checked |
| "My organisation" | An organisation with the same name — but the API one, not the team one |
There are two organisations. They share the same display name. They are not linked, not cross-queryable, and nothing in either product tells you the other exists:
Anthropic Console (API plan) Claude app (Team subscription)
---------------------------- ------------------------------
* where my Admin key lives * where my 8 engineers live
* one member (me) * the Claude Code seats + real usage
* our app's API key + credits * the dashboard I screenshotted
* Admin API works here * no programmatic API surface at all
| |
+------------- same name, NO link -------+
The Admin API key can only ever see the Console organisation. My engineers don't live there; they live in the Team subscription, which is a separate identity on a separate surface. And here's the part that moves this from "confusing" to "below the bar": this is a known, reported, still-open bug. Anthropic's own issue tracker carries claude-code #27780 — "Claude Code Analytics Admin API does not return subscription/OAuth users", documenting precisely this: the endpoint only ever returns customer_type: "api" records, and the OAuth/subscription users the docs themselves call "most common" never appear at all. It has been open since February 2026 with more than a dozen comments and no fix — and it notes that two earlier reports of the same bug (#20819 and #9700) were auto-closed by a bot without a single response from Anthropic. The product knows it gives a misleading answer here, and it gives it anyway, silently, with a 200.
I'll be plain about this as a design critique: two organisations with the same name and no discoverable relationship is a trap that every admin in my position will fall into. It cost me hours. It will cost the next person the same hours. Earn trust means, among other things, never letting a customer build a confident mental model on top of a silent inconsistency.
Act 5: The wall — and a documented door that opens onto a wall
Fine. If the engineers live in the Team subscription, I'll mint a key there. The documentation for the subscription analytics API is explicit: create an API key at claude.ai/analytics/api-keys, as a Primary Owner. I am the Primary Owner. So I had Claude drive my own browser to go find it.
That URL redirects to general Settings. The page does not exist for my organisation. We checked, methodically, every place a Primary Owner would reasonably look:
- Organisation settings — no API-keys section.
- The Analytics app itself (
/analytics/activity,/analytics/claude-code) — no API-keys section. - The Claude Code analytics dashboard, top to bottom — a gorgeous chart, a CSV Export button, and nothing resembling programmatic access.
The data was right there on the screen the whole time — that month, five active engineers, on the order of a hundred thousand lines of code accepted between them, weekly active users up by a third. The only sanctioned way to get those numbers out of Anthropic's servers and into a dashboard I control is to click "Export" and download a spreadsheet by hand, every week, forever.
The reason the URL is a dead end is the reason this whole post exists. The programmatic analytics API is real and genuinely good — per-user Claude Code metrics, daily/weekly/monthly active users, token and cost breakdowns. But the reference guide that documents it is the Claude Enterprise Analytics API guide, and minting a key requires being "Primary Owner within your Enterprise organisation." I am a Primary Owner of a Team plan. Team plans don't get it.
| Capability | Team plan | Enterprise plan |
|---|---|---|
| In-app Claude Code analytics dashboard | Yes | Yes |
| Manual CSV export | Yes | Yes |
| Programmatic Analytics API + key | No | Yes |
| Console Admin API returns your engineers | No (wrong org) | — |
So the documented path I was sent down — create a key, call the API — was never available to me. The door is in the docs. The wall is behind the door. The key is sold one pricing tier up.
Act 6: Why this is the wrong line to draw
Let me separate the legitimate from the indefensible, because I don't want this to read as a customer who simply wants everything for free. I don't.
What's legitimate. Gating heavy governance, SCIM provisioning, audit/compliance export, and bulk administrative control behind Enterprise is completely reasonable. Those are genuinely enterprise concerns with enterprise cost. If that were the line, I'd have nothing to write.
What's indefensible. Putting a Primary Owner's read-only access to their own team's adoption numbers on the far side of that same wall. Think about who that decision actually penalises. It's not the disengaged customer. It's the admin who is so bought in that they want to wire Claude Code metrics into their company's own operating cadence and evangelise the results internally. You are taxing your most enthusiastic champions at the exact moment they're trying to spend political capital on your behalf. Customer obsession would start from that champion and work backwards. This decision works backwards from a pricing table.
And the supporting details compound it rather than soften it:
- A documented URL (
claude.ai/analytics/api-keys) that redirects to nowhere for the plan most likely to read that doc. - An Admin API that returns a silent, empty, 200-OK wrong answer for subscription users — a behaviour reported repeatedly, and still open, in Anthropic's own issue tracker.
- A two-organisations-same-name identity model with no in-product signpost connecting them.
Individually, each is a paper cut. Together, they cost a competent, motivated, paying admin the better part of a day to discover that the answer is simply "no, not on your plan." That's not a hard technical limitation. Every byte of this data already leaves Anthropic's servers to render my dashboard and my CSV. This is a product-segmentation choice, and it's the wrong one.
What "good" looks like
Criticism without a recommendation is just complaint, so here's what I'd ship if this were my product. None of it requires building new data — only opening a tap that already flows.
- Give Team-plan Primary Owners a scoped, read-only analytics key — mintable from the very dashboard they're already looking at. Read-only. Their own org. That's the whole ask. I'll build everything downstream of it myself; in fact, I already have.
- Make the two-organisation relationship discoverable in-product. One line on the Console org switcher and the analytics page: "Your Claude Code seats live in your Team organisation. View its analytics here." A signpost costs nothing and saves every admin the rabbit hole I just climbed out of.
- Fix the silent wrong answers. If the Console Admin API can't return subscription users, it should say so — an explicit, documented
not-supported-for-this-org-typeresponse beats a friendly, confident, empty200every time. Loud failure over quiet falsehood. - Repair the docs. A reference guide should not point Team admins at a URL that redirects to Settings. Either the page exists for them, or the guide says, in bold, "Enterprise only."
- State the tiering honestly, up front. If programmatic analytics is an Enterprise feature, put that on the Team plan page before I write the integration — not three hours and one production-shaped backend into the build.
The Takeaway
I want to end where I started: as a customer who wants Anthropic to win. Claude Code is an outstanding product — my team's usage proves it, and the irony is that I only know how good the numbers are because the in-app dashboard is excellent. The build itself, done with Claude, took an afternoon. The product gap took the rest of the day to map, and it's the only thing standing between me and a dashboard that would have made me a louder advocate inside my own company.
So I'll say it directly and respectfully: Anthropic can do better here, and I believe they will. The fix is small, the data already exists, and the customers you'd delight are the ones already cheering loudest for you. Let the people keeping score see the scoreboard. Until you do, I'll wire up the CSV export and keep the live integration warm — it's ninety percent done, pointed at the endpoint I'm not yet allowed to call, ready the day that wall comes down.
I'd rather be writing about the dashboard. I'll settle, for now, for writing about why I can't.
Method note: the integration was written by Claude Code in a single session; the production read-path was validated live before any UI was built (which is what surfaced the empty result); and the org/credential investigation — including driving my own Chrome session through the Claude admin settings to confirm the missing API-key surface — was likewise done by Claude under my direction. Team-member identities and individual figures have been deliberately omitted; the only numbers quoted are organisation-level aggregates already shown on Anthropic's own dashboard. No teammate's personal usage is named here.
Stack, for the curious: React/Vite front end, Azure Functions API, a server-side fetch-and-cache module mirroring our existing Jira "Technology Roadmap" integration. Cups of coffee spent discovering that "the API exists" and "the API is available to me" are two very different sentences: more than the chart would suggest.

No comments:
Post a Comment