General Liquidity
Operating

Webhooks

Outbound events, signed, and derived from the same record rather than emitted beside it.

Derived, not parallel

Events are produced from the signed record itself. That is the whole design decision: an event stream emitted separately from the audit trail will eventually disagree with it, and then you have two accounts of what happened and no way to choose.

Verifying what you receive

Every delivery carries a GL-Signature header of the form t=<unix seconds>,v1=<hex>. The hex is an HMAC-SHA256 over the ASCII string {t}.{raw body}, keyed by the endpoint's secret. Verify against the raw bytes you received, before parsing them.

The events

gate.decision
A decision was made, whatever its outcome.
intent.denied
A payment was refused.
approval.pending
A payment is waiting for a person.
payment.settled
Value moved.
audit.appended
The record grew.
memory.recorded · memory.consolidated · memory.erased · memory.tainted
Memory lifecycle, where a deployment runs a store.
  • Check the signature before parsing the body.
  • Treat delivery as at-least-once and make your handler idempotent on the event id.
  • Do not order your own state off arrival order. The record is the sequence.

Subscribing

Endpoint management is operator-signed, not an ordinary API call. An agent cannot register somewhere to send copies of your record.

HTTP
POST   /webhooks/endpoints        # { url, events[] } -> 201, secret shown once
GET    /webhooks/endpoints        # list
GET    /webhooks/endpoints/{id}   # inspect one
PATCH  /webhooks/endpoints/{id}   # url, events, active
DELETE /webhooks/endpoints/{id}   # 204

The event surface, described

The whole event surface is projected as a machine-readable description, the same way the request surface is. If you generate your consumer from it, your consumer cannot drift from what we actually send.