AI spend and subscriptions
What you were billed and what you were metered, recorded as two numbers and never added into one.
One blended AI total reconciles against nothing
Ask what AI costs the business this month and the answer is a number with a shrug attached. Some of it is monthly subscriptions on the corporate card, one per tool, signed up for by whoever needed them first. Some of it is metered API usage on an account somebody in engineering owns. Some of it is a seat still being paid for by a person who left in March.
Most tooling makes that worse, because it produces one confident total. Add a £120 subscription to £340 of estimated tokens and you get £460, a figure that appears nowhere else in your business, on no vendor invoice and in no gateway. On a spend question somebody always checks.
How it works
- 01
Register the subscription against a named owner
Each entry names a vendor, a tool, a team and an owner email, normalised so the same service registered twice does not become two entries. Reads need viewer rank, writes need operator rank, and every mutation is audited. - 02
Map your finance export onto the import template
Ten required CSV headers: externalId, vendor, tool, team, kind, currency, amount, chargedAt, periodStart and periodEnd. ownerEmail and subscriptionId are optional. Upload or paste the CSV, validate it and review the preview before committing. The API accepts the same fields as JSON. - 03
Reject an import rather than half-apply it
An unrecognised column, a missing required one, a credential in metadata or an invalid period fails validation. Each import accepts up to 1,000 lines. CSV file uploads are capped at 2 MB (2,000,000 bytes); the API caps the JSON request body at 2 MiB (2,097,152 bytes). One line reusing an existing identity with different data rolls the whole batch back. - 04
Report billed and metered side by side
Subscription and API amounts are reported per currency with their evidence counts, and nothing is converted: a euro charge is reported in euros. Actual API invoices are never added to token-price estimates, and a report that hit its row cap says so on the result. The same figures reach an agent over MCP under the same team scope, to a caller holding an explicit report grant.
You map the charge lines out of your own finance export onto the import template, and the dashboard validates the file and shows you the parsed lines before anything is written.
- externalId
- vendor
- tool
- team
- ownerEmail optional
- subscriptionId optional
- kind
- currency
- amount
- chargedAt
- periodStart
- periodEnd
File totals before duplicate detection. Nothing is written yet.
| invoice line | tool / team | kind | amount | charged |
|---|---|---|---|---|
| INV-2026-09-001 | chat assistant Marketing | subscription | 1,240.00 USD | 2026-09-01 |
| INV-2026-09-002 | coding agent Engineering | api | 806.40 USD | 2026-09-01 |
| INV-2026-09-014 | meeting notetaker Sales | subscription | 276.50 GBP | 2026-09-01 |
Repeat imports are recognised by team, source and invoice-line identifier, so re-importing an export you already loaded skips the lines it already holds rather than doubling the bill.
- A billing credential
- A login to a vendor console
- A connector for somebody to review
Column names and bounds are the product’s own; the lines are illustrative. Timestamps are UTC, kind is subscription or api, currency is three uppercase letters, and an import is capped at 1,000 lines and 2 MB. Import charge lines once, never a bill total alongside the lines that make it up.
Billed and metered stay two numbers
A subscription invoice is a fact about money that has already moved. A token-price estimate is a calculation over observed traffic against a price table. Only one of them will ever appear on a bank statement, so adding them produces the single figure an executive asks for and a number nobody can trace to a source document. Currencies are held apart for the same reason: a converted total embeds a rate and a date the report would have to defend.
- Billed
- What an invoice line says, per currency, with its source, charge date and service period. Retained without proration: a period straddling a reporting window is not sliced.
- Estimated
- What metered traffic through the gateway is calculated to have cost, recorded separately and never folded into the billed figure.
- Unknown
- A source nobody has connected. Coverage is its own axis, so an unconnected source reads as unknown rather than as zero, because those look identical on a chart and mean opposite things.

Sample data in the real Token Observe interface, recorded from a local evaluation with a temporary database, a mock provider and one request. No live provider key was used. The product stamps its own demo rows SYNTHETIC EVALUATION DATA in these pixels.
Importing the same invoice twice adds nothing
Finance exports get run more than once: somebody re-checks a figure, a scheduled job retries after a timeout, two people import the same file on the same afternoon. A ledger that treats each of those as new charges doubles the total and takes a while to be noticed.
Identity is team, source and external id, and it is expected to be stable across exports. An identical reimport adds no spend. One that reuses an identity with different data is a conflict rather than an update, because the same reference carrying a different amount is something a person should look at. Corrections are issued as separately identified credit lines rather than by editing history.
POST /api/estate/charges/import
{
"source": "finance-export",
"lines": [{
"externalId": "invoice-2026-09-line-1",
"vendor": "anthropic",
"tool": "claude",
"team": "Engineering",
"ownerEmail": "owner@example.com",
"kind": "subscription",
"currency": "GBP",
"amount": 120,
"chargedAt": "2026-09-01T00:00:00Z",
"periodStart": "2026-09-01T00:00:00Z",
"periodEnd": "2026-10-01T00:00:00Z"
}]
}Each line closes off an assumption a reader would otherwise carry into a proof of concept.
What this does not doWhat this leans on
Approved and unauthorised AI
Approved, prohibited or unknown, so the subscriptions you already pay for stop arriving in the seat-spend report.
Spend controls
Hard USD ceilings, per-minute rate limits and a kill switch, all decided before the request leaves your network.
AI conversation evidence
What the AI was asked and what it returned, redacted before it is stored and bounded before it is kept.
Where this comes up
What do I have to supply to import a month of spend?
Map the charge lines from your finance export onto the dashboard's import template. It has ten required columns and two optional ones, ownerEmail and subscriptionId. Use the exact headers shown above. Upload or paste the CSV, validate it, then review the preview before committing. You need no vendor billing credential or vendor console login; your organisation decides how to review the data you import.
What happens if the same invoice is imported twice?
Nothing is added. Import identity is team, source and external id, and an identical reimport is recognised and ignored. The same identity arriving with different data is a conflict rather than an update: the import errors and rolls back completely, because the same reference carrying a different amount is something a person should look at. Corrections are issued as separately identified credit lines.
Will it find AI subscriptions nobody told us about?
Not from invoices, which list only what they list. Unregistered services surface through the observation side of the product instead, and that is evidence about a destination rather than proof of a subscription: a hostname without a verified owner cannot establish whose subscription it is. Treat the register as the record you build deliberately and observations as leads to investigate.
Prefer to ask a person? Write to James
Bring us the agent you are least comfortable with.
Create a cloud account and workspace. No card or server installation. Model calls and Google BigQuery scans can incur separate provider charges.