First Seal
Seal a Fact in 5 Minutes
Audience: CTO · Staff Engineer · SRE
One Endpoint
POST /v2/streams/{stream_id}/facts
Content-Type: application/jsonA 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.
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.
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"
}What Happened
- Horizon assigned sealed_at_ms (authoritative timestamp)
- Horizon computed fact_hash from a deterministic representation of the fact
- Horizon chained to previous fact via prev_hash
- Horizon stored the fact (append-only)
Horizon did not interpret custom_payload. That's your data.
Idempotency
Add client_ref to make the request idempotent:
{
"tenant_id": "acme-corp",
"actor": "ops-lead@acme-corp.com",
"client_ref": "incident-2024-01-26-stop-001",
"custom_payload": { ... }
}Same client_ref → same fact returned. No duplicate sealing.
Storage Guarantees
| Property | Guarantee |
|---|---|
| Append-only | Facts cannot be modified or deleted |
| Hash chain | Each fact links to previous via prev_hash |
| Tamper detection | Recompute hashes to detect modification |
| Tenant isolation | Facts scoped by tenant_id |
| Proof authority | sealed_at_ms assigned by Horizon |
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
Verify Chain Integrity
POST /v2/streams/{stream_id}/verifyReturns { "valid": true } if hash chain is intact.
Verification recomputes hashes and signatures. It does not interpret facts or assert correctness.