Documentation
ZK Licensing Developer Guide
ZK Licensing lets you add privacy-preserving license verification to any software using zero-knowledge proofs on Mina Protocol. No license servers, no email addresses, no tracking.
Quick Start
Get license verification into your app in under 10 minutes.
- Register your app on zklicensing.com/register — connect your Mina wallet, set your price, deploy the zkApp. Takes ~5 minutes.
- Copy your verification key from the post-deploy screen.
- Install the SDK in your project.
- Call
verifyLicense()at app startup.
How It Works
The system has three layers:
- zkApp (Mina smart contract) — holds the authoritative license state on-chain. Exposes methods
purchase()andrenew(). - Proof JSON — a ~22 kB file the buyer downloads. Contains a ZK proof attesting "a valid license exists for this app and tier" without revealing the buyer's wallet address.
- Verification key — a public key you embed in your app. Used to verify the proof offline in milliseconds.
Key Concepts
ZK Proof
A zero-knowledge proof is a cryptographic object that proves a statement is true without revealing the witness that makes it true. In our case: "a valid purchase transaction exists on Mina" is proven without revealing which wallet address made the purchase.
Verification Key
The verification key is derived from your zkApp's circuit. It's a ~500-byte string you hard-code into your application binary. It's safe to distribute publicly — it can only verify proofs, not create them.
zkApp Address
The on-chain address of your deployed licensing contract. Optionally used for chain-based verification as a fallback when the buyer has lost their proof file.
Registering Your App
Go to register.html and complete the 5-step form:
- Step 1 — Connect wallet. Your Auro wallet becomes the zkApp's admin key. Keep it safe — it's the only way to update pricing or withdraw funds.
- Step 2 — App info. Name, slug (used in proof files), description, category.
- Step 3 — Pricing. Your Mina payment address and license tiers. You can add multiple tiers (Free, Pro, Enterprise).
- Step 4 — Settings. Grace period, refund window, transfer rules, trial mode.
- Step 5 — Deploy. Signs a Mina transaction that publishes your zkApp contract.
SDK Reference
Available for TypeScript/Node.js, Python, and Rust. All SDKs expose the same interface.
verifyLicense(options)
| Option | Type | Description |
|---|---|---|
| proofPath | string | Absolute path to the user's proof.json file |
| proofJson | object | Alternative to proofPath — pass the parsed JSON directly |
| zkAppAddress | string | Your deployed zkApp's Mina address (B62q…) |
| verificationKey | string | Your circuit's verification key hash |
| requireTier | string? | Optional — reject if tier doesn't match (e.g. "pro") |
| allowGrace | boolean? | Accept proofs within the 7-day grace period (default true) |
| fallbackChain | boolean? | If proof is missing, query Mina RPC as fallback (requires network) |
Return value
| Field | Type | Description |
|---|---|---|
| valid | boolean | Whether the license is currently valid |
| tier | string | "free" | "pro" | your custom tier name |
| expiresAt | number | Unix timestamp of expiry (null for lifetime/free) |
| daysRemaining | number | Days until expiry (negative = already expired) |
| source | string | "proof" | "chain" — how the license was verified |
| error | string? | If invalid: "EXPIRED" | "INVALID_PROOF" | "NOT_FOUND" |
zkApp Circuit
The zkApp is written in o1js (TypeScript framework for Mina zkApps). The circuit enforces three rules:
- The purchase transaction was signed by a valid Mina private key.
- The payment amount equals the tier price at time of purchase.
- The proof's public output —
{ tier, expiresAt }— is correctly derived from the on-chain state.
Webhooks
Register a webhook URL in your app settings to receive POST notifications for license events. Useful for syncing to your own backend.
| Event | Trigger |
|---|---|
| license.created | New license purchased |
| license.renewed | License renewed on-chain |
| license.expired | License passed expiry timestamp |
| license.refunded | Refund processed within window |
Proof JSON Format
The proof file downloaded by buyers has this structure:
FAQ
What happens when Mina is down?
Proof verification is fully offline — it only reads the local proof.json file and runs the verifier against your embedded verification key. Mina network downtime has zero impact on existing license checks.
Can users share their proof.json?
The proof doesn't contain the buyer's wallet address in the public output, so sharing it would give another user a working license. You can mitigate this by enabling device binding in settings, which ties the proof to a machine fingerprint derived inside the ZK circuit.
Can I change my license price?
Yes — call the zkApp's updatePrice() method from your admin wallet. Changes apply to new purchases only. Existing licenses are unaffected. Price updates are rate-limited to once per 30 days.
What's the 2% platform fee?
ZKLicensing deducts 2% of each payment on-chain before sending the remainder to your payment address. This is enforced by the zkApp circuit — we can't change it after deployment. See Pricing for volume discount tiers.
Is the source code open?
The zkApp circuit and the SDK are open source on GitHub. The web frontend is source-available. We encourage developers to audit the circuit before integrating.