Webhook Failures
MemorySync dispatches webhook events asynchronously — webhook delivery never blocks or fails the API call that triggered it. This means webhook failures are silent from the caller’s perspective. This page covers the delivery lifecycle, how signatures work, the retry strategy, and how to diagnose failures using the delivery log.
Webhook Architecture
Webhook delivery happens after the API call that triggered the event completes. A failure during webhook delivery is logged for you, but it never propagates back into the original API response.
Key design decisions:
- Asynchronous: The triggering API request completes immediately and the webhook is dispatched independently afterwards.
- Best-effort delivery: Failed deliveries are retried with backoff. After the maximum number of attempts, the delivery is moved to the dead-letter log so you can replay it manually.
- Full audit trail: Every delivery attempt — success or failure — is recorded with status code, error message, timestamp, and attempt number.
This means if your webhook endpoint is down, your API requests continue to succeed. The failure is only visible in the webhook delivery log (Dashboard → Webhooks → Deliveries) and in the audit log.
The 12 Event Types
MemorySync emits these event types. Each endpoint subscribes to specific events — you only receive events you've opted into:
| Event Type | Trigger |
|---|---|
memory.created | A new memory is stored via API or ingestion pipeline |
memory.updated | An existing memory is modified (content, importance, metadata) |
memory.deleted | A memory is soft-deleted |
memory.batch_created | Multiple memories created in a batch operation |
memory.recalled | A memory appeared in a query result |
memory.superseded | A memory was replaced by a newer version with the same (type, key) |
team.member_added | A new member was added to the organization |
team.member_removed | A member was removed from the organization |
api_key.created | A new API key was generated |
api_key.revoked | An API key was revoked |
billing.limit_reached | Organization has reached a billing quota limit |
api.rate_limited | An API key has been rate limited |
Delivery Lifecycle
Each webhook delivery goes through a state machine:
pending → delivering → success
↘ retry → delivering → success
↘ retry → delivering → ...
↘ failed → dead_letter
State definitions:
- pending — delivery created, waiting to be sent
- delivering — HTTP request is in flight to your endpoint
- success — your endpoint returned a 2xx status code
- retry — delivery failed but retries remain; will attempt again after backoff
- failed — delivery failed and all retries exhausted
- dead_letter — terminal state; the event was recorded for manual replay
Each delivery record carries the response status code, the error message (if any), a truncated response body, the attempt number, the success or failure timestamp, and the request duration. All of this is visible in the dashboard.
HMAC Signature Verification
Every webhook delivery is signed with an HMAC signature so you can verify the payload was sent by MemorySync and hasn't been tampered with.
Signature format:
- The signature is sent in a configurable header (default:
X-Webhook-Signature) - A timestamp is sent in a separate header (default:
X-Webhook-Timestamp) - The signing payload is:
timestamp.body(timestamp dot-concatenated with the raw request body) - The algorithm is configurable per endpoint:
sha256(default) orsha512
Verification (any language):
- Read the timestamp and the signature from the request headers.
- Form the signing payload as
timestamp + "." + raw_request_body. - Compute an HMAC over the payload using your webhook secret and the configured algorithm.
- Compare the computed value to the received signature using a constant-time comparison.
⚠️ Common mistake: If you recently rotated the webhook secret, deliveries signed with the old secret will fail verification. After rotation, there's a brief window where in-flight deliveries may use the old secret. Always check both old and new secrets during the rotation transition period.
Retry Strategy
Failed webhook deliveries are retried with exponential backoff. Each subsequent retry waits longer than the previous one, up to a maximum delay configurable per endpoint.
429 Retry-After respect: If your endpoint returns a 429 Too Many Requests with a Retry-After header, the system honors that value instead of using exponential backoff. This prevents the retry system from hammering your endpoint when it's already rate-limited.
Non-retryable failures: Some failures are not retried because they're unlikely to succeed on subsequent attempts:
400— your endpoint explicitly rejected the payload401/403— authentication/authorization failure at your endpoint404— the endpoint URL is wrong405— the endpoint doesn't accept POST requests
Connection errors (DNS failures, timeouts, connection refused) are retried.
Failure Modes
Webhook deliveries can fail for several distinct reasons. The error message recorded on each delivery tells you exactly which one:
| Failure | Error Message Pattern | Retried? | Fix |
|---|---|---|---|
| Timeout | "Request timed out after 10s" | Yes | Ensure your endpoint responds within 10 seconds. Process the payload asynchronously if needed. |
| Connection error | "Connection error: ..." | Yes | Check DNS, firewall rules, and endpoint availability |
| Non-2xx status | "HTTP 500: ..." | Yes (5xx), No (4xx) | Fix the error in your webhook handler |
| SSL/TLS error | "SSL error: ..." | Yes | Check your certificate is valid and not expired |
💡 Timeout tip: The delivery timeout is 10 seconds. If your webhook handler does heavy processing (e.g., calling external APIs), accept the webhook immediately with a 200 response and process the payload in a background job.
Endpoint Health Tracking
MemorySync tracks the health of each webhook endpoint to surface persistent problems. The dashboard exposes:
- Consecutive failures — if this number is climbing, your endpoint is likely down or rejecting payloads.
- Total deliveries vs successful deliveries — gives you the success rate for the endpoint.
- Last error — the most recent failure message. Look for repeating patterns (for example, the same timeout every time).
- Last delivery timestamp — if this is stale, no events are being triggered for the endpoint’s subscriptions.
Audit log integration: When a delivery fails, an audit event is recorded under the webhook category with severity: "warning" while retries remain and severity: "critical" on the final attempt. Filter audit log entries by category and success: false to see all failed deliveries across all endpoints.
Manual replay: Failed deliveries can be replayed from the dashboard. Replay creates a new delivery attempt for the same event payload, sent to the same endpoint, and is itself recorded in the audit log.