Node.js SDK for privacy-preserving zero-knowledge proofs with post-quantum attestation. Prove eligibility, KYC outcomes, age checks, residency, and other predicates without exposing raw credentials. Verify proofs locally or via the AffixIO API.
Built for developers working with Noir circuits, Barretenberg (UltraHonk), verifiable credentials, and NIST post-quantum standards (FIPS 204 ML-DSA).
Classical signatures (ECDSA, EdDSA, RSA) are vulnerable to future quantum attacks via Shor's algorithm. NIST finalised ML-KEM, ML-DSA, and SLH-DSA in 2024. AffixIO combines:
- Zero-knowledge SNARK proving over Noir attestation circuits (115+ templates)
- ML-DSA-65 (FIPS 204) signatures on proof payloads and credentials
- Merkle audit anchoring for tamper-evident proof history
- Offline-first queue for unreliable networks
You get prove, verify, storage, and a CLI without running a proving cluster locally.
| Source | Best for |
|---|---|
npm @affix-io/sdk |
Production apps, CI, Docker images, package.json dependencies |
GitHub AffixIO/SDK |
Source review, Apache 2.0 audit, pinning a commit, air-gapped installs from tarball |
npm is what most teams use day to day. Install once, import in code, ship with your service:
npm install @affix-io/sdkGitHub is the same compiled package (pre-built dist/, no TypeScript source in the public tree). Clone when you need to inspect exactly what ships, vendor the repo, or run the CLI without adding a registry dependency:
git clone https://github.com/AffixIO/SDK.git
cd SDK
cp .env.example .env
npx affix-sdk healthNeither path runs npm install per proof. Both give you a library you call at runtime.
The SDK is a Node.js client. Proving and verification run on the AffixIO API; your app sends credentials or witnesses and receives proof strings back.
Your service AffixIO API
┌─────────────────┐ ┌──────────────────────┐
│ Express / Fastify│ HTTPS │ witness/prepare │
│ Next.js API route│ ────────► │ circuits/:id/prove │
│ BullMQ worker │ │ circuits/:id/verify │
│ LangChain tool │ │ merkle/audit │
│ MCP server │ └──────────────────────┘
│ Cron / batch job │
└────────┬─────────┘
│ optional local
▼
.affix/proofs.json
.affix/offline-queue.json
Typical integration points:
- API middleware: prove a predicate before a sensitive route runs (payout, account change, data export).
- Background workers: batch eligibility checks;
flushOfflineQueue()when connectivity returns. - LLM orchestration: gate tool calls, model tiers, or retrieval scopes with a proof instead of passing raw KYC or HR data into the prompt.
- Agent and MCP servers: return a
proof_idalongside tool results so downstream systems can verify without seeing credentials. - Webhooks and event pipelines: attach a proof digest to an audit log entry via Merkle anchoring.
Install the package in the service that holds secrets and talks to AffixIO. Do not embed API keys in browser bundles or client-side LLM prompts.
Requires Node.js 18+.
import { AffixSDK, defaultContext } from "@affix-io/sdk";
const sdk = new AffixSDK();
const result = await sdk.prove({
circuitId: "attested_boolean",
credential: {
schema_id: "eligibility_v1",
issuer_id: "issuer_abc",
issuer_pubkey_hash: "0x...",
credential_id: "0x...",
claim_value: "approved",
valid_from: 1700000000,
valid_until: 1800000000,
},
context: defaultContext({ required_claim_hash: "approved" }),
});
console.log(result.valid, result.decision);npx affix-sdk health
npx affix-sdk prove --circuit attested_boolean --claim approved
npx affix-sdk verify <proof-id>A public-tier key ships in .env.example (6 requests/second per IP). Copy to .env:
cp .env.example .env| Variable | Required | Default |
|---|---|---|
AFFIX_API_KEY |
Yes | Public tier key in .env.example |
AFFIX_API_BASE |
No | https://api.affix-io.com |
Commercial keys with higher throughput: affix-io.com.
prove() accepts one of three shapes.
Credentials are normalised to BN254 field elements, witness-prepared server-side, then proved.
await sdk.prove({ circuitId, credential, context });Call buildWitness() (POST /v1/witness/prepare) then prove:
const witness = await sdk.buildWitness(circuitId, credential, context);
await sdk.prove({ circuitId, witness });For Merkle batch proofs and custom Noir inputs:
await sdk.prove({
circuitId: "merkle_batch",
fields: { leaf: "0x...", sibling0: "0x...", index: "0", expected_root: "0x..." },
});| Method | Description |
|---|---|
prove(input) |
Generate a zero-knowledge proof |
verify(circuitId, proof) |
Verify a proof string |
proveAndVerify(input) |
Prove then verify in one call |
buildWitness(...) |
Server-side witness preparation |
isOnline() |
API health check |
flushOfflineQueue() |
Replay queued prove jobs |
listQueuedJobs() |
Inspect offline queue |
listStoredProofs() |
Local proof store (last 500) |
npx affix-sdk config
npx affix-sdk health
npx affix-sdk circuits
npx affix-sdk prove [--circuit <id>] [--claim <value>]
npx affix-sdk verify <proof-id-or-path> [--circuit <id>]
npx affix-sdk list
npx affix-sdk flushProof responses can include ML-DSA-65 attestations (FIPS 204, CRYSTALS-Dilithium family). Credentials carry mldsa_signature_b64 for issuer binding. This aligns with the migration path described in NIST IR 8547 toward quantum-resistant cryptography.
The proving backend uses Noir compiled to ACIR with Barretenberg UltraHonk, the same stack documented in the Noir web app guide.
115+ attested Noir circuits including:
| Domain | Examples |
|---|---|
| Identity / KYC | kyc, attested_boolean, attested_membership |
| Age / health | health_age, health_vaccination_status |
| Residency / travel | ticket_local_resident, travel_visa_eligibility |
| Education | edu_attendance_threshold, edu_enrollment_verification |
| Merkle / audit | merkle_batch, audit_proof, quantum_safe_token |
| Governance | govt_voting_eligibility, zk_voting |
Run npx affix-sdk circuits for the full list from the live API.
When prove() fails and queueOnFailure is not false:
- Witness or fields bodies queue as-is for
flushOfflineQueue(). - Credential-based queueing requires the private
@affix-io/sdk-witnessadd-on (commercial). - Online witness prep always uses
POST /v1/witness/prepare.
Local paths: .affix/offline-queue.json, .affix/proofs.json.
| Endpoint | Purpose |
|---|---|
GET /api/health |
Service health |
GET /v1/circuits |
Circuit catalogue |
POST /v1/witness/prepare |
Witness preparation |
POST /v1/circuits/:id/prove |
SNARK proof generation |
POST /v1/circuits/:id/verify |
Proof verification |
GET /v1/merkle/root |
Audit Merkle root |
POST /v1/merkle/audit |
Anchor proof to audit log |
Large language models should not receive passports, medical records, or full KYC payloads just to answer "is this user allowed?". The SDK lets a trusted backend prove a yes/no predicate and hand the model (or tool runtime) only the outcome.
| Scenario | Circuit examples | What you prove without exposing |
|---|---|---|
| Tool gating before expensive calls | attested_boolean, kyc, govt_security_clearance |
User tier, account standing, or clearance level |
| RAG and document access | attested_membership, govt_professional_license, edu_enrollment_verification |
Group membership or role without employee/student IDs |
| Age and consent checks for restricted advice | health_age, ent_age_restriction, hosp_checkin_age |
Age threshold met, not date of birth |
| Healthcare-adjacent assistants | health_consent_verification, health_prescription_auth, health_clinical_trial_eligibility |
Consent or trial eligibility, not PHI |
| Cross-border or policy-bound models | travel_visa_eligibility, travel_restriction_check, govt_immigration_status |
Eligibility flag, not passport number |
| Agent audit trail | audit_proof, merkle_batch |
That a decision was proved at a point in time |
Example pattern for an LLM tool router:
import { AffixSDK, defaultContext } from "@affix-io/sdk";
const sdk = new AffixSDK();
export async function beforeToolRun(userCredential: Record<string, unknown>) {
const { valid, proof_id } = await sdk.prove({
circuitId: "govt_security_clearance",
credential: userCredential,
context: defaultContext({ required_claim_hash: "cleared" }),
});
if (!valid) throw new Error("tool_access_denied");
return proof_id; // pass to logs or Merkle audit, not to the model context
}The model sees tool output. It does not need the credential or the witness.
- Onboarding:
kyc,attested_boolean,consent_verification - PEP and sanctions-style gates:
govt_criminal_record,cross_data_consent - Professional and licence checks:
govt_professional_license,hosp_agent_credentials
- Credit and income bands:
cross_credit_score_range,cross_income_bracket,govt_tax_bracket - Mortgage and motor finance:
mortgage_engine,motor_finance_eligibility,motor_ownership_verification - Insurance validity:
motor_insurance_proof,travel_insurance_coverage
- Age-gated services:
health_age,health_age_verification - Vaccination and trial eligibility:
health_vaccination_status,health_clinical_trial_eligibility - Prescription and insurance predicates:
health_prescription_auth,health_insurance_eligibility
- Residency and local rates:
ticket_local_resident,travel_residency_proof,hosp_longstay_resident - Passport and visa windows:
travel_passport_validity,travel_visa_eligibility - Venue access:
ticket_student_discount,ticket_vip_access,ticket_disability_access
- Admissions and attendance:
edu_age_admission,edu_attendance_threshold,edu_prerequisites_met - Alumni and library access:
edu_alumni_status,edu_library_access - Employment proofs:
cross_employment_status,edu_degree_completion
- Voting and benefits:
govt_voting_eligibility,govt_benefit_entitlement,zk_voting - Residency duration and property:
govt_residency_duration,govt_property_ownership - Military and immigration:
govt_military_service,govt_immigration_status
- Post-quantum token checks:
quantum_safe_token,token_validation - Tamper-evident history:
audit_proof,merkle_batch - Offline and edge: queue failed
prove()calls, replay withflushOfflineQueue()when the API is reachable again
Run npx affix-sdk circuits for the live catalogue (115+ templates). Circuit IDs map to Noir attestation templates on the API.
- noir-lang/noir: ZK domain-specific language
- @aztec/bb.js: Barretenberg proving backend
- @noble/post-quantum: ML-DSA / SLH-DSA primitives
- NIST PQC standards: FIPS 203, 204, 205
Apache License 2.0. See LICENSE.
Report vulnerabilities via SECURITY.md.