seq 001 · INDEPENDENT ENFORCEMENT AND EVIDENCE FOR AGENT PAYMENTS

Authorize first.
Prove everything.

Counterroll puts a deny-by-default policy gate between every AI agent and every x402 payment. It evaluates each request against your policy, fails closed on anything it cannot safely evaluate, and returns a signed, hash-chained receipt for every policy-evaluable decision — before settlement. x402 today, running live on Base; a rail-neutral evidence model designed for what comes next.

Deny by default Per-transaction and rolling-window caps Payee, network, and asset controls Independently verifiable evidence
quickstart.ts — live against the public sandbox, no signup
import { Counterroll, usdc } from '@counterroll/sdk';

// Public sandbox: one published key, bundled demo agents, a live URL.
const cr = new Counterroll({ apiKey: 'qm_sandbox_publicdemo_v1' });

const ok = await cr.check({ agent: 'research-bot', to: 'openai', amount: usdc(1) });
const no = await cr.check({ agent: 'research-bot', to: 'openai', amount: usdc(500) });

console.log(ok.approved, no.reasons); // true  ['per_tx_cap_exceeded']
console.log(no.receipt!.hash);        // signed + hash-chained — verify it yourself
Run the quickstart above against the live sandbox now — no account, no key request. A production or embedded pilot is a conversation, not a gate.
WHY NOW

x402.org reported more than 75 million transactions and $24 million in volume over the prior 30 days (observed 2026-07-14). Cloudflare Agents now supports x402 payments directly. The payment rail is scaling; teams need authorization and audit evidence before autonomous spend reaches production.

Market context observed 2026-07-14 — protocol signals, not Counterroll customer or revenue claims.
seq 002 · WHAT YOUR TEAM GAINS

Autonomy without ungoverned spend

A wallet limit can cap an amount. Counterroll records which agent asked, which policy was applied, why the decision was made, and whether the evidence still verifies later.

01 / CONTROL

Make policy executable

Express per-payment and rolling-window caps plus payee, network, and asset rules. No matching policy, ambiguous input, or malformed payload means DENY.

02 / EVIDENCE

Keep the reason, not just the result

Every policy-evaluable APPROVE and DENY preserves the applied policy snapshot—or its absence—plus decision reasons, hash-chain link, and organization signature.

03 / INDEPENDENCE

Keep proof independent of settlement

Policy and audit history live outside any one facilitator. Swap the upstream x402 facilitator without rebuilding your governance layer or surrendering the ledger — x402 today, a rail-neutral evidence model designed for what comes next.

seq 003 · HOW IT WORKS

check → receipt → chain → verify

1 · check()
Your agent asks first. One call carries the payee, amount, network, and asset of the x402 payment it wants to make. Deny by default: no matching policy, an ambiguous rule, or a malformed payload all come back DENY. Nothing approves on an error path.
2 · signed receipt
Every policy-evaluable decision returns an attestation signed with your org's Ed25519 key, carrying the exact policy snapshot it was evaluated against. Unknown agents, malformed payloads, and replayed nonces fail closed and are recorded separately because they cannot be represented safely on the chain.
3 · hash chain
Each receipt stores the SHA-256 of the one before it, and the ledger is append-only — enforced in code, in review, and by a Postgres trigger that raises on UPDATE or DELETE. History can be extended, never edited.
4 · verify yourself
qm.verify({ publicKey }) pulls the raw rows and re-derives the entire chain locally: every hash recomputed, every signature checked against a key you pinned out-of-band. An attacker who rewrote the database and re-signed it with a fresh key passes the server's own check — and fails yours.
APPROVE · research-bot → openai · $1.00 · chain genesis (seq 1)
{
  "decision": "APPROVE",
  "denyReasons": [],
  "attestation": {
    "id": "att_29240a122a59b0c63e0749d16008ded9",
    "organizationId": "org_sandbox",
    "seq": "1",
    "agentId": "research-bot",
    "policyId": "policy_sandbox_research",
    "decision": "APPROVE",
    "payTo": "openai",
    "amount": "1000000",
    "network": "eip155:8453",
    "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
    "policySnapshot": { "perTxCap": "5000000", "windowCap": null, … },
    "requirements": {  },
    "eip3009Nonce": "c31d1ab50d697dd6b7a1973632ca2a93d8e247fa442e830fef57d7c1b4bfcac6",
    "payloadSha256": "53e3bc4b0d3735baf9d8e1ab3642bfbc4626366b68d23fa543246cbef575c56b",
    "prevHash": "GENESIS",
    "hash": "e0c9a5964716f7b6a0cb71e6275601e4a00524bc43d40a15e6dbc547d9c15082",
    "signature": "23106faca39847ab2b2cec5c3f428760214b42e395754d3ebf576189d258ff83926059aeb7515ea5c18a0d4b85c45c9e0383191f42faf0c3c38b78a9544f0109",
    "createdAt": "2026-07-18T22:16:00.214Z"
  }
}
DENY · research-bot → openai · $500.00 over a $5.00 per-tx cap (seq 2)
{
  "decision": "DENY",
  "denyReasons": ["per_tx_cap_exceeded"],
  "attestation": {
    "id": "att_abbfe9ca99df62898d204f1c520ac181",
    "organizationId": "org_sandbox",
    "seq": "2",
    "agentId": "research-bot",
    "policyId": "policy_sandbox_research",
    "decision": "DENY",
    "payTo": "openai",
    "amount": "500000000",
    "network": "eip155:8453",
    "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
    "policySnapshot": { "perTxCap": "5000000", "windowCap": null, … },
    "requirements": {  },
    "eip3009Nonce": "9641901101b3259d4145bd6a594571bd45543051aa2585d1a0fd9755584b43b3",
    "payloadSha256": "9954c6456edcc97c62984f3c425de8d7fb50daa495c845553e29484757596e95",
    "prevHash": "e0c9a5964716f7b6a0cb71e6275601e4a00524bc43d40a15e6dbc547d9c15082",
    "hash": "dbf1b4efee0ff1baf6e76dce561627452f25affecae65d1735fc2ae0eb97c616",
    "signature": "c71dc37a66c2b7f933710bf452e41e72b2210d466b69b3eefaabcf84f9830610a07f75b98511feecd0a42545ec86da929c916752d15ffb518755013b2b8e2903",
    "createdAt": "2026-07-18T22:16:00.670Z"
  }
}

Rows 1 and 2 of Counterroll's live public sandbox chain (org_sandbox), pulled read-only from the deployed API on 2026-07-23. Every hash and signature is real: the DENY's prevHash is the APPROVE's hash, and both signatures verify against the org's published anchor e9d3619e…b6d1. Run qm.verify({ publicKey }) to re-derive the whole chain yourself against that key — 132 signed rows the day this was captured, and append-only since. Note what the deny costs you: nothing moved, and you still got a receipt.

seq 004 · PRODUCTION + EMBEDDED PARTNERS

Prove it in production. Then distribute it.

The SDK is public and self-serve — start there. Beyond it, Counterroll supports two focused partner paths: teams putting one governed payment flow into production, and platforms embedding the same independent control across many customers. Both begin with a real integration surface—not a generic AI demo.

01 · PRODUCTION DESIGN PARTNER

Govern one high-stakes agent flow.

Best for enterprises and infrastructure teams with a named technical owner, a production path, and a policy they refuse to ship without. Outcome: enforced decisions plus independently verifiable evidence.

02 · EMBEDDED GOVERNANCE PARTNER

Make policy and proof part of your platform.

Best for wallets, facilitators, agent runtimes, marketplaces, and cloud platforms that want independent governance without rebuilding policy and signed evidence. Outcome: one integration serving many downstream customers.

STRONG FIT

  • Your agent will initiate x402 payments or paid tool calls.
  • Security or finance needs enforceable limits and decision evidence.
  • You want policy independent of one wallet or facilitator.
  • You have a production path and a technical owner.

NOT THE PRODUCT

  • A consumer checkout or human expense card.
  • A wallet, custodian, payroll system, or settlement rail.
  • A promise that every autonomous payment should be approved.
  • A dashboard replacing cryptographic verification.

Bring one real payment flow or integration surface.

We will use it to test the three questions that determine whether Counterroll earns a place in your stack—or inside the product you distribute.

1 · EnforcementCan the policy fail closed on the exact agent, payee, amount, network, and asset?
2 · EvidenceCan your team re-derive the decision chain and verify signatures without trusting our API?
3 · ArchitectureCan the control remain useful if you change wallets, facilitators, or settlement infrastructure?
The email opens with five useful prompts, including the partner motion. No generic “tell us more” form and no invented urgency.
Why not rely only on wallet spending limits?

Wallet limits are useful and Counterroll does not replace them. Counterroll adds an organization-scoped decision layer: agent identity, policy assignment, payee and rail restrictions, rolling-window context, explicit deny reasons, and a signed policy snapshot preserved in an independently verifiable chain.

Does Counterroll hold funds or settle payments?

No. Counterroll authorizes, attests, and records. Approved x402 traffic is proxied to the facilitator your organization configures. Settlement remains upstream.

What happens if the Counterroll database is rewritten?

The SDK can pull raw rows and locally re-derive every hash and signature against an organization public key pinned outside the database. A rewritten chain signed with a different key fails that client-side verification.

What does a DENY look like to the agent?

A DENY is a successful policy evaluation, not an exception. The agent receives approved: false plus machine-readable reasons such as per_tx_cap_exceeded; the decision is retained as evidence before money moves.

seq 005 · WHY IT EXISTS

Built for the questions that follow an incident.

We audit Counterroll the way an attacker would, before each layer ships. Two findings from those audits shaped the architecture. Both are in the git history.

Finding 001 — the double-spend race

audit 2026-07-05 · fixed in commit 3a03a17

The window cap said $200 a day. The first build read the agent's window spend, evaluated the policy, then appended the attestation — three steps, no lock. Two near-cap requests arriving at once would each read the same "spent so far," each pass evaluation, and both get approved: window overspent, with two individually valid receipts to show for it. A textbook time-of-check/time-of-use race, in the one component whose job is making spend limits mean something.

The fix put the replay check, the window read, the evaluation, and the append inside a single transaction holding the org's row lock — and the regression test now races concurrent near-cap requests to prove it. Nothing evaluates outside that transaction.

Finding 002 — the wallet that impersonated an agent

audit 2026-07-08 · fixed in commit 2b76acc

For drop-in x402 compatibility, the gateway once accepted a fallback: if the agent-signature headers were missing, resolve the agent from the payment's EIP-3009 from wallet. Read that from an attacker's chair. The API key authenticates the tenant, not the agent — so anyone holding the org key could attribute spend to any agent in the org, minting APPROVE attestations and draining that agent's window budget, with no proof of possession of the agent's key. (Never settlements — the EIP-712 signature still fails upstream.)

The gateway now requires the agent's Ed25519 request signature by default and rejects the wallet path with 401 before any ledger write; the fallback survives only as an explicit per-org opt-in, documented as the tradeoff it is.

A tamper-evident ledger is only as good as the code that writes to it. The audits continue; the relevant fixes, tests, and threat-model decisions are available during technical diligence.

seq 006 · INDEPENDENCE

The system that authorizes should not be the only system you must trust.

Counterroll moves no money: v1 authorizes, attests, and records, and settlement is proxied to whichever x402 facilitator you configure. A governance layer is only credible if it can say no to the rail itself — so it is built to be checked without trusting us.

NO CUSTODY

We never move the money.

Counterroll holds no funds and no settlement keys. Approved x402 traffic is proxied to your configured facilitator, and your receipts ride in the standard x402 extensions field — swap facilitators without touching your ledger.

NO SILENT FALLBACK

Failure closes, never opens.

Deny by default, everywhere: no matching policy, an ambiguous rule, or a malformed payload all fail closed. An unavailable policy service cannot quietly become permission to pay, and the wallet-impersonation fallback stays off unless an org explicitly opts in.

No trust required: qm.verify({ publicKey }) re-derives every hash and signature locally against a key you pin out-of-band — e9d3619e…b6d1 for the public sandbox. A rewritten, re-signed database passes our server's own check and fails yours.