npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@hameddk/anthropic-spend-collector

v0.1.0

Published

Pull real spend and token usage from Anthropic's Admin Usage and Cost Report APIs. Joins per-workspace cost data with per-model token counts. Pluggable auth, paginated, zero dependencies.

Readme

@hameddk/anthropic-spend-collector

Pull real spend and token usage from Anthropic's Admin Usage and Cost Report APIs. Joins per-workspace cost data with per-model token counts into a single normalized row stream.

  • Calls /v1/organizations/cost_report for USD spend (no pricing-table guesses)
  • Calls /v1/organizations/usage_report/messages for token counts per model
  • Cursor-based pagination; tested across 90+ day ranges
  • Caller supplies the Admin API key — no DB, no filesystem, no business logic
  • Zero dependencies, ESM, Node ≥ 18

Status: 0.1.0 — early. Public API is stable for the documented surface.

Why

Most Anthropic usage tooling either (a) only reads token counts and guesses cost from a pricing table, or (b) reads bulk cost without per-model attribution. This collector calls both Admin endpoints and merges them so you get real USD spend broken down by model.

Install

npm install @hameddk/anthropic-spend-collector

Quick start

import { runCollector } from '@hameddk/anthropic-spend-collector';

const result = await runCollector({
  apiKey: process.env.ANTHROPIC_ADMIN_KEY,   // sk-ant-admin-…
  from: '2026-04-01',
  to: '2026-04-30',
});

if (!result.ok) {
  console.error(`[${result.errorType}] ${result.error}`);
  process.exit(1);
}

for (const row of result.rows) {
  console.log(`${row.date}  ${row.identity}  ${row.tool}  $${row.cost_usd?.toFixed(4)}`);
}

API

runCollector({
  apiKey: string,           // required — Admin API key (sk-ant-admin-…)
  from: 'YYYY-MM-DD',       // required — UTC inclusive
  to:   'YYYY-MM-DD',       // required — UTC inclusive
  workspaceId?: string,     // optional — filter to a single workspace
  baseUrl?: string,         // testing only
  fetch?: typeof fetch,     // testing only
})

Success result

{
  ok: true,
  rows: Array<{
    date: 'YYYY-MM-DD',
    identity: string | null,        // workspace_id, or null for aggregate rows
    identityType: 'workspace_id' | 'aggregate',
    tool: string,                   // model name, or 'aggregate' for cost-only rows
    tokens_input: number,
    tokens_output: number,
    cost_usd: number | null,        // null only when cost_report failed and warning emitted
    session_minutes: 0,
    raw: { usage?: ..., cost?: ... }
  }>,
  meta: {
    via: 'cost_report+usage_report',
    pages_fetched: number,
    warnings: string[],             // e.g. 'cost_report failed: ...; rows will have cost_usd: null'
  }
}

Error result

{
  ok: false,
  error: string,
  errorType: 'auth' | 'rate_limit' | 'not_found' | 'network' | 'parse' | 'config',
}

errorType: 'auth' is fatal even if usage_report succeeded — your token is invalid for at least one of the endpoints, so the result would be incomplete.

Cost attribution heuristic

cost_report returns USD totals per workspace (and per description / cost_type, but the endpoint does not expose per-model spend directly). usage_report/messages returns token counts per workspace and per model.

To produce per-model cost rows, this collector distributes each (date, workspace) cost across that bucket's models proportional to total tokens (tokens_input + tokens_output).

cost_for_model = workspace_day_cost × (model_tokens / workspace_day_tokens)

This is the cleanest attribution available without finer-grained data from Anthropic's API. The sum of distributed costs equals the original cost_report total for that bucket exactly. If a cost_report row has no matching tokens (e.g. a web_search-only day), the collector emits a single row with tool: 'aggregate' and tokens_input: 0 — the cost is preserved, just not attributed to a specific model.

If you need different attribution (uniform across models, weighted by output-only, etc.), apply your own logic to the returned rows; the raw cost_report and usage_report payloads are preserved on row.raw.

Authentication

Both endpoints require an Admin API key that starts with sk-ant-admin-, created from the Claude Console under Settings → Admin keys. Standard inference keys (sk-ant-api-…) return 401 on the organization endpoints — this collector validates the prefix and rejects them up front with a clear hint.

Pagination

Both endpoints use a next_page cursor. The collector follows it transparently; you don't need to drive pagination yourself. Tested with 90-day ranges that span 4+ pages per endpoint — see test/pagination.test.js.

Errors

import {
  AnthropicSpendError,           // base
  AnthropicSpendConfigError,     // bad args, wrong key prefix, missing dates
  AnthropicSpendAuthError,       // 401/403 from either endpoint
  AnthropicSpendRateLimitError,  // 429
  AnthropicSpendApiError,        // other HTTP / parse failures
} from '@hameddk/anthropic-spend-collector';

Errors carry the original response body when available, never the request headers. Your API key is in the request — it is not echoed in errors.

Testing hooks

For testing only:

runCollector({
  ...,
  baseUrl: 'http://localhost:8080',  // override the Anthropic host
  fetch: customFetch,                // override fetch
})

Do not use these in production.

What this library does not do

  • Doesn't write to a database — return value is rows; persist them yourself.
  • Doesn't translate workspace IDs or emails to display names — your adapter does that mapping.
  • Doesn't fall back to local pricing tables — cost_usd is real or null.
  • Doesn't synthesize "per-developer split" rows when only aggregate data exists — what the API returns is what you get.

License

MIT © 2026 Hamed Sattari