Core concepts
Understanding how Invoance works at the cryptographic level. These concepts underpin every anchored event, every signature, and every independent verification.
Canonical payload
Before hashing or signing, every submitted record is normalized into a deterministic canonical form. This ensures that the same logical record always produces the same hash, regardless of whitespace or encoding differences in the original request.
Invoance uses two canonicalization strategies depending on the resource type:
Event payloads are recursively sorted by key before serialization. This means key order in your request does not matter, the same logical payload always produces the same canonical form.
Attestation and document payloads use a fixed struct field order defined server-side. The canonical struct includes internal fields (attestation_id, tenant_id, hashes, timestamps) that your request does not contain, these are added by the server at ingestion time.
// Input (any key order)
{ "data": { "id": "inv_9f3a", "amount": 14200 }, "type": "invoice.approved" }
// Canonical form (keys sorted recursively, whitespace stripped)
{"data":{"amount":14200,"id":"inv_9f3a"},"type":"invoice.approved"}
// SHA-256 of canonical form
→ 9f3ac21e4b7d…// Server builds the canonical struct with internal fields:
{
"v": 1,
"attestation_id": "9549c332-a52b-…",
"tenant_id": "cf912d40-865c-…",
"attestation_type": "output",
"input_hash": "2f096d5e…",
"output_hash": "8a331903…",
"payload_hash": "8c741766…",
"model_provider": "openai",
"model_name": "gpt-4.1",
"model_version": "2026-01-01",
"created_at": "2026-03-06T03:57:29.529647Z"
}
// This entire struct is serialized, then Ed25519-signedContent hashing
Every anchored record is reduced to one or more SHA-256 hashes. These hashes are the immutable fingerprints of the record, they are what verification resolves against.
Each resource type computes multiple independent hashes for different verification and deduplication purposes:
input_hash, SHA-256 of the input text aloneoutput_hash, SHA-256 of the output text alonepayload_hash, SHA-256 of the entire canonical request body (used for deduplication)payload_hash, SHA-256 of the canonicalized payloadrequest_hash, SHA-256 of event_type + event_time + payload (used for deduplication)event_hash, SHA-256 of the full event recorddocument_hash, SHA-256 of the original document bytes (provided by the client at anchor time)Ed25519 signing
After canonicalization, Invoance signs the full canonical payload bytes using Ed25519, a modern, high-performance elliptic curve signature scheme. The signature proves the record was issued by the stated tenant's key and that no field has been altered since ingestion.
Immutability
The Invoance ledger is append-only by design. Once an event is anchored, it cannot be modified or deleted, not by your system, not by Invoance operators. This constraint is enforced at the database level, not just in application logic.
Access tiers and retention
Rather than deleting records when a retention period expires, Invoance seals them. Sealed records remain in the database to preserve the cryptographic proof chain, but they are hidden from standard read operations.
Independent verification
Any third party can verify an anchored record without an API key, without an Invoance account, and, using the public key and signed_payload alone, without contacting Invoance at all. Verification is a mathematical operation, not a trust assertion.
1. Retrieve the proof
GET https://invoance.com/proof/{event_id}
→ { signed_payload, signature, public_key, anchored_at, ... }
2. Verify the Ed25519 signature (strongest)
Ed25519.verify(public_key, signed_payload, signature)
→ if true, no field has been tampered with
3. Recompute the content hash (optional, content-level)
SHA-256(canonical(original_payload))
→ must match the payload_hash in the signed_payload
4. Confirm the public key against the tenant domain (optional)
GET https://api.invoance.com/keys/{tenant_domain}
→ cross-reference public_key against the tenant registryverify_signature() and verify_payload() methods that automate this process.Tenants and domain verification
Every Invoance account belongs to a tenant, an isolated organizational unit with its own keypair, event ledger, and verification namespace. Tenants verify ownership of their domain via DNS TXT record, which binds their public key to a publicly auditable domain identity.
// DNS TXT record to add
invoance-verify=<your_verification_token>
// Once verified, your domain appears in proof responses
{
"tenant_domain": "acme.com",
"public_key": "invoance:pk_tenant_7b1c"
}