Marturia

← Docs

Quickstart

From zero to a verified receipt. 15 minutes if you have a Python environment handy.

1. Get an account

Marturia is in closed beta. Request access at marturia.dev/#beta; once invited you'll get an email with a registration link. After verifying your email, you can sign in at marturia.dev/app/login.

2. Create a project and mint an API key

From the dashboard, click + New project. Each project gets its own ingest URL and per-key Ed25519 signing key — receipts emitted under one project are independent from any other project's chain.

Open the project, head to the API Keys tab, and click + New key. The plaintext key is shown once — copy it into your secrets store. It starts with mtu_live_.

3. Emit your first receipt

A "receipt" is a signed record of one agent decision. POST your decision payload to the receipts endpoint with the X-Marturia-Key header:

curl -sS -X POST https://marturia.dev/api/marturia/v1/receipts \
  -H "X-Marturia-Key: $MARTURIA_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "agent": "refund-router",
    "payload": {
      "op": "agent.decide",
      "action": "approve",
      "order_id": "12345",
      "amount_cents": 4900,
      "risk_score": 0.12,
      "reasoning": "trusted customer, low-risk merchant category"
    }
  }'

The response includes the receipt ID, the public key for the signing kid, the signed-bytes hash, and the chain pointer:

{
  "id": "rcpt_01J...",
  "receipt_seq": 1,
  "tenant_id": 1234,
  "agent_name": "refund-router",
  "signing_kid": "t1234-v1",
  "public_key": "MCowBQYDK2VwAyEAm...",
  "receipt_hash": "9f2c8e2a...",
  "prev_hash": null,
  "signature": "Ed25519:8a4f1c..."
}

4. Verify it offline

The point of Marturia is that auditors don't have to trust us. They install the open-source verifier from PyPI:

pip install marturia-verify
marturia-verify rcpt_01J...   # or pipe a receipt JSON to stdin

Output:

VALID
  tenant_id:       1234
  receipt_seq:     1
  signing_kid:     t1234-v1
  public_key:      OK
  signature:       OK (Ed25519)
  chain:           OK
  canonical_bytes: 387

Tamper with any byte of the payload, the public key, or the signature, and marturia-verify exits non-zero with the exact reason it broke. More on the verifier →

5. (Optional) Stream OTLP spans for the dashboard

If you instrument your agent with OpenTelemetry, point the exporter at Marturia's OTLP endpoint to also see latency/error charts in the dashboard. This is in addition to receipts — receipts are the regulator-facing artefact; spans are the operator-facing one.

from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter

exporter = OTLPSpanExporter(
    endpoint="https://marturia.dev/api/marturia/v1/traces",
    headers={"X-Marturia-Key": "mtu_live_..."},
)

What's next