Prepaid anonymous tickets for APIs,
on Zcash testnet

A transit card for APIs.

Top up once with a private Zcash payment. Every API call then uses one anonymous ticket: no new payment, and nobody can link a call to you or to any other call.

Gateway · live

Loading the gateway status

402Current challenge

GET /api/quote
Asking the gateway for a payment challenge
The idea

Pay once. Then just ride.

AI agents call paid APIs thousands of times a day. Both usual ways to pay give the agent away. Kippu works like a transit card or a strip of arcade tokens: one private top-up, then a ticket per call.

API key

Every call is logged to your account

The provider keeps a list of everything your agent asked, tied to who you are.

  • Linked to you
  • Calls linked to each other
Pay per call on a public chain

Every call is a public payment

Anyone can line the payments up. Each one costs a network fee and a wait for a block.

  • A transaction per call
  • Calls linked to each other
Kippu tickets

One private top-up, then a ticket per call

A shielded Zcash deposit buys a strip of tickets. Each call spends one, with a zero-knowledge proof that it is valid and unused.

  • No transaction per call
  • No link to you or between calls

Kippu is not a wallet, a spending policy or payroll. It only sells tickets and checks them.

In a real product

Kippu Agent. You ask, it pays in tickets.

A research assistant you prompt in the browser. It buys a strip of tickets with one shielded deposit, then pays for every live lookup (weather, exchange rates, Wikipedia, crypto prices, Hacker News) with one ticket. Its wallet shows the strip being punched, call by call.

Kippu Agent during the October 28 testnet run: a chat answering questions with paid lookups, each a 402, a proof and a 200, next to a ticket wallet whose strip shows the used tickets punched out.
Live testnet run, October 28, 2026: one shielded deposit 12fc57ba…bec219 bought 40 tickets; five lookups paid with five of them.
  • One depositbuys the whole strip, shielded: the chain shows no sender, amount or tickets.
  • One ticket per lookup402 Payment Required, a proof made in one to three seconds, then the data. No transaction.
  • Replay refusedSending a used ticket again gets NULLIFIER_SPENT.
How it works

A ticket office that can't see who rides.

Zcash has no smart contracts, so the gateway runs the ticket office. It sells tickets against a shielded deposit, checks one proof per call, and publishes a signed fingerprint of its ticket list on-chain so it can't quietly change the rules.

01

Deposit once

One shielded Zcash payment buys a whole strip of tickets. Its memo commits to every ticket and its value; the gateway checks it with its viewing key, then credits the strip.

Memoz402:<commitment to every ticket>
02

Prove per call

The API answers 402 Payment Required. Your client replies with a Groth16 proof made on your machine, in one to three seconds.

What the proof saysper call
  • Ticket is valid yes
  • Ticket is unused yes
  • Which ticket not revealed
03

Anchor

A signed fingerprint of the ticket list goes on-chain. Clients read it before proving, so every client proves against the same list.

Anchor memo z402:anchor:<tickets>:<root>:<spent>:<hash>:<sig>
04

Who sees what

The gateway learns that one ticket of that price paid. Not which one.

  • GatewayYour deposit, each call and your IP. Never which ticket paid.
  • Zcash chainA shielded deposit and the public anchors. Nothing per call.
  • YouEverything, in your own notes file.
05

Agents pay too

The MCP server gives any agent four tools, with spending caps the agent cannot raise.

  • statusYour tickets and the gateway's, read-only
  • depositPlan a strip and send one shielded deposit
  • claimHave the gateway credit the deposit
  • payFetch a URL, answering its 402 with a proof
Live

Price, straight from the gateway

Loading prices
Gateway

The hosted gateway, right now.

Every number below was fetched by this page from the gateway's /api/info a moment ago. Nothing is recorded or typed in.

Checking
Loading the gateway status
Open the gateway console

Tickets, anchors, the current root and a live 402, refreshed every 15 s.

Developers

Three calls. Then it just pays.

The TypeScript client plans the tickets, claims the deposit, and answers each 402 with a proof. It only pays its own gateway, at the price the gateway lists, against a root it has read on-chain itself.

client.ts@z402/sdk
import { Z402Client } from '@z402/sdk';

// reads anchors on-chain and pins the gateway's anchor key
const kippu = new Z402Client(GATEWAY, './notes.json', {
  anchorUivk: process.env.Z402_ANCHOR_UIVK,
  anchorPubkey: process.env.Z402_ANCHOR_PUBKEY,
});

// 1. plan(count, units): 20 tickets of 10 units
const { plan, address, amountZat, memo } =
  await kippu.plan(20, 10n);

// 2. send ONE shielded deposit, then claim it
await kippu.claim(plan, txid);

// 3. every call: the 402 is answered with a proof
const res = await kippu.pay(`${GATEWAY}/api/quote`);
Run it live

Ask the gateway for a 402

This sends a real GET /api/quote with no payment, and shows the challenge exactly as the gateway answers it.

Press the button: the response appears here.
Limits

What it does not promise.

Read these before you trust it with anything. The README lists every known limit in full.

  1. 01

    Testnet only, not audited

    It runs on Zcash testnet with a single-party Groth16 setup. Nobody has audited the circuits or the gateway.

  2. 02

    The gateway is trusted for liveness

    It could refuse a deposit or a proof, and it must keep anchoring: clients refuse anchors that are too old. Signed anchors make its spent set auditable after the fact.

  3. 03

    Clients trust their lightwalletd

    The client reads anchors through a lightwalletd server and checks no block headers, and that server sees what the client reads.

  4. 04

    Privacy is as big as the crowd

    A payment hides which ticket paid among the tickets of that price in the latest anchor. With one depositor, the gateway knows every call is theirs.

Run your own ticket office.

Circuits, the gateway, a TypeScript client and an MCP server. Open source, MIT.