SDKs and Libraries
Official client libraries for Python and Node.js, plus raw cURL examples for any language. Each SDK provides typed methods for every API endpoint, client-side hash verification, and Ed25519 signature validation with zero vendor lock-in.
Installation
pip install invoanceInitialize the client
Set INVOANCE_API_KEY in your environment and the client picks it up automatically. All subsequent calls are scoped to your organization.
from invoance import InvoanceClient
# Reads INVOANCE_API_KEY from env automatically
async with InvoanceClient() as client:
result = await client.events.ingest(...)
# Or override explicitly
client = InvoanceClient(api_key="invoance_live_xxx")Events
Ingest an event
Records a business event in the append-only ledger.
result = await client.events.ingest(
event_type="policy.approval",
payload={
"policy_id": "pol_8472",
"approved_by": "risk_committee",
"decision": "approved",
},
)
print(result.event_id)Get an event
Retrieve a single event by ID.
event = await client.events.get("evt_01HX…")
print(event.event_type, event.payload_hash)List events
Paginated listing with optional filters.
page = await client.events.list(
page=1, limit=50, event_type="policy.approval"
)
for e in page.events:
print(e.event_id, e.event_type)Verify an event
Compare a hash or raw payload against the anchored event.
result = await client.events.verify(
"evt_01HX…",
payload_hash="a3f2b1c9d4e8f7…",
)
print(result.match_result) # TrueDocuments
Anchor a file
RecommendedPass a file path or raw bytes, the SDK reads it, computes the SHA-256 hash, and uploads the original bytes (stored encrypted) for later retrieval. Set skip_original to anchor the hash only without storing the file.
result = await client.documents.anchor_file(
file="./invoice.pdf",
document_ref="Invoice #1042",
event_type="invoice",
metadata={"amount": 5230, "currency": "USD"},
trace_id="9549c332-…", # optional, attach to a trace
)
print(result.event_id)result = await client.documents.anchor_file(
file="./invoice.pdf",
document_ref="Invoice #1042",
skip_original=True,
)
print(result.event_id)Anchor a hash
If you already have the SHA-256 hash, use the low-level method directly.
result = await client.documents.anchor(
document_hash="a94a8fe5ccb19ba61c4c0873d391e987…",
document_ref="Invoice #1042",
)
print(result.event_id)Get a document
Retrieve a document event by ID.
doc = await client.documents.get("9549c332-a52b-…")
print(doc.document_ref, doc.has_original)List documents
Paginated listing with optional filters.
page = await client.documents.list(page=1, limit=50)
for d in page.documents:
print(d.event_id, d.document_ref)Download original document
Retrieve the original file bytes (if uploaded during anchoring).
data = await client.documents.get_original("9549c332-a52b-…")
with open("invoice.pdf", "wb") as f:
f.write(data)Verify a document
Compare a hash against the anchored document.
result = await client.documents.verify(
"9549c332-a52b-…",
document_hash="a94a8fe5ccb19ba61c4c0873d391e987…",
)
print(result.match_result) # TrueAI Attestations
Create an attestation
Anchor an AI input/output pair with model context.
result = await client.attestations.ingest(
type="output",
input="What is the company refund policy?",
output="Our refund policy allows returns within 30 days...",
model_provider="openai",
model_name="gpt-4.1",
model_version="2026-01-01",
user_id="user_7b1c",
session_id="sess_4f9a",
trace_id="9549c332-…", # optional, attach to a trace
)
print(result.attestation_id, result.payload_hash)Get an attestation
Retrieve the full attestation record with cryptographic metadata.
att = await client.attestations.get("9549c332-a52b-…")
print(att.attestation_type, att.signature_alg)List attestations
Paginated listing with optional filters.
page = await client.attestations.list(
page=1, limit=50,
attestation_type="output",
model_provider="openai",
)
for a in page.attestations:
print(a.attestation_id, a.model_name)Get raw canonical payload
Retrieve the original JSON that was hashed and signed. Useful for independent verification.
raw = await client.attestations.get_raw("9549c332-a52b-…")
print(raw["type"], raw["payload"]["input"])Verify by hash
Compare a SHA-256 hash against the anchored attestation.
result = await client.attestations.verify(
"9549c332-a52b-…",
content_hash="8c74176675eed4e2ff88bc0182af…",
)
print(result.match_result, result.matched_field)Verify by raw payload
SDK onlyPass the raw payload directly, the SDK hashes it client-side and calls the verify endpoint. Accepts a dict/object, JSON string, or raw bytes.
result = await client.attestations.verify_payload(
"9549c332-a52b-…",
payload={
"type": "output",
"payload": { "input": "...", "output": "..." },
"context": { "model_provider": "openai", ... },
"subject": None,
},
)
print(result.match_result) # TrueVerify Ed25519 signature
SDK onlyFetches the attestation and verifies the Ed25519 signature entirely client-side using the public key. Proves no field has been tampered with, including the timestamp. Zero trust in the server required.
# Requires PyNaCl: pip install PyNaCl
result = await client.attestations.verify_signature("9549c332-a52b-…")
print(result.valid) # True
print(result.signed_data) # The exact JSON that was signed
print(result.signed_data["created_at"]) # Timestamp is coveredTraces
Create a trace
Create a new open trace to group events, documents, and AI attestations into a verifiable process proof.
result = await client.traces.create(
label="Vendor Onboarding, Acme Corp",
metadata={
"department": "procurement",
"initiated_by": "j.smith@acme.com"
}
)
print(result.trace_id)List traces
Paginated listing of traces with optional status filter.
page = await client.traces.list(page=1, limit=50, status="open")
for t in page.traces:
print(t.trace_id, t.label, t.status)Get a trace
Retrieve a single trace with event summaries.
trace = await client.traces.get("tr_abc123…")
print(trace.trace_id, trace.event_count, trace.status)Seal a trace
Initiate sealing to compute composite hash and lock the trace from further events.
result = await client.traces.seal("tr_abc123…")
print(result.status) # "sealing"
# Poll for completion:
while True:
trace = await client.traces.get("tr_abc123…")
if trace.status == "sealed":
breakExport proof bundle
Retrieve the complete proof bundle for a sealed trace with all events and signatures.
bundle = await client.traces.proof("tr_abc123…")
print(bundle.composite_hash, bundle.event_count)
for event in bundle.events:
print(event.event_id, event.signature)