# BSVKey usage receipts (v2)

A signed, content-addressed receipt for every metered inference call that lets a
client audit **both the meter and the charge, offline, with nobody watching**.

## What the receipt lets you prove, without asking the broker

1. **This is my channel.** channel binding + a signature that recovers to the broker key.
2. **It was not counted before.** a monotonic per-channel `seq` (no gap, no replay).
3. **The totals add up.** running `cumSats`/`cumTokens`, bounded by the funded amount.
4. **The token count is real.** the meter is a published, deterministic tokenizer
   run over the *exact bytes* you exchanged, so you recompute it from your own
   system/prompt and the completion you received.
5. **The charge is right.** an integer, published formula over those tokens and a
   pinned rate card, so you recompute the exact sats. You can never be charged
   more than that; being charged less (a channel cap) is allowed.

## The signed body (v2)

| field | meaning |
|---|---|
| `v` | `bsvkey.usage-receipt/2` |
| `channelId` | the channel this call drew down |
| `seq` | monotonic per channel, 1-based |
| `model` | model actually run |
| `meter` | pinned tokenizer id, `bsvkey-meter/1` |
| `pricebookId` | pinned rate card id |
| `inputTokens`, `outputTokens` | published-meter counts over the exact bytes |
| `inputDigest`, `outputDigest` | `sha256` of the exact metered input / completion |
| `rateInPer1k`, `rateOutPer1k` | retail sats per 1k tokens used for this charge |
| `webSearchSats` | itemized web-search fee (0 if none) |
| `discountPct` | your tier discount, integer percent |
| `minChargeSats` | floor so tiny calls never bill 0 |
| `sats` | sats actually charged |
| `cumTokens`, `cumSats` | running totals over the channel, after this call |
| `fundedSats` | the channel's on-chain funded amount |
| `timestamp` | ISO 8601 |

Credentials (not signed content): `claimId` = `0x` + `sha256(canonical(body))`;
`signature`, a compact recoverable Bitcoin Signed Message over `claimId`;
`brokerPubKey` (carried, not trusted, verification recovers its own). Pin the
broker key from **`GET /v1/receipt-key`**.

## The meter

`bsvkey-meter/1` is BSVKey's own deterministic billing tokenizer. It is **not** a
claim to reproduce Anthropic's or xAI's proprietary tokenizer; it is the unit you
are billed on, and it is fully reproducible:

- `inputText = (system ? system + "\n\n" : "") + prompt`
- `inputTokens = meter(inputText)`, `outputTokens = meter(completion)`
- `meter(text) = max(ceil(len/4), ceil(words*1.3), 1)` (rounds up)

The provider's own token usage is used only as the broker's internal cost signal
(with a margin alert), never as the price. If a vendor ever publishes a
byte-exact tokenizer, that ships as a new `meter` id; old receipts are never
retokenized.

## The charge (frozen, integer-only)

```
tokenSats = ceil((inputTokens*rateInPer1k + outputTokens*rateOutPer1k) / 1000)
gross     = tokenSats + webSearchSats
sats      = max(minChargeSats, ceil(gross * (100 - discountPct) / 100))
```

## Verifying (offline, no broker round-trip)

Per receipt: `claimId` recomputes; the signature recovers to the pinned broker
key; recompute `inputTokens`/`outputTokens` and `inputDigest`/`outputDigest` from
your own system/prompt and the completion (the meter); recompute `sats` with the
formula above (you may be charged `<= sats`, never more). Across the channel:
`seq` has no gap/replay, `cumSats`/`cumTokens` reconcile, and `cumSats <= fundedSats`.

Reference verifier: `@bsvkey/x402-bsv-client` →
`import { verifyReceipt, verifyReceiptChain, verifyMeter, verifyCharge } from '@bsvkey/x402-bsv-client/usage-receipt'`.
The MCP server (`@bsvkey/inference-mcp`) runs these automatically and returns
`receiptVerified` / `meterVerified`.

## What this proves, and does not

- **Proves:** the broker signed these exact numbers (non-repudiable), the token
  count is the published function of the exact bytes you exchanged, the charge is
  the published function of those tokens, none were double-counted, and the totals
  stay within what you funded.
- **Does not prove:** that `bsvkey-meter/1` equals the model provider's internal
  token count (it is BSVKey's own published unit), nor that `delivered` is
  correct. The meter is now verifiable; whether our unit matches a vendor's is a
  measured, published basis, not a claim.
