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

@herrhelms/openai-token-cost-reports

v2.1.1

Published

Track OpenAI API token usage per Paperclip company, store daily rollups, render a dashboard, and export a monthly CSV for token-based billing. Pricing table covers GPT-5.5 / GPT-5.4 family and GPT-5.3 Codex.

Downloads

259

Readme

OpenAI Token Cost Reports

A Paperclip plugin that turns raw OpenAI API consumption into a token-priced client invoice.

Track OpenAI API token usage per Paperclip company, see who burned what across agents and models, and export a client-facing monthly invoice CSV in the currency you bill in. Daily FX snapshots and configurable margin.

Designed for operators on the OpenAI API who want to bill clients in a real currency without losing visibility on what API list price would have been.


Install

# From inside a Paperclip-enabled environment with the CLI installed:
paperclipai plugin install @herrhelms/openai-token-cost-reports

# Verify the install
paperclipai plugin list
# expect: key=openai-token-cost-reports  status=ready  version=2.1.1  id=<uuid>

The host runs the plugin's database migrations automatically and registers the dashboard + settings page slots. No additional configuration is required to install — pricing and currency are set per-company in the Settings page after install.

The npm package is scoped (@herrhelms/…) but the in-app plugin key is not — that's a Paperclip-host convention. To uninstall, use the unscoped key:

paperclipai plugin uninstall openai-token-cost-reports

paperclipai plugin list prints the unscoped key next to each install, so you can always discover it from the host.

Requirements

  • Paperclip host with @paperclipai/plugin-sdk >= 2026.609.0 available.
  • Node.js 22+ on the host that runs the plugin worker.
  • Outbound HTTP access from the host to https://open.er-api.com (used by the hourly FX-rate job).
  • The plugin must be granted the capabilities listed in Capabilities. The Paperclip host prompts the operator on install.

Where it shows up after install

| Surface | Where to find it | What's there | | --- | --- | --- | | Dashboard | /$COMPANY_HANDLE/monthly-report-openai (in the company sidebar) | Usage KPIs, per-model bars, per-agent table, daily chart, monthly CSV export | | Settings | /$COMPANY_HANDLE/company/settings/instance/plugins/<install-uuid> | Free-form pricing matrix (Add / Edit / Delete rows), margin, billing currency, FX-rate status, snapshot history timeline, cost adjustment multiplier |

The <install-uuid> is shown by paperclipai plugin list after install.


Quick start

After install, open the Settings page for any company:

  1. Pick a billing currency (10 supported). The hourly FX job will fetch today's USD→target rate and store one row per (day, currency).
  2. Set a margin % — the percentage you add on top of cost when invoicing the client.
  3. (Optional) Adjust per-model rates or add new model rows. Defaults are seeded from OpenAI's published list prices for the GPT-5.4 / 5.5 family, GPT-5.3 Codex, o3 / o4 reasoning models, ChatGPT (chat-latest), and computer-use-preview. For any model id you see the host emit that's missing from the table, click "Add rate" — type the exact model string and set input/output rates. The dashboard's "no rate set" chip surfaces these in real time.
  4. Backfill historical events. The Settings page has a Backfill from history button (for the current period) and Backfill all history (since the company's first cost event). The plugin reads directly from the host's public.cost_events table via the coreReadTables whitelist, so historical data from before the plugin install is available immediately.

Then open /$COMPANY_HANDLE/monthly-report-openai — the dashboard reflects the configuration within a second.


What it does

  • Subscribes to cost_event.created and agent.run.finished and writes one row per event into a private usage_events table. Keys are cost_event:<id> for cost events so the live subscription and Backfill from history action share a keyspace and dedupe idempotently.
  • Rolls up to usage_daily every 15 minutes per company.
  • Fetches a daily USD→target FX rate from open.er-api.com and stores one row per (day, currency) in fx_rates. Only fetches for currencies at least one company has configured.
  • Cleans up automatically when a company is archived (purges usage_events, usage_daily, pricing_config, currency state).

Dashboard at /$COMPANY/monthly-report-openai

  • 5 KPI cards: total tokens, input, output, cost (pre-margin), price (chargeback).
  • Per-model horizontal bar chart with native-currency cost and price.
  • Per-agent table with totals + per-model breakdown (Runs / Input / Output / Cost / Price columns).
  • Daily volume column chart — input + output stacked, peak label.
  • Status chips for ingest health and FX staleness next to the title.

Settings at /$COMPANY/company/settings/instance/plugins/<install-uuid>

  • Per-model rates (USD per 1M input / output) for the GPT-5.5 / GPT-5.4 / GPT-5.3-codex families.
  • Margin %.
  • Billing currency (10 currencies), with Refresh FX now and a status line showing the active rate.

The dashboard inherits the host's Paperclip theme (light/dark, shadcn-style cards) by referencing host CSS variables directly.


Billing math

For each event with model m, input tokens i, output tokens o:

list          = (i × pricing[m].input + o × pricing[m].output) / 1_000_000     # USD, raw OpenAI
your_cost     = list × effective_input_rate_multiplier                          # USD, post-adjustment
client_price  = your_cost × (1 + margin.percent / 100)                          # USD, post-margin
row.price     = client_price × fx_rate(month_end_day, currency)                 # Native currency

The dashboard surfaces all three tiers explicitly. List price is what an API user would pay at OpenAI list. Your cost is what the operator effectively owes (post-adjustment). Client price is what the customer is billed (after operator margin). Per-model and per-agent cards show the same three numbers per row so reconciliation is explicit.

The monthly CSV emits only row.price — operator-internal numbers (list, multiplier, margin) stay off the file you send to the client.


Cost adjustment multiplier

The plugin has one knob: effective_input_rate_multiplier, default 1.0 (full list price). It scales the entire list price (input + output); the variable name is a legacy artifact from earlier versions where it applied to input only.

Useful when:

| Scenario | Multiplier | Why | | --- | --- | --- | | Default | 1.0 | Client pays full API list price | | High cache-hit ratio | 0.5 | OpenAI's cached input is ~10% of standard; if half your tokens are cache hits, the effective rate is roughly half — pick a value matching your workload | | Custom contract | any value in (0, 1] | Operator-specific arrangement |

Saving pricing in Settings replaces the active snapshot and reprices every event in this company — past and future — so changing the multiplier is reflected across the full report immediately. To preserve period-by-period historical overrides, append snapshots explicitly via the addPricingSnapshot action (advanced).


Monthly CSV export

GET /api/plugins/openai-token-cost-reports/api/export/monthly.csv?companyId=...&from=YYYY-MM-DD&to=YYYY-MM-DD

Columns: period, month_start, month_end, model, input_tokens, output_tokens, total_tokens, currency, price.

Multi-month exports include a model = TOTAL row at the end of each month section. Filename: usage-<company-slug>-<from>-<to>-<currency>.csv.


Capabilities

The Paperclip host gates each of these on install. All are required for the plugin to function correctly.

| Capability | Why it's declared | | --- | --- | | events.subscribe | Receive cost_event.created, agent.run.finished, company.updated | | costs.read | Gates delivery of cost_event.created | | agents.read | Resolve agent display names for the per-agent breakdown | | companies.read | Resolve company name for the CSV filename slug | | database.namespace.migrate / .read / .write | Private SQL namespace | | plugin.state.read / .write | Per-company pricing + currency config in ctx.state | | jobs.schedule | rollup-daily (15 min) and fetch-fx-daily (hourly) | | api.routes.register | Scoped CSV export route | | ui.page.register | Dashboard page slot | | instance.settings.register | Settings page slot | | http.outbound | Daily FX fetch from open.er-api.com |


Reference

Data model

Private SQL namespace via ctx.db (plugin_openai_token_cost_reports_5d9ad52d0e):

  • usage_events(source_event_id PRIMARY KEY, company_id, agent_id, model, raw_model, provider, source, input_tokens, output_tokens, cached_input_tokens, cost_cents, occurred_at, day TEXT) — append-only event log. raw_model preserves the literal model id while model holds the normalized key; provider and source (api / subscription) drive the cost split.
  • usage_daily(company_id, day TEXT, model, input_tokens, output_tokens, PRIMARY KEY(company_id, day, model)) — rolled-up daily totals.
  • pricing_config(company_id PRIMARY KEY, json TEXT) — kept for historical compatibility; live pricing lives in ctx.state.
  • fx_rates(day, currency, rate, source, fetched_at, PRIMARY KEY(day, currency)) — daily USD-base FX snapshots.

Migrations: migrations/001_init.sql, migrations/002_costs_overview.sql, migrations/003_fx_rates.sql.

Core-read tables (declared in manifest): cost_events — used by the backfill action to import history from before the plugin install. Filtered by provider = 'openai'.

Plugin state keys

  • Company-scoped: pricing-config (rates + margin), currency-config (selected billing currency).
  • Instance-scoped: active-currencies (string[] — drives which currencies the daily fetcher requests).

Data handlers (registered on ctx.data, called from UI via usePluginData)

  • getDailyUsage({ companyId, from, to }) — daily rows with cost/price in USD and native currency. Drives the dashboard daily chart + KPIs.
  • getMonthlySummary({ companyId, from, to }) — calendar-month rollups (legacy aggregate, kept for the API surface).
  • getPerModelForRange({ companyId, from, to }) — per-model breakdown with cost → price in native currency.
  • getPerAgentBreakdown({ companyId, from, to }) — per-agent + per-model with runs, tokens, cost, price.
  • getPricing({ companyId }) — bare PricingConfig.
  • getCurrencyConfig({ companyId }){ currency, supported }.
  • getFxStatus({ companyId }) — current rate, day, source for the company's currency.
  • getIngestStats({ companyId }) — total + 24h ingest counts for the dashboard health chip.

Actions (registered on ctx.actions, called from UI via usePluginAction)

  • setPricing({ companyId, config })
  • setCurrencyConfig({ companyId, currency }) (best-effort prefetches FX)
  • refreshFxNow({ companyId })
  • backfillFromCostEvents({ companyId, from, to })
  • backfillAllHistory({ companyId })

API routes

Mounted under /api/plugins/openai-token-cost-reports/api/*:

  • GET /export/monthly.csv?companyId=...&from=...&to=... — streams the client-facing monthly CSV. auth: board.

Naming and forking

Three names refer to the same thing; keep them aligned across npm, the host, and the database:

| Surface | Value | Where it's set | | --- | --- | --- | | npm package name | @herrhelms/openai-token-cost-reports | package.json name | | In-app plugin key | openai-token-cost-reports | src/manifest.ts id | | Private DB namespace | plugin_openai_token_cost_reports_5d9ad52d0e | derived by the host as plugin_<slug-with-underscores>_<sha256(slug)[0:10]> |

The 5d9ad52d0e suffix is the first 10 hex characters of sha256("openai-token-cost-reports"). Forks that rename the plugin must regenerate this suffix in every migration file — the host computes the namespace from the slug at install time, and a stale suffix in the SQL makes every migration fail with "schema X does not exist". A one-liner to recompute:

node -e "console.log(require('crypto').createHash('sha256').update('openai-token-cost-reports').digest('hex').slice(0,10))"

Then sed -i '' 's/plugin_openai_token_cost_reports_5d9ad52d0e/plugin_<new_slug>_<new_hash>/g' migrations/*.sql. Tests do not catch this — the SQL runs at host install time, not at plugin build time.


Build from source

For developers and forks. Standalone plugin package; built against @paperclipai/plugin-sdk. TypeScript throughout; React + inline CSS for the UI (no Tailwind); esbuild for both the worker and the UI bundle.

pnpm install
pnpm typecheck       # base + tests/ (chained via tsconfig.test.json)
pnpm test            # 28 unit tests on the pure math + manifest
pnpm build           # emits dist/manifest.js, dist/worker.js, dist/ui/index.js

# Install the locally built copy into the Paperclip host on this machine:
paperclipai plugin install -l .
paperclipai plugin list

For a clean reinstall during development:

paperclipai plugin uninstall openai-token-cost-reports --force
paperclipai plugin install -l .

See docs/PRODUCTION-INSTALL-CHECKLIST.md for a verification flow to run after the first install on a non-dev Paperclip host.


License

MIT — see LICENSE.

Changelog

See CHANGELOG.md. The format follows Keep a Changelog and the project follows Semantic Versioning.