Install
Two ways in, and neither asks you to change how your agent is built. Install the SDK for one-call recording, or point an OpenTelemetry exporter you already run at the vault. Both produce the same tamper-evident, verifiable evidence.
Step 1: Get your credentials
From the dashboard you need three values. Your workspace id and an API key both come from Settings, API keys. Your data key is the 32-byte key generated when you set the workspace up.
The data key is the one that matters. It never reaches us, and it is what your payloads are encrypted under, so we store ciphertext we cannot read. If you lose it, your evidence stays sealed and nobody, including us, can open it. Keep it in your secret manager alongside your other production credentials.
Step 2: Send your events
Pick one of the two paths below. You do not need both, and both produce the same tamper-evident, verifiable evidence. Everything from here down in this step is specific to the path you choose; Step 3 applies to either one.
The SDK
Best when you want the strongest privacy guarantee and do not mind adding one dependency. Install it in the service that runs your agent.
npm install @getjuratify/sdkConstruct one client for the process and call record wherever something worth proving happens. Events are hashed, chained, and encrypted locally, then queued, so recording stays off your critical path.
import { Juratify } from "@getjuratify/sdk";
const client = new Juratify({
apiKey: process.env.JURATIFY_API_KEY!,
workspaceId: process.env.JURATIFY_WORKSPACE_ID!,
// 32-byte data key, raw bytes or base64. Never leaves the process.
dataKey: process.env.JURATIFY_DATA_KEY!,
});
await client.record(
"prompt",
{ input: "what is the capital of France", model: "gpt-5" },
{ sessionId: "sess-123" },
);
// Before the process exits, drain anything still queued.
await client.flush();A sessionId groups related events into one chain, so use a stable value for the life of a conversation or task run. Call flush before your process exits, otherwise queued events can be lost with it.
Or wrap a model instead
If your model exposes doGenerate or doStream, as the Vercel AI SDK does, you can capture prompts, completions, and tool calls without writing any record calls yourself. Recording failures are swallowed by design here, so instrumentation can never break the model call path.
import { wrapModel } from "@getjuratify/sdk";
const model = wrapModel(client, myModel, { sessionId: "sess-123" });OpenTelemetry
Best when you already emit traces and would rather not add a dependency. Keep your instrumentation and the GenAI semantic conventions, so chat calls, tool calls, and errors arrive as evidence without rewriting anything. There are two ways to connect.
Our span exporter (sealed in your process)
Drop our exporter into your existing tracer provider. It maps GenAI spans to events and seals each one locally through the same path as the SDK, so the vault still only ever sees ciphertext. This is the zero-knowledge OpenTelemetry path, and it takes the same three credentials as the SDK.
import { JuratifySpanExporter } from "@getjuratify/sdk";
import { BatchSpanProcessor } from "@opentelemetry/sdk-trace-base";
const exporter = new JuratifySpanExporter({
apiKey: process.env.JURATIFY_API_KEY!,
workspaceId: process.env.JURATIFY_WORKSPACE_ID!,
dataKey: process.env.JURATIFY_DATA_KEY!,
});
// Register it like any other span processor on your provider.
provider.addSpanProcessor(new BatchSpanProcessor(exporter));Set a juratify.session_id span attribute to group spans into one chain; without it each trace becomes its own session.
The raw OTLP endpoint (zero code, server-sealed)
If you would rather not add a dependency, point any OTLP exporter straight at the vault with two environment variables.
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=https://app.juratify.com/api/v1/otlp/traces
OTEL_EXPORTER_OTLP_HEADERS=authorization=Bearer <your API key>A stock exporter sends span attributes as plaintext, so on this path the vault reads the payload at ingestion and encrypts it at rest under a per-workspace key. Records are still hash-chained, receipted, and checkpointed identically. The difference is only where the sealing happens: use the exporter above if you need payloads sealed before they leave your process. See Security for the full comparison.
Step 3: Verify what you recorded
Export an evidence pack from the dashboard, then check it with the open-source verifier. This runs offline, needs no account, and talks to nothing, which is the point: your evidence stands up without us.
npm install -g @getjuratify/verify
juratify-verify evidence-pack.jsonIt exits 0 when every check passes, 1 when verification fails, and 2 for an operational problem such as an unreadable file, so it drops straight into CI. Add --json for a machine-readable report.
Where to go next
The evidence format specification documents the record structure, hash chain, and signatures, and the source is open if you would rather read the verifier than take our word for it. For how the sealing and checkpointing work, see Security.