Open source · Apache 2.0

Immutable history
for every entity.

Letopis stores every change to every object in your system — with tamper-evidentSHA-256 hash chains, point-in-time reconstruction, and conditional webhooks. REST + gRPC. Multi-tenant. Self-hosted.

letopis · quick start
# Set your API key from config.yaml
TOKEN=hm_dev_plaintext

# Ingest entity state — server computes the diff
curl -s -X POST \
  http://localhost:8080/api/v1/collections/crm.deals/entities/deal-1/state \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"state": {"title": "Acme Corp", "amount": 5000, "stage": "prospect"}}'

# Read full history
curl -s \
  http://localhost:8080/api/v1/collections/crm.deals/entities/deal-1/history \
  -H "Authorization: Bearer $TOKEN"

# Point-in-time: state at version 3
curl -s \
  "http://localhost:8080/api/v1/collections/crm.deals/entities/deal-1/state?version=3" \
  -H "Authorization: Bearer $TOKEN"
Built with
Go 1.25+·MongoDB 7+·Redis 6+·gRPC + REST·Apache 2.0

Everything you need for audit-grade history

From tamper-evident storage to conditional webhooks — Letopis gives you a complete, production-ready audit log infrastructure.

Hash-chain integrity

SHA-256-linked events make silent tampering or deletion immediately detectable. Verify any entity's complete history with the :verify endpoint.

Point-in-time reads

Reconstruct the exact state of any entity at any past version or timestamp. Snapshots keep read latency under 7 ms p99 for 10 000-version histories.

Two ingest modes

POST a full object state and let Letopis compute the diff, or POST a ready-made diff directly. Both produce identical, queryable events.

Three reliability modes

Choose per-request: strict (sync 201), durable (Redis-queued 202), orfast (in-memory 202). Ticket polling confirms async writes.

Rules + webhooks

Define conditional rules that fire signed, retried HTTP callbacks whenever matching changes arrive. Dead-letter queue for failed deliveries.

Multi-tenancy

Hard MongoDB-database isolation per tenant. API-key-based routing — no tenant ID in URLs. Per-tenant config, rules, and reliability defaults.

Three steps from write to query

01

Ingest

Your system POSTs the entity's current state or a ready-made diff. Letopis validates, normalizes, and queues the write with your chosen reliability mode. An optional idempotency key prevents duplicate events on retry.

02

Store

Events are written append-only to MongoDB. The SHA-256 hash-chain plugin links each event to the previous one. Every 100 events a snapshot materializes the current state for fast reads. Async modes use Redis Streams for durability.

03

Query

Read current state, paginated history, or reconstruct state at any past version or timestamp. Business flows link events across collections into causal DAGs. Export diffs as JSON Patch (RFC 6902) for compatibility.

Up and running in minutes

1

Build from source

Prerequisites: Go 1.25+, MongoDB 7+, Redis 6+.

2

Configure tenants

Copy config.example.yaml, set your tenant ID and API key (SHA-256 hash preferred).

3

Ingest & query

Send your first state change via REST. Use GET /history to verify it was stored.

# Or download a prebuilt binary: github.com/max-trifonov/letopis/releases
# Clone and build
git clone https://github.com/max-trifonov/letopis.git
cd letopis && make build

# Configure (edit tenants.*.keys)
cp config.example.yaml config.yaml

# Run
./bin/letopis serve

# Or with Docker Compose
docker compose -f docker-compose.dev.yml up --build

Built for teams that need accountability

📊

CRM & Sales

Full audit trail for every deal, contact, and pipeline stage change. Know exactly who moved the deal — and when.

📄

Contracts & Documents

Tamper-evident version history for every agreement. Reconstruct any clause at any revision for dispute resolution.

💰

Finance & Compliance

Immutable ledger for balance changes, transaction metadata, and account state. Ready for regulatory audit by design.

⚙️

Config & Infrastructure

Track every change to your configuration, infrastructure state, and deployment parameters with author attribution.

Choose the right guarantees per write

Override reliability at the collection level or per individual request with the X-Letopis-Mode header.

ModeResponseGuaranteeUse case
strict201 CreatedWritten to MongoDB before respondingAudited writes, financial records
durable202 AcceptedQueued to Redis Streams; worker writes asyncDefault — survives API restarts
fast202 AcceptedIn-memory queue; maximum throughputBulk imports, non-critical streams

Async modes return a ticket_id. Poll GET /tickets/{id} to track:accepted → processing → stored. Tickets expire after 24 h by default.

Built in the open

Letopis is Apache 2.0 licensed. Contributions are welcome — every commit needs a DCO sign-off. Discuss significant changes in an issue before investing in code. The public Go API is pkg/ext; internal packages are not stable.

Apache 2.0
License
Go 1.25+
Language
DCO
Sign-off required
pkg/ext
Stable public API

Ready to track every change?

Install Letopis in minutes and start building audit-grade history into your application.