Back to app

API Reference

ProofMatch exposes a Widget SDK and a REST API so any app can add ZK balance verification in minutes. All endpoints run on Stellar testnet with Groth16 / Soroban.

Widget SDK

Drop two script tags on any page. The widget opens a modal, runs the full ZK proof pipeline, and fires your callbacks.

<!-- 1. Load the widget --> <script src="https://localhost:3443/widget.js"></script> <!-- 2. Trigger verification --> <script> ProofMatch.verify({ minAmount: 100, // minimum balance to prove asset: "XLM", // "XLM" | "USDC" onVerified: (result) => { console.log(result.shareUrl); // shareable proof link console.log(result.txHash); // Stellar transaction hash }, onFail: (reason) => console.log("Failed:", reason), }); </script>

onVerified result object

FieldTypeDescription
verifiedbooleanAlways true in this callback
displayAmountstringHuman-readable amount, e.g. "100.00 XLM"
shareUrlstringFull URL to the shareable verification page
txHashstringStellar transaction hash of the on-chain verification
assetstring"XLM" or "USDC"
thresholdstringThreshold in stroops (1 XLM = 10,000,000)

npm SDK

The @stellar-zk/proofmatch package wraps the REST API for Node.js and ESM browser environments. Handles balance parsing, error handling, and progress callbacks.

# install npm install @stellar-zk/proofmatch

verifyFunds

import { verifyFunds } from "@stellar-zk/proofmatch"; const result = await verifyFunds({ accountId: "GC53FANLM24CPNH3DIYCMM4PYGJXKD6LYAAXC3QBWVLIDE3FWCYONKSM", minBalance: "100 XLM", // or "50 USDC", or 100 (XLM) serverUrl: "https://localhost:3443", onStep: (i, label) => console.log(`Step ${i}: ${label}`), }); // { verified: true, proofUrl: "...", txHash: "...", ledgerSeq: 55432101 }

getWalletHistory

import { getWalletHistory } from "@stellar-zk/proofmatch"; const { count, proofs } = await getWalletHistory( "GC53FANLM24CPNH3DIYCMM4PYGJXKD6LYAAXC3QBWVLIDE3FWCYONKSM" ); // count: 3, proofs: [{ threshold, asset, shareUrl, storedAt, ... }]

verifyLink

import { verifyLink } from "@stellar-zk/proofmatch"; const verdict = await verifyLink("https://localhost:3443/v/aB3xYz12"); // { verified: true, threshold: "50000000", asset: "XLM", ... }

REST API

All endpoints are under /api/, accept JSON bodies, and return JSON. CORS headers are set on all /api/* routes — call from any origin.

ⓘ Rate limited to 5 requests per IP per minute on proof-generation endpoints. Health and stats endpoints are unrestricted.

POST /api/prove-from-account

Fetch a live balance from Stellar testnet, generate a Groth16 ZK proof server-side, and verify it on-chain via Soroban. The private balance is never stored or returned.

Request

ParameterTypeDescription
accountIdstringrequiredStellar public key (G…, 56 chars)
thresholdstringrequiredMinimum balance in stroops (integer string)
assetstringoptional"XLM" (default) or "USDC"
curl -X POST https://localhost:3443/api/prove-from-account \ -H "Content-Type: application/json" \ -d '{ "accountId": "GC53FANLM24CPNH3DIYCMM4PYGJXKD6LYAAXC3QBWVLIDE3FWCYONKSM", "threshold": "50000000", "asset": "XLM" }'
Response — verified
{ "ok": true, "verified": true, "threshold": "50000000", "asset": "XLM", "accountId": "GC53FA···KSM", "txHash": "a3f9b2…", "txExplorerUrl": "https://stellar.expert/explorer/testnet/tx/a3f9b2…", "ledgerSeq": 55432101, "shareUrl": "/v/aB3xYz12", "contractId": "CB33TG…" }

POST /api/prove-multi

Prove combined balance across 2–3 Stellar wallets meets a threshold — without revealing any individual wallet amount.

Request

ParameterTypeDescription
accountIdsstring[]requiredArray of 2–3 unique Stellar public keys
thresholdstringrequiredMinimum combined balance in stroops
assetstringoptional"XLM" (default) or "USDC"
curl -X POST https://localhost:3443/api/prove-multi \ -H "Content-Type: application/json" \ -d '{ "accountIds": ["GABC…", "GXYZ…"], "threshold": "1000000000", "asset": "XLM" }'

POST /api/verify-proof

Submit a pre-generated Groth16 proof (e.g. from browser-side snarkjs) for on-chain Soroban verification. The server skips witness and proof generation — only verifies.

Request

ParameterTypeDescription
proofobjectrequiredsnarkjs Groth16 proof object (pi_a, pi_b, pi_c)
publicSignalsstring[]requiredPublic signals array from snarkjs — ["1", threshold]
thresholdstringrequiredThreshold in stroops (must match publicSignals)
accountIdstringoptionalWallet address for record — stored masked, never full key
assetstringoptional"XLM" (default) or "USDC"

Machine-readable verification of any share link. Lets third-party apps confirm a user's proof without embedding the ZK stack.

curl -X POST https://localhost:3443/api/verify-link \ -H "Content-Type: application/json" \ -d '{ "url": "https://localhost:3443/v/aB3xYz12" }'
Response
{ "ok": true, "verified": true, "threshold": "50000000", "asset": "XLM", "accountId": "GC53FA···KSMD", "txHash": "a3f9b2…", "storedAt": 1751500800000 }

GET /api/wallet/:accountId

Full proof history for a wallet. Returns all verified proofs associated with this address — threshold, asset, timestamps, share links. Balances are never stored. Proofs are retained for 1 year.

curl https://localhost:3443/api/wallet/GC53FANLM24CPNH3DIYCMM4PYGJXKD6LYAAXC3QBWVLIDE3FWCYONKSM
Response
{ "ok": true, "accountId": "GC53FA···KSM", "count": 3, "proofs": [ { "id": "aB3xYz12", "threshold": "50000000", "asset": "XLM", "ledgerSeq": 55432101, "storedAt": 1751500800000, "shareUrl": "/v/aB3xYz12" } ] }

GET /api/leaderboard

Returns the 50 most recent verified proofs. No private data — balances are never stored. Proofs persist for 1 year.

curl https://localhost:3443/api/leaderboard
Response
{ "ok": true, "total": 127, "proofs": [ { "id": "aB3xYz12", "threshold": "50000000", "asset": "XLM", "accountId": "GC53FA···KSMD", "ledgerSeq": 55432101, "txExplorerUrl": "https://stellar.expert/…", "storedAt": 1751500800000, "shareUrl": "/v/aB3xYz12" } ] }

GET /api/stats

Total proof count — used by the live counter badge on the homepage.

curl https://localhost:3443/api/stats { "ok": true, "totalProofs": 127 }

GET /api/health

Liveness check — returns 200 when Horizon is reachable and the proof store is writable, 503 when degraded.

curl https://localhost:3443/api/health { "ok": true, "checks": { "horizon": "ok", "proofsDir": "ok" }, "contract": "CB33TG…", "network": "testnet", "uptimeSeconds": 3600 }