AI Attestations
Seal what went into a model and what came out — one API call per output. After your model responds, POST the exact input, the exact output, and the model identity; you get back a signed, independently verifiable record and a public proof link you can hand to a customer, an auditor, or a regulator.
What an attestation is
Each attestation stores three SHA-256 hashes: input_hash over the exact input text, output_hash over the exact output text, and payload_hashover the canonical request body. The server then builds a canonical statement — the attestation id, type, all three hashes, the model context, and the timestamp — and signs it with your tenant's Ed25519 key. Records land in append-only storage where deletes are blocked at the database level, and every attestation gets a public proof link anyone can open, with no Invoance account.
Three content hashes
input_hash, output_hash, and payload_hash — SHA-256 over the exact input text, the exact output text, and the canonical request body. Recompute any of them yourself to check a record against text you hold.
Ed25519 signed
The server signs a canonical attestation statement with your tenant's Ed25519 key. The exact signed bytes, the signature, and the public key are stored on the record and returned by the API.
Public proof page
Every attestation resolves at invoance.com/proof/ai/{attestation_id} — the issuing organization, the three hashes, the model context, and the signature, openable by anyone with no account or API key.
Idempotent + deduped
Send an Idempotency-Key to make retries safe. Independently of the header, identical bodies hash to the same payload_hash and return 200 with status "duplicate" and the original attestation_id.
Before you begin
Attestation endpoints use the standard API scopes: a key needswrite to create attestations and readto fetch, list, and verify them. Authenticate withAuthorization: Bearer invoance_live_…or an X-API-Key header. Every example below is a complete request, swap invoance_live_xxx for your key.
https://api.invoance.com/v1Quick start
After the model responds, send one request with type (here "output"; also decision and approval), the exact payload.input and payload.output, and the model identity in context. An optional subject ties the record to a user or session, and an optional Idempotency-Key header makes retries safe. A 201 means the attestation is durably queued; identical bodies come back as 200 with status "duplicate" and the original id.
POST /v1/ai/attestationscurl -X POST https://api.invoance.com/v1/ai/attestations \
-H "Authorization: Bearer invoance_live_xxx" \
-H "Idempotency-Key: 7f4c1c9d-5b8a-4d42-9e0b-1f2a3b4c5d6e" \
-H "Content-Type: application/json" \
-d '{
"type": "output",
"payload": {
"input": "Summarize the attached Q2 report.",
"output": "Q2 revenue grew 14% quarter over quarter…"
},
"context": {
"model_provider": "openai",
"model_name": "gpt-4o",
"model_version": "gpt-4o-2024-11-20"
},
"subject": { "user_id": "user_123", "session_id": "sess_456" }
}'{
"attestation_id": "b7d266a0-4b8e-4b0e-9c6a-2f1d3e5a7c90",
"created_at": "2026-07-04T12:00:00Z",
"input_hash": "9a0364b9e99bb480dd25e1f0284c8555…",
"output_hash": "50d858e0985ecc7f60418aaf0cc5ab58…",
"payload_hash": "873ac9ffea4dd04fa719e8920cd6938f…",
"status": "accepted"
}Retrieve the stored attestation with its three hashes, the exact canonical bytes that were signed (signed_payload), the Ed25519 signature, and the signing public_key. Persistence is asynchronous, so a GET immediately after the 201 can return 404 for a moment while the record commits.
GET /v1/ai/attestations/:attestation_idcurl https://api.invoance.com/v1/ai/attestations/b7d266a0-4b8e-4b0e-9c6a-2f1d3e5a7c90 \
-H "Authorization: Bearer invoance_live_xxx"{
"attestation_id": "b7d266a0-4b8e-4b0e-9c6a-2f1d3e5a7c90",
"attestation_type": "output",
"attestation_hash": "873ac9ffea4dd04fa719e8920cd6938f…",
"input_hash": "9a0364b9e99bb480dd25e1f0284c8555…",
"output_hash": "50d858e0985ecc7f60418aaf0cc5ab58…",
"signed_payload": "7b2276223a312c2261747465737461…",
"signature": "6ac1d2f0…",
"public_key": "3ba1c9e4…",
"signature_alg": "ed25519",
"model_provider": "openai",
"model_name": "gpt-4o",
"model_version": "gpt-4o-2024-11-20",
"retention_policy": "standard",
"created_at": "2026-07-04T12:00:00Z",
"organization": { "name": "Acme AI", "primary_domain": "acme.ai", "domain_verified": true }
}Every attestation resolves at https://invoance.com/proof/ai/{attestation_id}. Anyone can open it — no Invoance account, no API key. The page shows the issuing organization, the three hashes, the model context, and the signature, and lets a visitor submit a recomputed hash against the record. The underlying data endpoint is public too (IP rate-limited).
GET /v1/proof/ai/:attestation_id# public endpoint — no API key needed
curl https://api.invoance.com/v1/proof/ai/b7d266a0-4b8e-4b0e-9c6a-2f1d3e5a7c90{
"organization": { "name": "Acme AI", "primary_domain": "acme.ai", "domain_verified": true },
"attestation": {
"attestation_id": "b7d266a0-4b8e-4b0e-9c6a-2f1d3e5a7c90",
"attestation_type": "output",
"input_hash": "9a0364b9e99bb480dd25e1f0284c8555…",
"output_hash": "50d858e0985ecc7f60418aaf0cc5ab58…",
"payload_hash": "873ac9ffea4dd04fa719e8920cd6938f…",
"model_provider": "openai",
"model_name": "gpt-4o",
"model_version": "gpt-4o-2024-11-20",
"attestation_hash": "873ac9ffea4dd04fa719e8920cd6938f…",
"signature_alg": "ed25519",
"public_key": "3ba1c9e4…",
"signature": "6ac1d2f0…",
"created_at": "2026-07-04T12:00:00Z"
}
}Recompute SHA-256 over text you hold — the output your user saw, the input you sent, or the raw canonical body — and submit it as content_hash (64 hex characters). The server compares it against the anchored attestation_hash, input_hash, output_hash, and payload_hashand tells you which field matched. If the text changed by even one byte, the hash won't match.
POST /v1/ai/attestations/:attestation_id/verifyHASH=$(printf '%s' 'Q2 revenue grew 14% quarter over quarter…' \
| shasum -a 256 | cut -d' ' -f1)
curl -X POST https://api.invoance.com/v1/ai/attestations/b7d266a0-4b8e-4b0e-9c6a-2f1d3e5a7c90/verify \
-H "Authorization: Bearer invoance_live_xxx" \
-H "Content-Type: application/json" \
-d "{ \"content_hash\": \"$HASH\" }"{
"attestation_id": "b7d266a0-4b8e-4b0e-9c6a-2f1d3e5a7c90",
"match_result": true,
"matched_field": "output_hash",
"anchored_hash": "50d858e0985ecc7f60418aaf0cc5ab58…",
"submitted_hash": "50d858e0985ecc7f60418aaf0cc5ab58…",
"anchored_at": "2026-07-04T12:00:00Z"
}Good to know
- 201 means durably queued. Persistence is asynchronous — the hashes come back immediately, but a GET right after the 201 can return 404 for a moment while the writer commits the row.
- Duplicates are free. An identical body hashes to the same
payload_hash, so re-sending returns 200 with status"duplicate"and the originalattestation_id. Retries with the sameIdempotency-Keyreplay the original response for 24 hours; the same key with a different body is rejected with 409. - Signature checks fetch from the server. The SDKs'
verify_signature()/verifySignature()retrieve the record from the API and check the Ed25519 signature against the public key embedded in that response — that proves the record is internally consistent, not that the server is honest. For a stronger check, compare the record's key against your published key fromGET /keys/{your-domain}. Fully offline verification without any server fetch is currently available for audit events, not attestations. - Plan allowances. Attestations are included on every plan: developer 50/month, builder 5,000, growth 30,000, compliance 500,000, enterprise unlimited.