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.
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));
}| Tier | Max per batch | When to use |
|---|---|---|
| Free | 10 | Testing & small-scale |
| Pro | 100 | Regular batch processing |
| Scale | 500 | High-throughput pipelines |
| Enterprise | 2,000 | Multi-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
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"
}
]
}Required fields:
receiptId— The receipt ID returned by VanishdapiKeyId— 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 recordsnotes— Internal notes (e.g., ticket number)