Skip to content
SDKs

JavaScript / TypeScript SDK

The @vitrified/sdk package: hashing, submission, bundle fetch, offline verification — same API across Node and browser.

JavaScript / TypeScript SDK

@vitrified/sdk is the official Node and browser SDK. It targets Node 24 and modern browsers (ES2022). The verifier path is isomorphic: verifyBundle runs end-to-end in any browser with no Node-specific dependencies on the critical path.

Install

npm install @vitrified/sdk

Configure

import { Vitrified } from "@vitrified/sdk";

const vitrified = new Vitrified({
  apiKey: process.env.VITRIFIED_API_KEY,
  // Optional overrides:
  // baseUrl: "https://api.vitrified.glass",
  // timeoutMs: 30_000,
});

Hash a file (Node)

const digest = await vitrified.hashFile("./build/release.tar.gz");
// → "9f86d081884c7d65..."

Hash a buffer or stream

const digest = await vitrified.hashBytes(buffer);
// or
const digest = await vitrified.hashStream(readableStream);

Submit an attestation

const submission = await vitrified.attestations.create({
  artifact: { sha256: digest },
  metadata: {
    schema: "slsa.provenance.v1",
    predicate: {
      buildType: "https://example.com/build-type",
      builder: { id: "https://github.com/Attestations/GitHubActionsBuilder@v1" },
      // ...
    },
  },
  // Optional:
  // idempotencyKey: "release-1.2.3",
});

console.log(submission.id); // "sub_01J..."

Wait for the bundle

const bundle = await vitrified.attestations.waitForBundle(submission.id, {
  timeoutMs: 120_000, // wait up to 2 minutes
});

Or poll manually:

const submission = await vitrified.attestations.get(sub.id);
if (submission.bundle) {
  // ready
}

Verify a bundle (offline)

The verifier path is fully offline. No network calls required after the bundle is in hand.

import { verifyBundle } from "@vitrified/sdk";

const verdict = verifyBundle(bundle);

if (verdict.isVerified) {
  console.log("Bundle verified.");
} else if (verdict.overall === "partial") {
  console.log("Some mechanisms partial:");
  for (const [name, m] of Object.entries(verdict.mechanisms)) {
    console.log(`  ${name}: ${m.status}`);
  }
} else {
  console.error("Verification failed:", verdict.message);
}

Bitcoin oracle (optional)

OpenTimestamps verification can confirm structural validity without a Bitcoin source; full chain verification requires block-header lookups. Provide a Bitcoin oracle to enable full OTS:

import { verifyBundle, type BitcoinBlockHeaderOracle } from "@vitrified/sdk";

const oracle: BitcoinBlockHeaderOracle = {
  async getBlockHeaderHash(height: number) {
    // your Bitcoin source — Esplora, Blockstream, your own node, ...
    const r = await fetch(`https://blockstream.info/api/block-height/${height}`);
    return await r.text();
  },
};

const verdict = verifyBundle(bundle, { bitcoinBlockHeaderOracle: oracle });

Without an oracle, OTS lands verified_partial (structurally valid, chain anchor unchecked).

List submissions

const page = await vitrified.attestations.list({
  limit: 50,
  cursor: nextCursor, // from the previous page
  filter: { schema: "purl" },
});

Export

// Continuous sync to your destination (S3, GCS, Azure, git).
await vitrified.exports.create({
  destination: { kind: "s3", bucket: "my-attestations", prefix: "vitrified/" },
  filter: { schema: "slsa.provenance.v1" },
});

Webhooks

Outbound webhooks fire on attestation.witnessed, attestation.partial, and other lifecycle events. The SDK provides verifyWebhook() to validate the Vitrified-Signature header:

import { verifyWebhook } from "@vitrified/sdk";

const event = verifyWebhook({
  body: rawRequestBody,
  signatureHeader: req.headers["vitrified-signature"],
  secret: process.env.VITRIFIED_WEBHOOK_SECRET,
});

Browser usage

@vitrified/sdk works in the browser for read and verify operations. For submission from the browser, use a short-lived API key issued from your backend or use a server-side relay. The verifier path is the same code that powers @vitrified/verifier-web and the hosted verify.vitrified.glass page.

Source

sdks/js/ — SDK source, including the full type definitions.

Was this page helpful?