First Seal

Seal a Fact in 5 Minutes

CTO · Staff Engineer · SRE

This page shows how to seal a fact technically. It does not explain how to interpret its meaning.

One Endpoint

POST /streams/{stream_id}/facts
Content-Type: application/json

A stream is identified by stream_id, provided by the client in the URL. If no stream with that ID exists, Horizon creates it implicitly when the first fact is sealed.

The only identifier you manage is stream_id; Horizon does not impose any business semantics on it.

One Request

{
  "tenant_id": "acme-corp",
  "actor": "ops-lead@acme-corp.com",
  "custom_payload": {
    "action": "stop_service",
    "context": "Memory leak confirmed"
  }
}

In production deployments, tenant_id is typically derived from authentication context rather than provided in the payload.

Your payload is opaque to Horizon. It is recorded exactly as provided.

One Response

{
  "fact_id": "fact-01HRX7G2NB",
  "stream_id": "stream-034",
  "tenant_id": "acme-corp",
  "actor": "ops-lead@acme-corp.com",
  "sealed_at_ms": 1706284801000,
  "custom_payload": {
    "action": "stop_service",
    "context": "Memory leak confirmed"
  },
  "fact_hash": "a1b2c3d4e5f6...",
  "prev_hash": "9f8e7d6c5b4a...",
  "parent_fact_id": "fact-01HRX7F1MA"
}

Fields such as fact_hash and prev_hash are used for integrity and verification, not business logic.

What Happened

Horizon did not interpret custom_payload. That's your data.

  1. Horizon assigned sealed_at_ms (authoritative timestamp)
  2. Horizon computed fact_hash from a deterministic representation of the fact
  3. Horizon chained to previous fact via prev_hash
  4. Horizon stored the fact (append-only)
See Verification

Idempotency

{
  "tenant_id": "acme-corp",
  "actor": "ops-lead@acme-corp.com",
  "client_ref": "incident-2024-01-26-stop-001",
  "custom_payload": { ... }
}

Add client_ref to make the request idempotent:

Same client_ref → same fact returned. No duplicate sealing.

Idempotency does not alter the proof. It prevents duplication only.

Storage Guarantees

PropertyGuarantee
Append-onlyFacts cannot be modified or deleted
Hash chainEach fact links to previous via prev_hash
Tamper detectionRecompute hashes to detect modification
Tenant isolationFacts scoped by tenant_id
Proof authoritysealed_at_ms assigned by Horizon

These properties hold even if the client system is compromised, because any modification is detectable.

What Horizon Does Not Do

  • No interpretation·custom_payload is opaque
  • No workflow·No states, no transitions, no approvals
  • No validation·Your payload, your schema
  • No business logic·Seal facts, nothing else
For the semantic boundary of what a sealed fact proves and does not prove, see Proof Semantics

Verify Chain Integrity

POST /streams/{stream_id}/verify

Returns { "valid": true } if hash chain is intact.

Verification recomputes hashes and signatures. It does not interpret facts or assert correctness.

Verification results only attest that the recorded sequence hasn't been tampered with.