zkAPI lets you pay for AI and other APIs with ETH and make unlinkable requests. It keeps API usage separate from your on-chain deposit: the service can verify that you can pay without learning which deposit is yours.
Built by Open Anonymity in collaboration with the Ethereum Foundation, zkAPI uses zero-knowledge proofs to make this possible. Deposit ETH, pay only for what you use, and withdraw your remaining balance on-chain.
Live web app: chat.openanonymity.ai — try zkAPI in OA Chat by choosing the Ethereum wallet option.
Documentation: zkapi.openanonymity.ai.
The protocol is experimental; see the note-binding review and the concession exit design, which lets a user withdraw without any cooperation from the operator.
Releases follow semantic versioning on major version 0: until 1.0.0, any interface may change in any release. See the changelog.
This branch adds native Tor conversation isolation, canonical prompt rewriting, separate target-side history, bounded cover traffic and saved vault-protocol selection to the local client. Start with the client README and build instructions.
Not a production release: concession network manifests are undeployed and production proving keys are missing; legacy needs its matching historical wallet bundle. Neither protocol selection nor privacy features bypass these checks. Local wallets, binaries, proving assets and scratch outputs are excluded from Git.
Use zkapi-clientd to configure an ETH wallet and serve
inference to Open WebUI or another local OpenAI-compatible client. Its
withdrawals can pay their network fee from the payout (withdraw --fees payout, through an ERC-4337 paymaster), so the payout address needs no ETH;
the vault is unchanged.
npm ci
npm test
npm run verify:assets
npm run verify:builds # the placeholder profiles must refuse to build
cargo build --release --workspace
cargo test --release --workspace
cargo test --release --manifest-path protocol/rust/Cargo.toml --workspace
(cd protocol/contracts && forge test)The protocol and required Solidity libraries are ordinary files in this repository. No submodule initialization, Cairo compiler or STARK prover is needed. See source provenance.
@openanonymity/zkapi-browser-sdk owns native ETH funding, wallet persistence,
proof generation, lease recovery, settlement and withdrawals. Mainnet and Sepolia
have independent deployment pins, signing keys and wallet state. Applications
configure the SDK before initializing a wallet; see SDK integration
and native billing. A withdrawal can pay its
network fee from the payout (fees: 'payout', through an ERC-4337 paymaster),
so the payout address needs no ETH; the vault is unchanged.
The packaged WASM and proving keys support the current circuit
zkapi-v2-concession-v1 (vault revision 3), with the development setup until
the multi-party ceremony has run. Until a revision-3 vault is deployed, the
packaged network profiles are placeholders and npm run build:browser and
npm run build:mainnet refuse them by design (deployment_not_deployed);
npm run verify:builds checks exactly that. Notes of the earlier circuit
zkapi-v2-note-bound-v1 are served by the release line
release/v2-note-bound. Ordinary SDK consumers do not need Rust. To rebuild
WASM deliberately, use scripts/build-browser-client.sh and review the changed
artifact hashes; npm run verify:wasm rebuilds it reproducibly and compares.
Run npm run test:e2e:v2 to build and test circuit zkapi-v2-concession-v1
end to end on a fresh local chain. It covers the honest flow and the Sepolia
drill scenarios that run locally, and writes a gas report. The drill scenarios
include withholding, bad successor anchors, a lying expiry check, forced and
conceding escapes with raises and defeats, the bounded pause, a missed
defeat with leaf retirement, and gasless withdrawals through a local
bundler.
The contracts, proofs, server, indexer, challenger, signer sidecar, browser SDK
and clientd companion are real. The provider, OA org and price feed are
mocked. See the acceptance process and coverage limits.
node scripts/check-withdrawal-golden.mjs submits the Rust, JS and Go
withdrawal encoders' calldata to an Anvil vault.
zkapi serverd: native ETH lease authorization, settlement and Schnorr signing.zkapi-indexerd/zkapi indexer: vault event indexing and Merkle paths from a view verified against the vault.zkapi db init: create the server database with its append-only request evidence and bind it to the deployment manifest, before any daemon starts.zkapi-challenged: durable escape monitoring; defeats escapes from spent states, raises under-conceded escapes, and retires a closed note's leaf after a missed defeat; private status endpoints.zkapi signing-keys: derive deployment public keys from operator seeds (the published development keys are rejected).zkapi settlement reopen: with the API server stopped, verify, repair and reopen a lease cancelled for a corrupt binding.zkapi setup --output-dir NEW_DIRECTORY: generate a fresh single-party development setup, which release builds refuse.
Native server startup requires a pinned oracle RPC/feed, a lease issuer, the
deployment manifest, and both ZKAPI_STATE_SEED and ZKAPI_CLEAR_SEED; there
are no default seeds. The server refuses to start unless their keys equal the
vault's immutable keys and the vault, adapter and Poseidon library match the
manifest. Use deployment instructions,
Docker operation,
challenge service operation and the
concession-vault migration runbook. The
browser sends prompts directly to the inference provider; the server handles
authorization and settlement.
The keys in protocol/setup/v2-concession (the ceremony's, once G-SETUP has
run) must match the vault's immutable verifier and the client's pinned proof
artifacts; protocol/setup/v2-concession-dev holds the development keys for
tests, the drill vault and vaults deliberately deployed on a single-party setup
(Single-party setup). The setup
command generates new development keys;
it is not part of connecting a client to the configured vault.
The active protocol uses Groth16 over BN254, Poseidon, note-bound Baby-JubJub commitments and Schnorr signatures, a nullifier chain whose successor anchors are derived from the spent nullifier, and a 32-level append-only Merkle tree. The ledger uses integer gwei. An escape concedes at most the request budget of the state it leaves and needs no operator cooperation. Production keys need the multi-party setup described in the ceremony setup; the committed keys are a single-party development setup.
| Directory | Purpose |
|---|---|
zkapi-clientd/ |
Local ETH-funded OpenAI-compatible client and installer |
sdk/ |
Browser native ETH wallet, public artifacts and SDK tests |
protocol/rust/ |
Shared v2 types, BN254 helpers, circuits and Rust/WASM wallets |
protocol/contracts/ |
Native ETH vault, Groth16 verifier and contract tests |
protocol/setup/v2-concession/, v2-concession-dev/ |
Ceremony and development setups of the current circuit |
protocol/setup/v2/ |
Setup of the legacy circuit, for release/v2-note-bound |
crates/ |
Operator CLI, server, indexer, challenger and the clientd wallet companion |
demo/contracts/ |
Native ETH verifier/vault deployment script |
docker/aws/ |
API/indexer/challenger image configuration and restricted signer |