npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@certnode/sdk

v2.1.0

Published

CertNode SDK — cryptographic provenance for AI outputs. Sign content from Claude, OpenAI, Mistral, or any model with independently verifiable receipts. Complete rewrite from v1.x (unrelated to previous API surface).

Readme

@certnode/sdk

Cryptographic provenance for AI outputs. Sign content from Claude, OpenAI, Mistral, or any model with independently verifiable receipts.

Install

npm install @certnode/sdk

Quickstart

  1. Get an API key at https://certnode.io/ai-provenance (100 signings/month free).

  2. Sign AI output:

import { CertNode } from '@certnode/sdk'
import Anthropic from '@anthropic-ai/sdk'

const claude = new Anthropic()
const cert = new CertNode({ apiKey: process.env.CERTNODE_API_KEY! })

const response = await claude.messages.create({
  model: 'claude-opus-4-7',
  messages: [{ role: 'user', content: 'Write marketing copy for X' }],
})

const signed = await cert.signAIOutput({
  output: response.content[0].text,
  model: 'claude-opus-4-7',
  provider: 'anthropic',
})

console.log(signed.receiptId)
console.log(signed.verifyUrl)
// Anyone can verify at: certnode.io/verify/<receiptId>
  1. Verify later (no API key required for verification):
const verification = await cert.verify({ receiptId: signed.receiptId })
console.log(verification.valid)  // true
console.log(verification.receipt?.signedAt)

OpenAI

import OpenAI from 'openai'
import { CertNode } from '@certnode/sdk'

const openai = new OpenAI()
const cert = new CertNode({ apiKey: process.env.CERTNODE_API_KEY! })

const completion = await openai.chat.completions.create({
  model: 'gpt-4o',
  messages: [{ role: 'user', content: 'Summarize this article' }],
})

const signed = await cert.signAIOutput({
  output: completion.choices[0].message.content!,
  model: 'gpt-4o',
  provider: 'openai',
})

What gets signed

Every call to signAIOutput produces a receipt with:

  • Content hash — sha256 of the output (not the raw content; re-hash to verify)
  • JWS signature — ES256 signature over the payload
  • Three-layer timestamps:
    • CertNode internal timestamp (HMAC-SHA256, sub-second)
    • RFC 3161 timestamp from an independent TSA (court-admissible standard)
    • Bitcoin anchor via OpenTimestamps (queued, confirmed within 1-2 hours)
  • Metadata — model, provider, optional prompt hash

Verification

Anyone can verify a signature — no account required:

// Mode 1: by receipt ID (looks up stored receipt)
await cert.verify({ receiptId: 'uuid-here' })

// Mode 2: by raw signature + content (re-hashes and verifies)
await cert.verify({
  signature: signed.signature,
  content: 'original content here',
})

Or use the hosted verify page: https://certnode.io/verify/[receiptId]

Why this matters

  • AI detection is losing. Every model release breaks GPTZero, Turnitin, and other detectors. Provenance is cryptographic — it doesn't degrade.
  • Designed for court admissibility under FRE 902(13)/(14). Three-layer timestamp chain provides self-authenticating digital evidence.
  • EU AI Act Article 50 compliant (enforces August 2026). Content provenance for AI-generated content.
  • Platform-agnostic. Works with Claude, OpenAI, Mistral, Meta, or any AI tool. Not locked to one provider.

Pricing

| Monthly volume | Per-signing | |---|---| | 0 – 100 | Free | | 100 – 10,000 | $0.010 | | 10,000 – 100,000 | $0.007 | | 100,000 – 1,000,000 | $0.004 | | 1,000,000+ | $0.002 |

Volume discounts apply automatically. Verifications are always free.

API reference

new CertNode(options)

interface CertNodeOptions {
  apiKey: string              // Required. cn_live_... or cn_test_...
  baseUrl?: string            // Default: https://certnode.io/api/v1/provenance
  timeoutMs?: number          // Default: 15000
}

cert.signAIOutput(input)

interface SignAIOutputInput {
  output: string              // AI-generated text to sign
  model?: string              // e.g. 'claude-opus-4-7'
  provider?: string           // e.g. 'anthropic'
  promptHash?: string         // sha256 of prompt (optional, privacy)
}

cert.signContent(input)

interface SignContentInput {
  content: string
  contentType?: 'ai_output' | 'image' | 'document' | 'json'
  model?: string
  provider?: string
  promptHash?: string
}

cert.verify(input)

interface VerifyInput {
  // Mode 1: by receipt ID
  receiptId?: string

  // Mode 2: by raw signature + content
  signature?: string
  content?: string
}

cert.getReceipt(receiptId) (v2.1.0)

Look up a receipt by ID. Convenience wrapper around verify({ receiptId }) that returns just the receipt object if valid. Throws CertNodeError with code 'not_found' if the receipt doesn't exist or is invalid. Verification is free; this does not consume API quota.

const receipt = await cert.getReceipt('uuid-here')
console.log(receipt.signedAt)
console.log(receipt.timestamps.bitcoin?.status) // 'anchored' | 'pending' | 'skipped'

cert.searchRegistry(input) (v2.1.0)

Search the org's signed receipts. Scoped to the API key's organization. Returns the structured export bundle that the dashboard uses — self-describing for compliance / eDiscovery hand-off.

interface SearchRegistryInput {
  q?: string         // substring against id / model / provider
  from?: string      // ISO date (signed_at >=)
  to?: string        // ISO date (signed_at <=, inclusive of full day)
  apiKeyId?: string  // filter to a single API key
  limit?: number     // default 100, max 10000
}

const results = await cert.searchRegistry({
  from: '2026-05-01',
  to: '2026-05-31',
  q: 'gpt-4o',
})

console.log(results.export.row_count)
for (const r of results.receipts) {
  console.log(r.id, r.signed_at, r.verify_url)
}

cert.getTrustScore(receiptId) (v2.1.0)

Compute a developer-facing trust score (0-100) from a receipt's verification signals. The score weights the cryptographic chain (signature 40 + RFC 3161 20

  • Bitcoin anchored 30 + age bonuses). NOT a regulatory or legal metric — a developer-facing convenience number. For legal admissibility framing, always cite the underlying receipt itself (designed for FRE 902(13)/(14) self-authenticating digital evidence).
const trust = await cert.getTrustScore('uuid-here')
console.log(trust.score)                       // 95
console.log(trust.signals.bitcoinAnchored)     // true
console.log(trust.signals.ageHours)            // 26.4

Errors

All errors throw CertNodeError:

import { CertNodeError } from '@certnode/sdk'

try {
  await cert.signAIOutput({ output: '...' })
} catch (err) {
  if (err instanceof CertNodeError) {
    console.log(err.code)    // e.g. 'free_tier_exceeded'
    console.log(err.status)  // HTTP status
  }
}

Common error codes:

  • missing_api_key — no apiKey passed to constructor
  • invalid_or_revoked_api_key — key revoked or malformed
  • free_tier_exceeded — over 100/mo without a subscription
  • content_required — empty content
  • content_too_large — over 1 MB
  • timeout — request exceeded timeoutMs

Links