Skip to content

@zkprova/verify-sdk

TypeScript SDK for ZKProva identity verification.

Quick Start

import { ZKProvaClient } from '@zkprova/verify-sdk';

const client = new ZKProvaClient({
  apiKey: 'your-api-key',
  baseUrl: 'https://api.zkprova.com/api/v1',
});

// Verify a QR token proof
const result = await client.verifyProof('qr-token-string');
console.log(result.all_verified); // true
console.log(result.auto_fill);    // [{ field: 'membership_status', value: 'Active member at Demo CU', ... }]

// Check quota
const quota = await client.getQuotaStatus();
console.log(`${quota.remaining}/${quota.monthly_quota} requests remaining`);

Error Handling

import { RateLimitError, QuotaExceededError, AuthenticationError } from '@zkprova/verify-sdk';

try {
  await client.verifyProof(token);
} catch (error) {
  if (error instanceof RateLimitError) {
    console.log(`Retry after ${error.retryAfter}s`);
  } else if (error instanceof QuotaExceededError) {
    console.log('Upgrade your plan');
  } else if (error instanceof AuthenticationError) {
    console.log('Check your API key');
  }
}

Full Verification Flow

The typical lender integration: resolve a QR token, verify the ZKP proofs, then check the trust registry.

import { ZKProvaClient } from '@zkprova/verify-sdk';

const client = new ZKProvaClient({
  apiKey: process.env.ZKPROVA_API_KEY!,
  baseUrl: 'https://api.zkprova.com/api/v1',
});

async function verifyMember(qrToken: string) {
  // 1. Resolve the QR token to get claims
  const resolved = await client.resolveToken(qrToken);
  if (!resolved.token_valid) {
    throw new Error('Invalid or expired QR token');
  }

  // 2. Verify all ZKP proofs
  const proof = await client.verifyProof(qrToken);
  if (!proof.all_verified) {
    console.error(`Verification failed at: ${proof.failed_step}`);
    return null;
  }

  // 3. Check the issuer is in the trust registry
  const registry = await client.getTrustRegistry();
  const issuer = registry.find(r => r.did === proof.issuer_info?.did);
  if (!issuer || issuer.status !== 'active') {
    throw new Error('Issuer not in trust registry');
  }

  // 4. Use auto-fill data for your loan application
  return proof.auto_fill;
}

Webhook Signature Verification

Verify incoming webhook payloads using HMAC-SHA256:

import crypto from 'crypto';

function verifyWebhookSignature(
  rawBody: string,
  signature: string,
  secret: string
): boolean {
  const expected = 'sha256=' + crypto
    .createHmac('sha256', secret)
    .update(rawBody, 'utf8')
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

Methods

Method Description
resolveToken(token) Resolve a QR token → member DID + claims
verifyProof(token) Full ZKP proof verification pipeline
getVerificationHistory(options?) Paginated verification history
getTrustRegistry() List trusted credit union issuers
getQuotaStatus() Current plan usage and remaining quota

All methods throw typed errors: AuthenticationError, RateLimitError, QuotaExceededError, or ZKProvaError.

Auto-Retry

The SDK automatically retries on: - 429 responses (respects Retry-After header) - 5xx server errors (exponential backoff, max 3 retries)

Configure retries:

const client = new ZKProvaClient({
  apiKey: 'key',
  retries: 5,        // max retry attempts
  timeout: 15000,    // request timeout in ms
});

Documentation