Quick Start

Get up and running with Vanishd in 5 minutes.

1. Get Your API Key

Sign in to the dashboard and navigate to API Keys. Create a new key and copy it somewhere safe.

Important: Your API key is only shown once when created. Store it securely.

2. Hash Your Credential Locally

Your actual data never leaves your system. Hash it locally using SHA-256 before sending to Vanishd.

// JavaScript example
const crypto = require('crypto');

const salt = crypto.randomBytes(16).toString('hex');
const credentialId = 'user@example.com';
const apiKeyId = 'YOUR_API_KEY_ID'; // From your dashboard
const hashInput = `vanishd:v1:${apiKeyId}:${credentialId}:${salt}`;
const credentialHash = crypto.createHash('sha256').update(hashInput).digest('hex');

// IMPORTANT: Save the salt and apiKeyId to verify later
console.log('Salt (SAVE THIS):', salt);
console.log('Hash:', credentialHash);

The salt allows you to later prove which credential the hash corresponds to, without revealing it upfront.

3. Create a Deletion Receipt

Call the Vanishd API to create a blockchain-anchored receipt for your deletion claim.

// Using @dfinity/agent (JavaScript)
import { Actor, HttpAgent } from '@dfinity/agent';
import { Ed25519KeyIdentity } from '@dfinity/identity';
import { IDL } from '@dfinity/candid';

// 1. Create agent and identity
const agent = new HttpAgent({ host: 'https://ic0.app' });
const identity = Ed25519KeyIdentity.generate();
agent.replaceIdentity(identity);

// 2. Create actor with Vanishd canister
const CANISTER_ID = 'lyksb-qiaaa-aaaae-aec2a-cai';
const idlFactory = ({ IDL }) => {
  const Error = IDL.Variant({
    unauthorized: IDL.Null,
    notAuthorized: IDL.Null,
    invalidInput: IDL.Text,
    internalError: IDL.Text,
    rateLimited: IDL.Null,
    usageLimitExceeded: IDL.Null,
    userDisabled: IDL.Null,
    userFrozen: IDL.Null,
  });
  const Receipt = IDL.Record({
    id: IDL.Text,
    status: IDL.Text,
    createdAt: IDL.Int,
    credentialHash: IDL.Vec(IDL.Nat8),
    commitmentHash: IDL.Vec(IDL.Nat8),
  });
  return IDL.Service({
    certify: IDL.Func(
      [IDL.Text, IDL.Record({
        credentialHash: IDL.Vec(IDL.Nat8),
        destroyedAt: IDL.Int,
        metadata: IDL.Opt(IDL.Vec(IDL.Tuple(IDL.Text, IDL.Text))),
        idempotencyKey: IDL.Opt(IDL.Text),
      })],
      [IDL.Variant({ ok: Receipt, err: Error })],
      []
    ),
  });
};
const actor = Actor.createActor(idlFactory, { agent, canisterId: CANISTER_ID });

// 3. Convert hex hash to Uint8Array
const hashBytes = new Uint8Array(
  credentialHash.match(/.{2}/g).map(byte => parseInt(byte, 16))
);

// 4. Create the receipt
const result = await actor.certify(apiKey, {
  credentialHash: hashBytes,
  destroyedAt: BigInt(Date.now()) * 1000000n, // nanoseconds
  metadata: [],
  idempotencyKey: [],
});

if ('ok' in result) {
  const receipt = result.ok;
  console.log('Receipt ID:', receipt.id);
  // SAVE THIS RECEIPT - it's your proof of deletion
}

3b. Batch Operations (Optional)

Processing multiple deletions at once? Use certifyBatch to create many receipts in a single API call. This is significantly more efficient for bulk operations because the entire batch counts as just 1 API call toward your rate limit.

// Batch certify: create multiple receipts at once
const results = await actor.certifyBatch(apiKey, [
  {
    credentialHash: hashBytes1,
    destroyedAt: BigInt(Date.now()) * 1000000n,
    metadata: [],
    idempotencyKey: ['batch-001-item-1'],
  },
  {
    credentialHash: hashBytes2,
    destroyedAt: BigInt(Date.now()) * 1000000n,
    metadata: [],
    idempotencyKey: ['batch-001-item-2'],
  },
]);

if ('ok' in results) {
  console.log(`Created ${results.ok.length} receipts`);
  results.ok.forEach(r => console.log('Receipt:', r.receiptId));
}
TierMax per batchWhen to use
Free10Testing & small-scale
Pro100Regular batch processing
Scale500High-throughput pipelines
Enterprise2,000Multi-agent fleet operations

Use certify for single receipts (<10/minute). Use certifyBatch for bulk operations (>10 receipts). See the API Reference for full details.

4. Store Your Receipt

The receipt contains all the cryptographic proof needed for verification. Store it securely:

  • Programmatically: Save the full receipt JSON in your database alongside the deletion record
  • Dashboard backup: Receipts are also visible in your dashboard for export
  • Canister: The receipt is anchored to the blockchain for verification
Best practice: Always save receipts programmatically when you create them. The dashboard is a backup, not your primary storage.

5. Verify Anytime

Anyone can verify a receipt using the public verification endpoint:

// Verify a receipt
const result = await actor.verify(receiptId);

if ('ok' in result) {
  console.log('Receipt is valid');
  console.log('Credential hash:', result.ok.credentialHash);
  console.log('Destroyed at:', result.ok.destroyedAt);
  console.log('Merkle proof valid:', result.ok.merkleProofValid);
}

For bulk verification, use the Auditor Dashboard.

5. Store Your Salts Securely

To later prove which credential a receipt corresponds to, you must save the salt you used when creating the hash. We recommend storing credentials in a structured format:

{
  "vanishd_credentials": [
    {
      "receiptId": "abc-123-def",
      "apiKeyId": "key_abc123",
      "credentialId": "user@example.com",
      "salt": "a1b2c3d4e5f6g7h8",
      "createdAt": "2026-02-08T11:45:32Z",
      "notes": "GDPR deletion request #1234"
    }
  ]
}
Tip: You can upload this file in the Receipts dashboard to automatically verify your credentials match your receipts — all client-side.

Required fields:

  • receiptId — The receipt ID returned by Vanishd
  • apiKeyId — Your API key ID (from dashboard)
  • credentialId — The original credential (e.g., email, user ID)
  • salt — The random hex salt you generated

Optional fields:

  • createdAt — ISO timestamp for your records
  • notes — Internal notes (e.g., ticket number)