The third pillar
Notify
A record captures the full lifecycle of a piece of work: the intent at the start, the handoffs in the middle, the result at the end, each stage signed the moment it is real. Notify carries the events of that signed span out to the systems and people you already run in production. When an agent finishes a task, when a verdict lands, when a delegation changes hands, the delivery shows up at your endpoint as an HTTPS POST you already know how to receive. No broker to adopt, nothing to poll: the loop closes by delivery, not by you asking.
At-least-once · Idempotency key · Retry with backoff · Circuit breaker · 7-day DLQ · HMAC-SHA256 / Ed25519 RFC 9421
Last updated: 2026-06-10 · API v1.2.0
The shape
Human-in-the-loop by delivery, not by polling
An agent that has to wait on a person should not sit in a loop hitting an inbox endpoint. Notify pushes the moment a record reaches a state someone cares about - an approval queue, a Slack channel, a ticketing system, a payment platform - so the human or the downstream system reacts to a delivery instead of the agent burning cycles polling for one. The agent registers what it wants to hear about, then goes idle until the event arrives.
Everything Notify carries is an event of an already-signed record. The capability story on this page is the delivery: how the event gets to you intact, exactly-handleable, and provable to the receiver. What is inside a settlement event - the SETTLE, HOLD, or RELEASE on a terminal verdict - lives on the Settlement Signals page; those are one payload class on this channel, not the whole of it.
Signing
Two signing schemes for two trust problems
Every delivery is signed. The scheme is fixed per subscription and reported on the webhook's read surface as signingAlg, so a consumer checks it once and writes the matching verifier. Which scheme you want depends on who needs to trust the delivery.
hmac - default
HMAC-SHA256 over a per-subscription shared secret, in the same header shape Stripe, GitHub, and Shopify use: X-AGLedger-Signature: t=<unix>,v1=<hex>. It confirms to one specific receiver that the POST came from the Server it subscribed against, untampered. It verifies in two lines and needs no third party. This is the right choice for ordinary notarization fan-out, where only your own system consumes the event.
ed25519 - the non-repudiable path
RFC 9421 HTTP Message Signatures, signed with the Server's vault key - the same key that signs the chain. The receiver verifies against the Server's published public keys and holds no secret of its own. A subscription that lists a settlement event defaults to ed25519 when the Server has a signing key. This is the scheme that lets a settlement instruction cross a company boundary.
Non-repudiation
Signed the same way the chain is signed
A shared secret is symmetric: the receiver holds the same key that signs, so it can confirm a delivery for itself but cannot prove to anyone else who produced it. For a Settlement Signal routed into a payment platform, ERP, or ticketing system, that is the difference that matters.
The Ed25519 path is asymmetric and non-repudiable. The delivery is signed by the same vault key that signs the chain, naming the accountable principal inside the payload. The payment system on the other side verifies a SETTLE against a public key it fetched once - no shared secret to exchange, and the signature is provable to a third party. That is what lets a settlement instruction cross a company boundary without a trusted intermediary in the middle, and it is a property a plain webhook does not have.
The receiver resolves the key by the keyid in the signature header against GET /v1/verification-keys (also published at /.well-known/agledger-vault-keys.json), recomputes the signature base, and checks the Ed25519 signature. The SETTLE and the chain record it settles share one trust root.
Derived components (@method, @target-uri, @authority) are deliberately excluded so a load balancer or reverse proxy that rewrites host and path cannot break verification of an authentic message. Step-by-step verification code for both schemes is in the webhook guide.
Events
Business moments, not internal state transitions
Notify emits an event at every business-meaningful moment in the record lifecycle. Register an endpoint through POST /v1/webhooks with an event-type filter or the wildcard ["*"]. Federation events mirror the lifecycle stream with a federation. prefix and a thin cross-org payload, so a single subscription can see both sides without two divergent schemas on one event type. Payloads ship in AGLedger's native envelope or CloudEvents 1.0.
| Category | Example events |
|---|---|
| Record lifecycle | record.created, record.recorded, record.completion_submitted, record.fulfilled, record.failed, record.expired, record.cancelled |
| Agent-to-agent | record.proposed, record.proposal_accepted, record.proposal_rejected, record.delegated, record.revision_requested |
| Cascading verification | cascading.verification.complete |
| Settlement and disputes | signal.emitted, signal.received, dispute.opened, dispute.resolved, dispute.withdrawn |
| Federation | federation.record.state_changed, federation.settlement.signal, record.federation_fulfilled (and other federation-projected lifecycle events) |
| Entity references | record.reference_added, agent.reference_added |
Every payload carries a type and a status in display names (CREATED / FULFILLED / FAILED / RECORDED…), not internal state-machine names. The full event-type list is in the API reference.
Delivery
Built to survive a receiver that is having a bad day
At-least-once, deduplicated by you. Every event carries a stable X-AGLedger-Idempotency-Key - minted once and replayed verbatim on every retry of the same event. Treat a repeat as a no-op. A separate per-attempt X-AGLedger-Delivery id is for log correlation, not dedup.
Order by status, not by arrival. Delivery is serialized per subscription, but a retried event can overtake a later one that succeeded first. Receivers integrating a state machine branch on the status field in the payload rather than on event arrival order.
Retry with exponential backoff. A failed delivery retries roughly six times over about five minutes, then moves to the subscription's dead-letter queue. The window is intentionally short - operators wanting longer windows replay from the DLQ explicitly rather than tying up a worker for hours.
Circuit breaker. After ten consecutive failures against the same subscription the breaker opens and subsequent events go straight to the DLQ without an attempt. It closes again on the first successful delivery, or an operator resets it once the receiver is fixed.
Dead-letter replay. Permanently failed deliveries land in the DLQ for seven days, carrying the original event body so you can audit what failed. Replay one entry or drain the whole queue once the receiver is back.
Secret rotation with a grace window. Rotate an HMAC secret without downtime - the previous secret stays valid for a configured window so consumers update on their own schedule.
Management
Subscriptions are an API, not a config file you redeploy
Register, inspect, rotate, pause, resume, and tear down endpoints programmatically. Send a test event before you wire anything up, read the delivery log to see exactly what each attempt returned, and work the dead-letter queue when a receiver comes back. For config-as-code installs, the same subscriptions can be declared in provisioning YAML with operator-supplied secrets.
Org-wide health and DLQ views (GET /v1/admin/webhooks/health) give SRE dashboards one row per subscription with breaker state and last-success timestamp.
Related capabilities
What the Ed25519-signed delivery carries on terminal verdicts - SETTLE, HOLD, RELEASE.
How a peer Server's event projects into your local stream as signal.received.
Trace-ID join keys and OCSF SIEM export - the other ways AGLedger fits under your stack.
SSRF protection on delivery URLs, secret storage, and the verification-key surface.
Register an endpoint and verify both signature schemes, with real code.
The full webhook route surface and per-event payload schemas.