@certivu/sdk
v2.6.0
Published
Official SDK for Certivu — quantum-resistant AI content provenance
Maintainers
Readme
@certivu/sdk
Official SDK for Certivu — quantum-resistant provenance for AI-generated content.
Certivu signs AI-generated content with ML-DSA (NIST FIPS 204) cryptographic signatures and invisible frequency-domain watermarks. Anyone can verify signed content without an account.
Install
npm install @certivu/sdk
# or
bun add @certivu/sdkRequires Node.js 18+ (uses built-in fetch, Blob, crypto).
Quickstart
import { CertivuClient } from '@certivu/sdk'
const certivu = new CertivuClient({
apiKey: 'ctv_key_abc123',
generatorId: 'gen_xyz',
})
// Sign AI-generated content — returns the signed file + token
const { token, record_id, signedContent } = await certivu.sign({
content: imageBuffer, // Buffer or Uint8Array (image, audio, or text)
model: 'stable-diffusion-xl',
format: 'image', // optional — auto-detected from magic bytes if omitted
})
// signedContent is a Uint8Array — serve this, it has provenance embedded
// Verify — token optional, extracted automatically from XMP or watermark
const result = await certivu.verify({ content: imageBuffer })
if (result.authentic && result.confidence === 'high') {
console.log('Verified:', result.provenance?.org, result.provenance?.signed_at)
}Get your API key and generator credentials at dashboard.certivu.ai.
API Reference
new CertivuClient(config)
| Field | Type | Required | Description |
|---|---|---|---|
| apiKey | string | Yes | API key from the dashboard (ctv_key_...) |
| generatorId | string | No | Default generator ID for sign calls |
| baseUrl | string | No | Override API base URL (default: https://api.certivu.ai) |
certivu.sign(input)
Signs AI-generated content server-side — watermarking, hashing, and ML-DSA signing all happen in the API. Accepts images (JPEG/PNG/WebP), audio (MP3/FLAC/WAV), and text (PDF/HTML/plain text). Returns the signed file with provenance embedded.
const { token, record_id, signedContent, format } = await certivu.sign({
content: fileBuffer, // Uint8Array | Buffer
model: 'stable-diffusion-xl', // model identifier
generatorId: 'gen_xyz', // overrides config.generatorId
format: 'image', // optional — 'image' | 'audio' | 'text', auto-detected if omitted
})
// signedContent — Uint8Array with provenance embedded (XMP / ID3 / meta tag / ZWC)
// format — the detected/confirmed format string
// watermarkedContent — alias for signedContent, kept for backwards compatibilityUpload limit: 50 MB.
certivu.verify(input)
Verifies content authenticity. Token is optional — extracted automatically from XMP metadata or the frequency-domain watermark.
const result = await certivu.verify({
content: imageBuffer, // Uint8Array | Buffer
token: 'ctv_...', // optional
})Response shape:
{
authentic: boolean,
tampered: boolean,
confidence: 'high' | 'medium' | 'low' | 'none',
token_source: 'provided' | 'xmp' | 'watermark' | 'phash',
format?: 'image' | 'audio' | 'text',
signals: {
watermark_found: boolean,
record_found: boolean,
signature_valid: boolean,
phash_match?: boolean,
},
provenance: {
org: string,
model: string,
signed_at: string,
} | null,
reason?: string,
}| Confidence | Meaning |
|---|---|
| high | Watermark + record + signature all valid |
| medium | Record + signature valid, no watermark |
| low | Partial signals |
| none | No provenance found — no claim either way |
Absence of provenance does not imply human origin.
certivu.verifyBatch(items)
Verify up to 50 items in a single request.
const { results } = await certivu.verifyBatch([
{ content: image1, token: token1 },
{ content: image2 },
])certivu.getAuditLog(options?)
const { events, total } = await certivu.getAuditLog({ page: 1, limit: 50 })certivu.getTokenStatus(token)
Lightweight CDN-cacheable status lookup — no image upload needed.
const status = await certivu.getTokenStatus('ctv_7f3kx9mq2...')
// { generator_status: 'active' | 'revoked', model, signed_at, org_id }certivu.getAnalyticsOverview(days?)
Verification analytics summary. Plan-gated: Free = 7-day, Starter = 30-day, Growth+ = 90-day.
const overview = await certivu.getAnalyticsOverview(30)
// { total_verifications, tamper_count, authentic_count, daily_trend, top_records, period_days }certivu.getRecordAnalytics(recordId)
Per-record verification drill-down. Growth+ required.
const record = await certivu.getRecordAnalytics('rec-uuid')
// { confidence_breakdown: { high, medium, low, none }, recent_events, ... }certivu.listWebhooks()
const { endpoints, webhooks_enabled } = await certivu.listWebhooks()certivu.createWebhook(input)
Register a new HTTPS endpoint. Growth+ required. The secret in the response is shown once.
const endpoint = await certivu.createWebhook({
url: 'https://your-app.example.com/certivu',
events: ['record.created', 'verify.tamper_detected', 'quota.warning'],
})certivu.deleteWebhook(webhookId)
await certivu.deleteWebhook('webhook-uuid')Error handling
try {
await certivu.sign({ content, model: 'sdxl' })
} catch (e) {
if (e instanceof Error) {
console.error(e.message)
}
}| Status | Meaning |
|---|---|
| 400 | Validation error |
| 401 | Bad API key |
| 402 | Quota exhausted (free tier) |
| 403 | Generator doesn't belong to your org |
| 404 | Generator not found or revoked |
| 413 | Upload exceeds 50 MB limit |
Docs
Full documentation at docs.certivu.ai.
