Create an endpoint
- Up to 5 endpoints per organization.
urlmust behttps://, 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_typesdefaults to none — you opt in explicitly per event type. Leave it as an empty list only if you intend to add types later viaPATCH.
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:
Idempotency & ordering
Useid 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
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
Signature mismatch
Signature mismatch
- 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-Timestampis Unix seconds, not milliseconds.
HTTPS required
HTTPS required
Webhook endpoint URLs must be
https://. HTTP URLs are rejected at creation time. For local
development, tunnel with ngrok or cloudflared.Endpoint auto-disabled
Endpoint auto-disabled
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.Events not firing
Events not firing
- 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/deliveriesfor failed attempts.
API reference
See also
- Webhook Event Catalog — every event type and its payload.
- Safe House Threat Model — what
sh.*verdicts mean. - Card-Change Notifications — a separate, per-agent webhook/SSE mechanism specifically for canonical card changes (its own signing convention).