Docs · SDKs
Ruby SDK
Install the Ruby SDK, build a client, see every method with a Ruby sample, and verify records offline.
Install
Ruby
invoance on RubyGems.
Ruby 3.0 or later. Standard library only (net/http, json, openssl, digest); responses are Hashes with string keys.
Terminal
gem install invoance
# or in a Gemfile
gem "invoance"
Client
api_key | The API key. Falls back to INVOANCE_API_KEY. |
|---|---|
base_url | API host. Falls back to INVOANCE_BASE_URL, then https://api.invoance.com. |
api_version | Path prefix put before every request path. Default v1. |
| timeout | Per-request timeout in seconds. Default 30; past it the call raises Invoance::TimeoutError. |
idempotency_key | Default Idempotency-Key header for every mutating request; a per-call key wins. |
extra_headers | Headers merged into every request. |
| Retries | None. Each request is sent once; on TimeoutError or NetworkError, retry it yourself with the same idempotency_key. |
Ruby
require "invoance"
# Reads INVOANCE_API_KEY and INVOANCE_BASE_URL from the environment.
client = Invoance::Client.new
# Or pass options.
configured = Invoance::Client.new(
api_key: "invoance_live_...",
base_url: "https://api.invoance.com",
timeout: 60
)
# GET /v1/me checks no scope, so any live key passes. Never raises.
result = client.validate
puts result["valid"], result["reason"]
Methods
Every endpoint with a Ruby sample, by resource. Open a row for the sample; the link opens the endpoint card with its fields, response and errors.
EventsReference
POST/v1/events
Ruby
require "invoance"
# Reads INVOANCE_API_KEY from the environment.
client = Invoance::Client.new
result = client.events.ingest(
event_type: "policy.approval",
event_time: "2026-09-22T08:14:07Z",
payload: {
"policy_id" => "pol_8472",
"approved_by" => "risk_committee",
"decision" => "approved"
},
idempotency_key: "policy-approval-pol_8472"
)
puts result["event_id"], result["ingested_at"]
GET/v1/events
Ruby
require "invoance"
# Reads INVOANCE_API_KEY from the environment.
client = Invoance::Client.new
page = client.events.list(page: 1, limit: 50, event_type: "policy.approval")
puts page["total"], page["has_more"]
page["events"].each do |event|
puts [event["event_id"], event["ingested_at"], event["payload_hash"]].join(" ")
end
GET/v1/events/{event_id}
Ruby
require "invoance"
# Reads INVOANCE_API_KEY from the environment.
client = Invoance::Client.new
event = client.events.get("7c1e4b52-9a0f-4d2e-b6f3-2f8a61c0d9e4")
puts event["event_type"], event["ingested_at"]
puts event["payload_hash"], event["event_hash"], event["request_hash"]
p event["payload"]
POST/v1/events/{event_id}/verify
Ruby
require "invoance"
# Reads INVOANCE_API_KEY from the environment.
client = Invoance::Client.new
result = client.events.verify(
"7c1e4b52-9a0f-4d2e-b6f3-2f8a61c0d9e4",
payload: {
"policy_id" => "pol_8472",
"approved_by" => "risk_committee",
"decision" => "approved"
}
)
puts result["match_result"], result["matched_field"]
puts result["anchored_hash"], result["submitted_hash"], result["anchored_at"]
DocumentsReference
POST/v1/document/anchor
Ruby
require "digest"
require "invoance"
document_hash = Digest::SHA256.file("./INV-2026-0917.pdf").hexdigest
# Reads INVOANCE_API_KEY from the environment.
client = Invoance::Client.new
result = client.documents.anchor(
document_hash: document_hash,
document_ref: "INV-2026-0917.pdf",
event_type: "invoice.issued",
metadata: {
"invoice_number" => "INV-2026-0917",
"amount" => 5230,
"currency" => "USD"
},
idempotency_key: "anchor-#{document_hash}"
)
puts "#{result["event_id"]} #{result["status"]}"
GET/v1/document
Ruby
require "invoance"
# Reads INVOANCE_API_KEY from the environment.
client = Invoance::Client.new
page = client.documents.list(limit: 25, date_from: "2026-09-01T00:00:00Z")
puts "#{page["total"]} #{page["has_more"]}"
page["documents"].each do |d|
puts "#{d["event_id"]} #{d["document_ref"]} #{d["has_original"]}"
end
GET/v1/document/{event_id}
Ruby
require "invoance"
# Reads INVOANCE_API_KEY from the environment.
client = Invoance::Client.new
doc = client.documents.get("7c1e4b52-9a0f-4d2e-b6f3-2f8a61c0d9e4")
puts "#{doc["document_hash"]} #{doc["has_original"]} #{doc["created_at"]}"
if doc["organization"]
puts "#{doc["organization"]["issuer_name"]} #{doc["organization"]["domain_verified"]}"
end
GET/v1/document/{event_id}/original
Ruby
require "invoance"
# Reads INVOANCE_API_KEY from the environment.
client = Invoance::Client.new
data = client.documents.get_original("7c1e4b52-9a0f-4d2e-b6f3-2f8a61c0d9e4")
File.binwrite("./INV-2026-0917.pdf", data)
puts data.bytesize
POST/v1/document/{event_id}/verify
Ruby
require "digest"
require "invoance"
document_hash = Digest::SHA256.file("./INV-2026-0917.pdf").hexdigest
# Reads INVOANCE_API_KEY from the environment.
client = Invoance::Client.new
result = client.documents.verify("7c1e4b52-9a0f-4d2e-b6f3-2f8a61c0d9e4", document_hash: document_hash)
puts "#{result["match_result"]} #{result["anchored_hash"]} #{result["anchored_at"]}"
AI AttestationsReference
POST/v1/ai/attestations
Ruby
require "invoance"
# Reads INVOANCE_API_KEY from the environment.
client = Invoance::Client.new
result = client.attestations.ingest(
type: "output",
input: "Summarize the termination clause in contract CT-8472.",
output: "Either party may terminate with 30 days written notice. Early termination fees do not apply after month 12.",
model_provider: "openai",
model_name: "gpt-4.1",
model_version: "2026-04-14",
subject: { user_id: "u_4821", session_id: "sess_9f3a", department: "legal" },
idempotency_key: "ct-8472-summary-1"
)
puts result["attestation_id"], result["payload_hash"]
GET/v1/ai/attestations
Ruby
require "invoance"
# Reads INVOANCE_API_KEY from the environment.
client = Invoance::Client.new
page = client.attestations.list(
limit: 50,
attestation_type: "output",
model_provider: "openai"
)
puts page["total"], page["has_more"], page["attestations"].length
GET/v1/ai/attestations/{attestation_id}
Ruby
require "invoance"
# Reads INVOANCE_API_KEY from the environment.
client = Invoance::Client.new
att = client.attestations.get("7c1e4b52-9a0f-4d2e-b6f3-2f8a61c0d9e4")
puts att["attestation_hash"], att["signature_alg"], att["public_key"]
GET/v1/ai/attestations/{attestation_id}/raw
Ruby
require "invoance"
# Reads INVOANCE_API_KEY from the environment.
client = Invoance::Client.new
raw = client.attestations.get_raw("7c1e4b52-9a0f-4d2e-b6f3-2f8a61c0d9e4")
puts raw["type"], raw["context"]["model_name"]
POST/v1/ai/attestations/{attestation_id}/verify
Ruby
require "invoance"
# Reads INVOANCE_API_KEY from the environment.
client = Invoance::Client.new
result = client.attestations.verify(
"7c1e4b52-9a0f-4d2e-b6f3-2f8a61c0d9e4",
content_hash: "c4efe15781214a84046ad7e0592977c634a5cf45f4c1e06160daf760a295a8df"
)
puts result["match_result"], result["matched_field"]
TracesReference
POST/v1/traces
Ruby
require "invoance"
# Reads INVOANCE_API_KEY from the environment.
client = Invoance::Client.new
trace = client.traces.create(
label: "Invoice batch 2026-09",
metadata: { "batch_id" => "b_4471", "region" => "eu-west" }
)
puts trace["trace_id"], trace["status"]
POST/v1/traces/{trace_id}/seal
Ruby
require "invoance"
# Reads INVOANCE_API_KEY from the environment.
client = Invoance::Client.new
sealed = client.traces.seal("7c1e4b52-9a0f-4d2e-b6f3-2f8a61c0d9e4")
puts sealed["status"], sealed["message"]
Audit LogsReference
POST/v1/audit/events
Ruby
require "invoance"
# Reads INVOANCE_API_KEY from the environment.
client = Invoance::Client.new
result = client.audit.events.ingest(
organization_id: "org_8472",
action: "user.signed_in",
occurred_at: "2026-09-22T08:14:07Z",
actor: { "type" => "user", "id" => "u_4821", "name" => "Ada Lovelace" },
targets: [{ "type" => "workspace", "id" => "ws_17" }],
context: { "location" => "203.0.113.10", "user_agent" => "Mozilla/5.0" },
metadata: { "method" => "sso", "mfa" => true },
idempotency_key: "signin-u_4821-2026-09-22T08:14:07Z"
)
puts result["event_id"], result["ingested_at"]
POST/v1/audit/orgs
Ruby
require "invoance"
# Reads INVOANCE_API_KEY from the environment.
client = Invoance::Client.new
org = client.audit.orgs.create(
organization_id: "org_8472",
name: "Acme Robotics"
)
puts org["id"], org["retention_days"]
PlatformReference
GET/v1/me
Ruby
require "invoance"
# Reads INVOANCE_API_KEY from the environment.
client = Invoance::Client.new
me = client.me
puts me["organization"]["primary_domain"]
puts me["api_key"]["scopes"].inspect
puts me["limits"]["rate_limit_per_sec"]
Verify offlineHow verification works
Two checks run without trusting the server: attestations.verify_signature fetches the record and checks its Ed25519 signature over signed_payload; Invoance::AuditVerify.verify_audit_event rebuilds the invoance.audit/1 bytes of an audit event and checks its signature. Pass public_key to pin the key from GET /keys/{domain} instead of the key on the row.
Ruby
require "invoance"
client = Invoance::Client.new
# AI attestation: Ed25519 over signed_payload, checked locally.
sig = client.attestations.verify_signature("a1d4f8c2-7b3e-4e9a-b5c6-0d2e8f4a7c19")
puts sig["valid"], sig["reason"]
# Audit event: canonical bytes rebuilt locally, signature checked
# against a pinned key (the public_key from GET /keys/{domain}, base64url decoded to hex).
pinned_hex_key = "d4443bd9d30ef4c2e0e5db03467e3c5c740358482c1a1e30cdb27a2e02a38176"
event = client.audit.events.get("aevt_01J8F3KQ2R7VWX9YB4ND6MCZAH")
result = Invoance::AuditVerify.verify_audit_event(event, public_key: pinned_hex_key)
puts result["valid"], result["reason"], result["key_source"] # pinned