Skip to main content
Instead of polling the API, register a webhook endpoint and Mnemom POSTs events to it as they happen — integrity checkpoints, drift alerts, Safe House verdicts, quota thresholds, card and team changes, and billing events. See the Webhook Event Catalog for the full list of event types and their payloads. Every delivery is signed with HMAC-SHA256 so your server can verify authenticity before acting on it.

Create an endpoint

Or with the CLI:
The response includes the signing secret exactly once:
Copy signing_secret immediately — it is not retrievable after creation. If you lose it, rotate it: mnemom webhooks rotate-secret <org_id> <endpoint_id> or POST /v1/orgs/{org_id}/webhooks/{endpoint_id}/rotate-secret.
Requirements:
  • Up to 5 endpoints per organization.
  • url must be https://, with no username or password in it. Loopback, RFC-1918/link-local/CGNAT ranges, cloud metadata addresses, and internal-only names (localhost, single-label hosts, .local, .internal) are rejected, and so is a hostname that resolves to any of those addresses. The check runs at creation time and again immediately before every delivery. A delivery follows at most 3 redirects, and each redirect target goes through the same check.
  • event_types defaults to none — you opt in explicitly per event type. Leave it as an empty list only if you intend to add types later via PATCH.
Send a test delivery to confirm connectivity before waiting on a real event:
If the test can’t reach your endpoint (DNS failure, connection refused, timeout, or a blocked address or redirect), success is false and error is the generic "destination unreachable". The response doesn’t say which of these happened, so check your endpoint’s DNS, TLS, and firewall. If your endpoint answers with an HTTP error, status carries its status code.

Payload envelope

Every delivery uses the same envelope, whichever event type fired:

Signature verification

Every delivery carries three headers: The signature is computed over the string {timestamp}.{raw_body} using your endpoint’s signing secret as the HMAC key — the same construction as Stripe’s webhook signing. Always verify against the raw request body, not a re-serialized JSON object, and use a constant-time comparison.

Delivery, retries & auto-disable

Mnemom attempts inline delivery immediately when an event fires, then falls back to a background retry loop on failure. Retries follow a fixed backoff schedule and stop after 6 total attempts: Your endpoint has 30 seconds to respond. If processing takes longer, return 200 immediately and process asynchronously. If an endpoint accumulates 100 consecutive delivery failures, it is automatically disabled (is_active: false). Re-enable it once the issue is fixed:
Re-enabling resets the failure counter.

Idempotency & ordering

Use id from the payload envelope as an idempotency key — the same event can be delivered more than once (retries, manual redelivery, or replay). Deliveries are best-effort ordered by creation time; use created_at if your handler needs strict ordering.

Delivery log, health, and replay

For live debugging without registering an endpoint, stream deliveries directly:
mnemom listen (and the underlying GET /v1/orgs/{org_id}/webhooks/listen SSE stream) mirrors events to your terminal in near-real-time — Stripe CLI-equivalent ergonomics for local development. Pass --forward-to with --secret to re-sign and forward events to a local server.

CLI reference

Troubleshooting

  • Verify against the raw request body, not re-serialized JSON.
  • Confirm the signing secret — it’s shown once at creation; rotate if lost.
  • X-Webhook-Timestamp is Unix seconds, not milliseconds.
Webhook endpoint URLs must be https://. HTTP URLs are rejected at creation time. For local development, tunnel with ngrok or cloudflared.
After 100 consecutive failures the endpoint is disabled. Fix the underlying issue, then mnemom webhooks update <org_id> <endpoint_id> --active true — this resets the failure counter.
  • Confirm the endpoint is active (is_active: true).
  • Confirm the event type is in the endpoint’s event_types (empty means none — not all).
  • Check GET /v1/orgs/{org_id}/webhooks/deliveries for failed attempts.

API reference

See also