InvoanceInvoance
Log inStart free
Developers
Search docs…⌘K
Getting started
OverviewConceptsAuthenticationCreate an API key
API reference
EndpointsErrors
Audit Logs
Quick startIntegrationsEmbeddable viewerEvent schemaExporting eventsSDK reference
AI Attestations
Quick startAttestation schemaVerification & proofSDK reference
Events
OverviewSDK reference
Documents
OverviewSDK reference
Traces
OverviewSDK reference
SDKs
PythonNode.jsGoJavaRubyRust.NETPHPcURL
Verification
How it works
Support
API FAQ

Embeddable viewer

@invoance/audit-viewer puts the audit log inside your own product (say, admin.yourapp.com/audit): the same signed event table, filters, export, and in-browser Ed25519 tamper test as the hosted portal, rendered as a native React component in your DOM. No iframe, no styling conflicts, and the cryptographic verification runs in your customer's browser, so the proof never depends on trusting the page that renders it.

Signed event table

Actor, targets, action, and gap-free sequence numbers, with filters, keyset paging, CSV/JSON export, and 15-second live refresh.

In-browser tamper test

A detail drawer with the raw signed event: your customer edits any field and watches the Ed25519 verification flip from Authentic to Tampered.

Stream config screen

Mint the session with intent log_streams and the same component renders the SIEM webhook destination screen instead.

Before you begin

  • An API key with the audit scopes (create one) and at least one audit org receiving events.
  • React 18 or newer. The package has no other runtime dependencies.
  • No Tailwind required: the stylesheet ships compiled, prefixed, and themed by CSS variables.
1Install the package
npm install @invoance/audit-viewer
2Add a token endpoint to your backend

The component authenticates with a short-lived, org-scoped portal session that your backend mints for whichever of your customers is signed in. This is the one server-side piece.

The Invoance API key must never reach the browser. Mint server-side and return only the one-time token; it is useless for anything except opening this one organization's viewer.
// app/api/audit-portal-token/route.ts (Next.js example; any backend works)
import { InvoanceClient } from "invoance";

const client = new InvoanceClient({ apiKey: process.env.INVOANCE_API_KEY });

export async function POST() {
  const organizationId = await currentCustomerOrgId(); // however your app resolves it

  const session = await client.audit.portalSessions.create({
    organization_id: organizationId,
    intent: "audit_logs",
    session_duration_seconds: 3600,
  });

  return Response.json({ token: session.token });
}

Every SDK exposes the same call; in Python it is client.audit.portal_sessions.create(...). Keep session_duration_seconds short: the component re-mints through your endpoint automatically when it expires.

3Render the component
"use client";

import { AuditLogViewer } from "@invoance/audit-viewer";
import "@invoance/audit-viewer/styles.css";

export default function AuditPage() {
  return (
    <AuditLogViewer
      getPortalToken={async () => {
        const r = await fetch("/api/audit-portal-token", { method: "POST" });
        return (await r.json()).token;
      }}
    />
  );
}

getPortalToken is a callback, not a static prop, so expiry never strands the visitor. In the Next.js App Router the package already carries the "use client" banner, so you can import it from a server component tree. In Vite or CRA, mount it anywhere; only the fetch to your own token endpoint matters.

4Verify it works

Open the page as a signed-in customer. You should see their organization's events with your issuer branding in the header. Click any row and press Verify signature: the verdict should read Authentic. Now add a character to any field in the editor and verify again: it flips to Tampered, computed entirely in the browser. That is the demo worth showing your customers.

Props

PropDefaultWhat it does
getPortalToken-Async callback returning a fresh one-time portal token from your backend. Re-invoked automatically when the session expires.
tokenFromUrlfalseRead and strip a one-time ?token= from the page URL (hosted-page style).
persistSessionfalseCache the session JWT in sessionStorage so a refresh survives without a new token.
baseUrlhttps://api.invoance.comAPI origin; point it at a dev backend while developing.
pageSize25Initial rows per page (25, 50, or 100); the visitor can change it.
autoRefreshtrueQuietly re-pull page 1 every 15 seconds while idle.
theme-CSS-variable overrides, e.g. { variables: { background: "240 6% 12%" } }.
className-Extra class(es) on the root element.
onSessionExpired-Called when the session cannot be renewed.

Theming

Nine CSS variables (HSL triples, shadcn-style) drive every color. Override them on :root, on any ancestor of the viewer, or through the theme prop; bare names get the --inv- prefix automatically. A dark embed is three lines:

<AuditLogViewer
  getPortalToken={getPortalToken}
  theme={{ variables: { background: "240 6% 12%", foreground: "0 0% 98%", border: "240 6% 20%", muted: "240 5% 16%", popover: "240 6% 12%" } }}
/>
VariableDefault (light)
--inv-background0 0% 100%
--inv-foreground240 10% 8%
--inv-border240 6% 90%
--inv-muted240 4% 95%
--inv-popover0 0% 100%
--inv-popover-foreground240 10% 8%
--inv-success161 94% 30%
--inv-danger0 72% 51%
--inv-warning32 95% 44%

Sessions and failure modes

  • The exchanged JWT is org-scoped: it can only ever read the one organization the session was minted for. Portal traffic is rate-limited per visitor IP and never counts against your API budget.
  • On a 401 mid-session the component calls getPortalToken once and retries; if that fails it shows a clear expiry message and calls onSessionExpired.
  • A rate-limited exchange (many visitors behind one office NAT clicking at once) retries automatically honoring Retry-After; the one-time link is not consumed by a rate-limit rejection.
  • In browsers whose Web Crypto lacks Ed25519, the tamper test still checks the hash and reports the signature as not verifiable in this browser, distinct from a failed verification.
  • Events return context and metadata verbatim; whoever can render the embed can read them. Your tenant id is never exposed.

The mint endpoint is documented under Audit Logs endpoints, and the quick start covers sending the events the viewer displays. Source and issues: github.com/Invoance/invoance-audit-viewer.

Invoance

Neutral digital proof infrastructure for business. Tamper-evident, independently verifiable records.

Subscribe to our newsletter

Products
Platform
How It Works
Developers
Verify
Resources
Help & Legal
Products
  • Event Ledger
  • Document Anchoring
  • AI Attestation
  • Audit Logs
Platform
  • Why Invoance
  • For Compliance Teams
  • For Finance Teams
  • Pricing
How It Works
  • Overview
  • Event Ledger
  • Document Anchoring
  • AI Attestation
Developers
  • Overview
  • Endpoints
  • Authentication
  • Concepts
Verify
  • Verify Document
  • Verify AI Attestation
  • Verify Event
  • Verify Trace
Resources
  • All Resources
  • SOC 2 Guide
  • HIPAA Guide
  • ISO 27001 Guide
Help & Legal
  • Support
  • Status
  • Verification Help
  • FAQ

Invoance provides technical verification and proof infrastructure for digital records. Invoance does not issue legal, financial, or regulatory advice.

Records anchored through Invoance are cryptographically signed and tamper-evident by design. Invoance does not verify the accuracy, legality, or authenticity of document contents, only that a record existed in a specific form at a specific time. Verification links are publicly resolvable and do not require authentication. Invoance does not act as a custodian of funds, a legal authority, or a regulated financial entity. Use of Invoance does not constitute legal compliance. Consult qualified counsel for your specific obligations.

© 2025 – 2026 Invoance, Inc. All rights reserved.••