Live on Stellar Testnet · ShieldedPool deployed
x402 + ZK on Stellar — subscriber can't see merchant · merchant can't see subscriber

Your identity,never exposed

Subscribe to APIs via a ShieldedPool contract on Stellar. The 402 response shows only the pool contract — subscriber never learns the merchant's address. The server receives only a commitment hash — merchant never learns who subscribed. Neither side learns the other. Prove access with a Groth16 ZK proof. No identity. No trace.

11,741Circom circuit constraints
ShieldedPoolmerchant never on-chain
0 walletseen by the API server
Privacy model

Three things
stay hidden.

ZeroGate enforces four privacy properties: hidden merchant, blind server, unlinkable sessions, and ZK proof of access. Payment routes through a ShieldedPool contract — the merchant never appears on-chain. The server never learns your wallet.

01

Merchant hidden on-chain

Your USDC never goes to the merchant's wallet. It goes to a ShieldedPool Soroban contract. The contract stores only a Poseidon commitment hash — no merchant address, no plan, no price ever touches the ledger. Anyone watching the chain sees: wallet → pool contract. That's it.

ShieldedPoolCDMJVG…GXYY · Stellar Testnet
02

Server blind to your wallet

The /subscribe endpoint never receives your wallet address or transaction hash. It only receives a commitment hash — Poseidon(secret, expiry) — computed entirely in your browser. The server issues a session token tied to the commitment, not to you. It is provably unable to know who subscribed.

0 walletfields in /subscribe body
03

Unlinkable API access

Every API call carries a session token derived from your commitment hash via HMAC. The server verifies it without storing any wallet data. In production this becomes a full Groth16 ZK proof — the server learns only that a valid subscription exists, never which wallet holds it.

HMAC→ Groth16 · no session history
04

ZK proof of access

Your browser generates a Groth16 proof over the Poseidon Merkle tree — proving you hold a valid, unexpired subscription leaf without revealing which leaf, which wallet, or what amount was paid. 11,741 constraints, BN254 curve, verified by Stellar's native host functions.

11,741constraints · BN254 · Groth16
Flow

Deposit.Prove.Access.

Privacy guarantees

Four things
we never leak.

Every privacy property in ZeroGate is cryptographically enforced — not a policy promise. The Groth16 circuit proves all four simultaneously with a single pairing check on Stellar.

Circuit proof stats
circuit constraints11,741
Merkle tree depthdepth 20
proof systemGroth16
elliptic curveBN254
proof generation<3s
Amount hiddenMerchant hiddenUnlinkable sessionsNon-custodial

Amount-hiding

The USDC amount you pay is committed via Poseidon hash and never appears in any Stellar transaction field readable by the verifier or merchant.

Merchant-hiding

The API provider's Stellar address is replaced by a Poseidon commitment on-chain. No on-chain observer can determine who you paid, only that you paid someone.

Session unlinkability

Each API call produces a unique nullifier. The nullifier registry prevents replay without enabling any form of call correlation across sessions.

Non-custodial

No server or third party ever holds your wallet keys or session token. The ZK proof is generated entirely in-browser — your secret never leaves your machine.

Technical stack

Built on proven
ZK primitives.

Every layer of ZeroGate is open source. The circuit, the contracts, the middleware, and the frontend — all auditable and self-hostable.

Circom 2.0 circuit

11,741 constraints. Poseidon Merkle membership proof, nullifier derivation, merchant commitment, timestamp validity. Compiled with snarkjs Groth16.

Soroban verifier

Three contracts: Groth16Verifier (BN254 pairing check), NullifierRegistry (double-spend prevention), SubscriptionRegistry (Merkle tree + proof orchestration).

x402 payment layer

HTTP 402 flow over Stellar USDC SAC. The server issues a 402 challenge; the client pays and receives a leaf commitment. Amount never stored.

Freighter integration

In-browser wallet via @stellar/freighter-api. The wallet signs the x402 payment; the ZK proof is generated locally by snarkjs — no key material leaves the browser.

subscription_proof.circom
// subscription_proof.circom — core privacy circuit
pragma circom 2.0.0;
include "poseidon.circom";
include "merkleProof.circom";

template SubscriptionProof(levels) {
    // Private inputs — never leave the browser
    signal input secret;
    signal input merkle_path[levels];
    signal input path_indices[levels];
    signal input nullifier_secret;
    signal input merchant_addr;
    signal input merchant_salt;
    signal input amount;          // ← amount stays private

    // Public outputs — the only things the server sees
    signal output root;
    signal output nullifier;
    signal output merchant_commitment;
    signal output timestamp;

    // Prove Merkle membership without revealing leaf
    component merkle = MerkleProof(levels);
    // ... 11,741 constraints total
}
Get started

Private APIs,
merchant invisible.

Connect Freighter, deposit USDC into the ShieldedPool, and access any API with a ZK credential — the server never learns your wallet, the chain never reveals the merchant. Entirely in the browser, on Stellar Testnet.

Stellar Testnet · ShieldedPool deployed · Circom + Groth16 + Soroban