Getting started
Instrument an agent to produce verifiable, tamper-proof receipts in about five minutes.
What is Zanii
Zanii is a transparency log for AI agents. Every agent gets a cryptographic identity (did:key),
delegated by its owner. Each action becomes a signed, hash-chained receipt in an append-only Merkle log whose
state is anchored on-chain. Anyone can verify a receipt — signature, delegation, scope, inclusion — offline,
with no trust in Zanii. Receipts store only a hash of your payload, so no business data leaves your systems.
Install
# TypeScript / JavaScript npm install @zanii/sdk # Python pip install zanii
Quickstart (TypeScript)
1 — create an owner and agent identity, and an owner-signed delegation granting the agent scoped authority:
import { generateKeypair, createCert, ZaniiAgent } from '@zanii/sdk'; const owner = generateKeypair(); const agent = generateKeypair(); const cert = createCert( { issuer: owner.did, subject: agent.did, scopes: ['email.*', 'crm.read'], exp: '2027-01-01T00:00:00.000Z' }, owner.privateKey);
2 — wrap your tools. Every call is signed and shipped to the log automatically:
const zanii = new ZaniiAgent({ serverUrl: 'https://ledger.zanii.agency', agentDid: agent.did, agentPrivateKey: agent.privateKey, delegation: [cert], apiKey: process.env.ZANII_API_KEY, }); const sendEmail = zanii.wrapTool('email.send', realSendEmail); await sendEmail('jane@acme.co', 'Your invoice'); // recorded + provable await zanii.flush();
Core concepts
- Identity — an Ed25519 keypair; the agent’s DID is its public key, so anyone can verify its signatures with no lookup.
- Delegation — an owner-signed certificate granting an agent scoped, expiring authority. A delegate can only narrow scope, never widen it. Revocable.
- Receipt — a signed record of one action, hash-linked to the agent’s previous receipt. Gaps and edits are detectable.
- Transparency log — an append-only Merkle tree. Inclusion proofs show a receipt is in the log; consistency proofs show the log was never rewritten.
- Anchoring — the signed tree head is periodically written on-chain, so history is immutable even to the operator.
Verifying proofs (zero trust)
Anyone can fetch a receipt’s proof and verify it entirely client-side — signature, delegation, scope, Merkle inclusion, and the signed tree head:
import { fetchAndVerifyProof } from '@zanii/sdk'; const report = await fetchAndVerifyProof('https://ledger.zanii.agency', receiptHash); console.log(report.ok); // true — verified without trusting the server
Every receipt also has a shareable, human-readable proof page at /verify/<hash>.
Audit bundles
Export an agent’s complete, offline-verifiable history — receipts, proofs, revocations, and anchors — as a single
file: GET /v1/export/:agentDid. Verify it anywhere with verifyAuditBundle().
Useful for compliance evidence (EU AI Act record-keeping, SOC 2).
Accounts & API keys (self-serve)
Reads are public and need no key. Writing receipts needs an API key — create an account and issue your
own, no waiting. The admin key (zk_admin_) manages your account; the
ingest key (zk_live_) writes receipts. Both are shown once.
# 1. sign up — save the admin key curl -X POST https://ledger.zanii.agency/v1/account/signup -H 'content-type: application/json' -d '{"name":"Acme AI"}' # → { "org_id": 1, "admin_key": "zk_admin_…" } # 2. issue an ingest key (send the admin key as a Bearer token) curl -X POST https://ledger.zanii.agency/v1/account/keys -H 'authorization: Bearer zk_admin_…' -d '{"label":"prod"}' # → { "api_key": "zk_live_…" } — pass as apiKey (TS) / api_key (Python)
Manage your account (all require the admin key):
GET /v1/account/keys·DELETE /v1/account/keys/{id}— list / revoke keysGET /v1/account/usage?since=YYYY-MM-DD— receipts recorded per dayGET /v1/account/me— org, plan, active keys, 30-day usage
Webhooks
Get notified when your agents act. Register an https endpoint and Zanii POSTs a signed JSON event to it.
Events: receipt.recorded (an agent recorded an action) and
receipt.rejected (a write was rejected — e.g. out of scope, or a revoked delegation).
curl -X POST https://ledger.zanii.agency/v1/account/webhooks -H 'authorization: Bearer zk_admin_…' -d '{"url":"https://your-app.com/zanii","events":["receipt.recorded","receipt.rejected"]}' # → { "id": 1, "secret": "whsec_…" } (secret shown once)
Every delivery carries an X-Zanii-Event header and an
X-Zanii-Signature header. Always verify the signature before trusting a delivery —
it is sha256= followed by the HMAC-SHA256 of the raw request body, keyed with your secret:
import { createHmac, timingSafeEqual } from 'node:crypto'; function verify(rawBody, signature, secret) { const expected = 'sha256=' + createHmac('sha256', secret).update(rawBody).digest('hex'); return timingSafeEqual(Buffer.from(signature), Buffer.from(expected)); }
Payload shape:
{ "event": "receipt.recorded",
"ts": "2026-07-04T13:00:00.000Z",
"data": { "hash": "sha256:…", "index": 42, "agent_id": "did:key:…",
"action": "tool_call", "target": "crm.lookup" } }
Manage with GET /v1/account/webhooks and
DELETE /v1/account/webhooks/{id}. Only public https URLs are accepted;
delivery is best-effort with retries.
Public pages & embeds
Everything below is public — no key, no login. Great for dashboards, live demos, and sharing.
/verify/<hash>— human-readable proof page (with a scan-to-verify QR)/agent/<did>— a shareable agent trust profile (previews as a card when posted)/badge/<did>.svg— an embeddable “Verified by Zanii · N proofs” badge/qr/<hash>.svg— a QR to a proof’s verify page, for slides / live events/dashboard— the live transparency log (receipts stream in as they land)GET /v1/stats— counters (receipts, agents, anchors) for live tickersGET /v1/stream— a Server-Sent Events feed of receipts in real time
Learn more
- The protocol specification — receipts, delegation, Merkle proofs, anchoring.
- The live log — watch receipts arrive and open real proofs.
- GitHub — SDKs, offline verifier, reference implementation.