documentation

Meter your API. Settle the actual.

Three packages, and a working metered service in about forty lines. One implements the x402 upto scheme on Hedera; one makes its receipts verifiable by anyone; one hands both to an AI agent.

01

Install

Add both packages alongside their peers. @x402/core and @hiero-ledger/sdk are peer dependencies you already have if you run an x402 service on Hedera.

shell
npm i x402-hedera-upto x402-hedera-receipts @x402/core @hiero-ledger/sdk

Requires a facilitator that supports upto on Hedera. No public one does yet — run your own (§04), which x402 encourages and Hedera’s docs ask for.

02

Client — sign a ceiling, pay nothing

The buyer registers the scheme and lets @x402/core answer 402s automatically. Paying costs one off-chain EIP-712 signature — no transaction, no gas, no HBAR.

client.ts
import { x402Client } from '@x402/core/client';
import { createUptoClientSigner } from 'x402-hedera-upto';
import { UptoHederaScheme } from 'x402-hedera-upto/upto/client';
import { PrivateKey } from '@hiero-ledger/sdk';

const signer = createUptoClientSigner(
  '0.0.BUYER',
  PrivateKey.fromStringECDSA(process.env.BUYER_KEY!),
  { network: 'hedera:testnet' },
);

const client = new x402Client().register('hedera:*', new UptoHederaScheme(signer));
// 402s are now answered with a signed authorisation, automatically.
The buyer account must be ECDSA with an EVM alias. ecrecover returns the alias, and it is the only address form HTS resolves. An ED25519 account cannot sign an authorisation.
03

Resource server — advertise a maximum, settle the actual

Advertise a ceiling in the 402. Do the work, then settle exactly what it consumed. The fifth argument is the whole scheme.

server.ts
import { x402ResourceServer } from '@x402/core/server';
import { UptoHederaScheme } from 'x402-hedera-upto/upto/server';

server.register('hedera:*', new UptoHederaScheme({
  defaultAssets: { 'hedera:testnet': { asset: '0.0.429274', decimals: 6 } }, // USDC
}));

// ...run the work, then charge for exactly what it consumed:
const actual = String(outputTokens * unitPrice);
await server.settlePayment(payload, requirements, undefined, undefined, { amount: actual });
//                                                                     ^^^^ the 5th argument
Settle before you serve. The reference implementation ships data on a verify pass and settles after; a verify-pass/settle-fail leaks the goods. Here a failed settlement returns 402 and the buyer keeps its money.
04

Facilitator — verify and settle

The facilitator submits capture() and pays the network fee, so the buyer never sends a transaction. It supports exact too, so it is a drop-in replacement — not a parallel universe.

facilitator.ts
import { x402Facilitator } from '@x402/core/facilitator';
import { createUptoFacilitatorSigner, accountEvmAddress } from 'x402-hedera-upto';
import { UptoHederaScheme } from 'x402-hedera-upto/upto/facilitator';

const upto = new UptoHederaScheme(
  createUptoFacilitatorSigner('0.0.FAC', key, { proxyContractId: '0.0.PROXY' }),
  { proxyContractId: '0.0.PROXY', chainId: 296,
    facilitatorEvm: await accountEvmAddress('0.0.FAC', 'hedera:testnet') },
);

new x402Facilitator().register(['hedera:testnet'], upto)
  .registerExtension({ key: 'offer-receipt' })
  .registerExtension({ key: 'meter' });
/supported — the difference
Blocky402schemes: exact · extensions: []Tallyschemes: exact, upto · extensions: offer-receipt, meter
05

Receipts & audit

The seller signs four documents — an offer and a price schedule before the work, a receipt and a meter reading after — and anchors them to HCS. Then anyone audits a settlement from the public Mirror Node, trusting nobody.

audit.ts
import { auditSettlement, buildLedger } from 'x402-hedera-receipts';

// one settlement, from HCS + the chain
const verdict = await auditSettlement(bundle, 'hedera:testnet');
//   → { ok, violations: ['arithmetic_fraud', ...], captured, claimed, units, unitPrice }

// score every seller on a topic, purely from public data — no database
const ledger = await buildLedger({ receiptsTopicId: '0.0.9557142', network: 'hedera:testnet' });

The verdict is a pure function of the seller’s signature and the on-chain Captured event — auditSettlementLogic() takes them directly, no I/O, and is covered by 56 offline unit tests.

06

The CLI — audit anything, trusting nobody

Audit a live topic with no install, no key, no account. It reads the public Mirror Node and returns the same verdict from any machine.

shell
npx x402-hedera-receipts audit --topic 0.0.9557142
npx x402-hedera-receipts audit --topic 0.0.9557142 --tx 0.0.X@169...  # one settlement, in full
07

Agents — pay and audit over MCP

Any MCP-capable agent — Claude Desktop, Cursor, the Hedera Agent Kit — gets three tools: tally_pay, tally_audit_settlement and tally_seller_reputation. The two audit tools need no key at all; they read the public Mirror Node.

claude_desktop_config.json
{
  "mcpServers": {
    "tally": {
      "command": "npx",
      "args": ["-y", "x402-hedera-mcp"],
      "env": {
        "HEDERA_NETWORK": "hedera:testnet",
        "BUYER_ID": "0.0.xxxxxxx",
        "BUYER_KEY": "<ecdsa-private-key-hex>"
      }
    }
  }
}
Paying is bounded, because the endpoint writes its own invoice. Whatever URL an agent is pointed at supplies the terms it would sign — so tally_pay refuses to sign above TALLY_MAX_CEILING_ATOMIC, refuses hosts outside TALLY_ALLOWED_HOSTS, and refuses private or link-local targets, resolving DNS first. Omit the buyer keys and only the two keyless audit tools load.

The same loop runs headless in this repo — an agent with a goal and a budget it will not cross:

shell
npm run agent:auto                       # honest run, $1.00 budget, six purchases
npm run agent:auto -- --cheat-at 3       # seller turns dishonest mid-run; it gets cut off
npm run agent:auto -- --min-honesty 0.9  # walk away from sellers the chain rates below 90%
08

Hedera rails, and why each is load-bearing

HTS + HIP-336
The asset, and token allowances as the funding rail.
the payment
HIP-376 facade
transferFrom spends against the caller’s allowance — what makes a Permit2-equivalent possible.
the settlement
Smart contracts
X402UptoProxy enforces the four MUSTs in consensus.
compliance
HCS
Signed offers, price schedules, meter readings — $0.0001 a message.
per-call receipts
Mirror Node
Key resolution, preflight, the Captured event, the whole audit.
zero-infra verifiability
HIP-991
Bonded dispute topic — an accusation costs a bond, charged by consensus.
sybil-resistant reputation
09

Requirements & what this does not do

  • Clients must be ECDSA accounts with an EVM alias. The long-zero form of an alias-bearing account does not resolve in HTS calls.
  • Settles HTS fungible tokens only (USDC). Native HBAR is unreachable from a contract via the ERC-20 facade; it needs the Hedera Account Service path (HIP-906).
  • It cannot prove the token count is truthful — the seller counts the tokens. What changes is that the count is signed, timestamped, and bound to a hash of what was delivered. The buyer holds the response, can recount, and then holds the seller’s signature on a false number.
  • Testnet only. The proxy is unaudited.
AUTHORISE A CEILING · PAY THE ACTUAL ✦ FIRST NON-EVM UPTO IN X402 ✦ SOFTWARE PAYS SOFTWARE · NO HUMAN IN THE LOOP ✦ AN OVERCHARGE IS ARITHMETIC ANYONE CAN CHECK ✦ RECEIPTS ON HCS · $0.0001 EACH ✦ AUTHORISE A CEILING · PAY THE ACTUAL ✦ FIRST NON-EVM UPTO IN X402 ✦ SOFTWARE PAYS SOFTWARE · NO HUMAN IN THE LOOP ✦ AN OVERCHARGE IS ARITHMETIC ANYONE CAN CHECK ✦ RECEIPTS ON HCS · $0.0001 EACH ✦