documentation

How 402.fhe works

API marketplaces today require trust in the operator. The platform can see how much every buyer has deposited, how much every merchant has earned, and which APIs are being called most. For autonomous AI agents transacting at scale, that's sensitive business intelligence leaking by design.

402.fhe fixes this with Zama fhEVM. Buyer balances and merchant revenues are stored as ciphertexts on-chain. The operator runs the infrastructure but is cryptographically blind to the financial data — not a policy claim, a math claim.

01Merchants list APIs with cleartext prices.
02Buyers deposit USDC once — balance is encrypted on-chain.
03AI agents pay per call via x402 HTTP payments — no gas, just a wallet signature.
04Calls accumulate as signed proofs off-chain. Settlement is one transaction for N calls.
05Either party settles at any time. No cooperative close, no dispute window.

Overview

nonegas per API call
zerooperator visibility
up to 50calls per settle tx
FHEencryption

How a call happens

01

Deposit

Buyer deposits USDC once. The balance is wrapped as an encrypted euint64 on-chain — only the buyer can decrypt it via the Zama KMS.

02

Request

Buyer hits the API endpoint. Middleware issues a 402 challenge containing the apiId and a random nonce.

03

Sign & Pay

Buyer signs the nonce with their wallet key and retries with an X-Payment header. No gas. No transaction. Just a signature.

04

Proof stored

Middleware verifies the signature, runs canAfford as a gas-free eth_call, then stores the signed proof off-chain. The API response is returned immediately.

05

Settle

Either the buyer or merchant triggers settlement at any time. The middleware calls batchSettle — one transaction for N accumulated calls. The FHE mux deducts from the buyer's encrypted balance and credits the merchant's encrypted revenue without decrypting either.

FHE guarantee

Balances and revenues live on-chain as euint64 ciphertexts. The operator cannot run a query that returns plaintext values.

The FHE mux inside batchSettle deducts from the buyer balance and credits merchant revenue — all without decrypting either value. Every update is gated on an encrypted ebool (affordable flag). If the buyer can't pay, nothing changes — and the operator can't tell either way.

Withdrawals are fully self-serve. The contract marks every balance and revenue update as publicly decryptable via the Zama KMS. When withdrawing, the user calls publicDecrypt from their browser, gets back a KMS-signed proof, and submits it on-chain. No operator wallet, no relay.

// what the operator sees
buyer.balance = 0x7f3a9c...
merchant.revenue = 0xc2d18e...
protocol.fees = 0x09ef31...
// operator is blind by math

Contract

Contract · Sepolia0x34e412625DF16F8397B31CD122C8320f85b5c0A5
Payment token
USDC · Sepolia0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238
Key functions
listApi(name, description, price)Merchant lists an API with a cleartext USDC price per call.
deposit(amount)Buyer deposits USDC. Balance is encrypted as euint64 on-chain.
canAfford(apiId, buyer)Middleware-only gas-free eth_call. Returns encrypted ebool — no plaintext leaks.
batchSettle(apiIds, buyers, counts)Middleware-only. Settles N accumulated calls in one tx via FHE mux — all encrypted throughout.
requestWithdrawal()Buyer or merchant signals intent to withdraw. Sets withdrawalPending flag.
fulfillWithdrawal(merchant, cleartexts, proof)Merchant submits KMS-signed proof from their browser. Contract verifies and transfers USDC.
fulfillBuyerWithdrawal(buyer, cleartexts, proof)Buyer submits KMS-signed proof from their browser. Contract verifies and transfers USDC.