Quickstart.
Eight steps from nothing to a signed, publicly logged verification record. Typical setup is under ten minutes. You'll need an account and an API key from the dashboard.
How it works
- Register your database as a read-only system.
- Attest: snapshot what data exists for a subject (for example, a user's email).
- Delete the data in your own application. BurnLedger is not in the loop.
- Verify: BurnLedger re-queries and confirms the data is gone.
- A signed verification record is issued and appended to the public transparency log.
1 · Install the SDK
npm install burnledger
pip install burnledger
Published as burnledger on npm and burnledger on PyPI.
2 · Initialize the client
Use the API key from your dashboard (it starts with dp_).
import { BurnLedger } from "burnledger";
const dp = new BurnLedger({
apiKey: process.env.BURNLEDGER_API_KEY,
baseUrl: "https://api.burnledger.io",
});
import os
from burnledger import BurnLedger
dp = BurnLedger(
api_key=os.environ["BURNLEDGER_API_KEY"],
base_url="https://api.burnledger.io",
)
3 · Register your database
A system is a read-only connection to one of your data stores. Where the engine can report its own privileges — PostgreSQL among them — BurnLedger rejects credentials that have write access.
const system = await dp.registerSystem({
name: "users-db",
connectorType: "postgresql",
dsn: "postgresql://readonly_user:password@db.example.com:5432/myapp?sslmode=verify-full",
subjectQuery: "SELECT * FROM users WHERE email = $1",
hashScope: "full",
});
console.log("System registered:", system.id);
system = dp.register_system(
name="users-db",
connector_type="postgresql",
dsn="postgresql://readonly_user:password@db.example.com:5432/myapp?sslmode=verify-full",
subject_query="SELECT * FROM users WHERE email = $1",
hash_scope="full",
)
print("System registered:", system.id)
Read-only is enforced, not suggested. Registration fails if write access is detected on the credential — for PostgreSQL that check runs against pg_roles and the engine's own grant tables. Engines that cannot report their privileges require an explicit read_only assertion instead, and refuse to connect without one; each connector guide states which case applies. The subjectQuery uses $1 as the placeholder for the subject identifier; the placeholder syntax varies per connector.
TLS is required. The connection must reach verified TLS (certificate chain and hostname), or the connector is refused and every attestation against the system fails. For PostgreSQL that means ?sslmode=verify-full: omitted, the driver defaults to prefer, which silently falls back to plaintext. Each connector's own requirement is in its guide.
Supported connector types: postgresql, mysql, sqlserver, oracle, mongodb, redis, cassandra, neo4j, hbase, marklogic, elasticsearch, s3, dynamodb, redshift, bigquery, gcs, azure_blob, snowflake, databricks, teradata. Each has a full integration guide.
4 · Run a health check
Confirm BurnLedger can reach your database before creating attestations.
const health = await dp.healthCheck(system.id);
console.log("Status:", health.healthStatus); // "HEALTHY"
health = dp.health_check(system.id)
print("Status:", health.health_status) # "HEALTHY"
5 · Create an attestation
An attestation is a signed snapshot of what data exists for a subject. Do this before deleting the data.
const attestation = await dp.attest("user@example.com", {
systemIds: [system.id],
});
console.log("Attestation:", attestation.id);
console.log("Records found:", attestation.systems[0].recordCount);
attestation = dp.attest("user@example.com",
system_ids=[system.id],
)
print("Attestation:", attestation.id)
print("Records found:", attestation.systems[0].record_count)
6 · Delete the data
Delete the subject's data using your own application logic. BurnLedger does not delete data; it only observes.
// Your application code. BurnLedger is not involved here.
await db.query("DELETE FROM users WHERE email = $1", ["user@example.com"]);
# Your application code. BurnLedger is not involved here.
cursor.execute("DELETE FROM users WHERE email = %s", ("user@example.com",))
conn.commit()
7 · Verify and get the verification record
Verification re-queries your database. If the records are gone, a signed verification record is issued and appended to the public transparency log. If they aren't, no verification record is issued.
const result = await dp.verify(attestation.id, "user@example.com");
if (result.status === "CERTIFIED") {
console.log("Deletion confirmed!");
console.log("Certificate:", result.certificate.id);
// Download the PDF certificate
await dp.savePdf(result.certificate.id, "./deletion-proof.pdf");
} else {
console.log("Records still exist — deletion incomplete");
}
result = dp.verify(attestation.id, "user@example.com")
if result.status == "CERTIFIED":
print("Deletion confirmed!")
print("Certificate:", result.certificate.id)
# Download the PDF certificate
dp.save_pdf(result.certificate.id, "./deletion-proof.pdf")
else:
print("Records still exist — deletion incomplete")
8 · Verify the verification record offline
Both SDKs include a burnledger CLI for offline verification: Ed25519 signatures, canonical JSON, and the Merkle inclusion proof are checked entirely on your machine, using only the verification record file and the published public keys. See Verify a record for the full third-party story.
# Download the certificate and the published public keys
curl -H "Authorization: Bearer $BURNLEDGER_API_KEY" \
https://api.burnledger.io/v1/certificates/{id} -o certificate.json
curl https://api.burnledger.io/.well-known/burnledger-keys -o keys.json
# Verify offline
npx burnledger check --cert certificate.json --keys keys.json
# With online revocation check
npx burnledger check --cert certificate.json --keys keys.json \
--online --api-url https://api.burnledger.io --api-key $BURNLEDGER_API_KEY
With the Python SDK installed, the command is burnledger check … instead of npx burnledger check ….
Optional: webhooks
Register a webhook to get notified when attestations and verification records are created.
const webhook = await dp.registerWebhook({
url: "https://yourapp.com/webhooks/burnledger",
});
// Save this secret; it's only shown once
console.log("Webhook secret:", webhook.secret);
webhook = dp.register_webhook(
url="https://yourapp.com/webhooks/burnledger",
)
# Save this secret; it's only shown once
print("Webhook secret:", webhook.secret)
Events you'll receive:
attestation.created: snapshot takenattestation.verified: deletion confirmed, verification record issuedattestation.failed: records still existcertificate.revoked: verification record was revokedcertificate.log_included: added to the transparency logcertificate.transparency_failed: inclusion was retried and then abandoned;transparency_statusisFAILEDand stays there until an operator re-runs inclusion. The record is still signed and verifies offline — it has no inclusion proof.system.health_degraded/system.health_recovered: a registered system stopped answering health checks, or answered again
Deliveries are signed. Verify them with the SDK helper:
import { verifyWebhookSignature } from "burnledger";
const isValid = verifyWebhookSignature(
webhookSecret,
request.headers["x-burnledger-timestamp"],
requestBody,
request.headers["x-burnledger-signature"],
);
from burnledger import verify_webhook_signature
is_valid = verify_webhook_signature(
webhook_secret,
request.headers["X-BurnLedger-Timestamp"],
request_body,
request.headers["X-BurnLedger-Signature"],
)
Creating a read-only database user
PostgreSQL
CREATE ROLE burnledger_ro WITH LOGIN PASSWORD 'your_password';
GRANT CONNECT ON DATABASE myapp TO burnledger_ro;
GRANT USAGE ON SCHEMA public TO burnledger_ro;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO burnledger_ro;
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT SELECT ON TABLES TO burnledger_ro;
MongoDB
db.createUser({
user: "burnledger_ro",
pwd: "your_password",
roles: [{ role: "read", db: "myapp" }]
})
Environment variables
| Variable | Description |
|---|---|
| BURNLEDGER_API_KEY | Your API key (starts with dp_). |
| BURNLEDGER_API_URL | API endpoint: https://api.burnledger.io. |
Next
Read a verification record field by field in Verification Record anatomy, or hand one to a skeptic along with Verify a record.