Skip to main content

Webhook Notifications

Real-time HTTP POST notifications for integrity and alignment events. Pipe violations, drift alerts, conscience escalations, alignment traces, and billing events into PagerDuty, Slack, Datadog, or any HTTP endpoint. Instead of polling the API, configure webhook endpoints to receive events as they happen. Mnemom signs every payload with HMAC-SHA256 so your server can verify authenticity before acting on it. Mnemom emits two categories of webhook events:
  • Integrity Events (AIP) — real-time checkpoint verdicts from the gateway (violations, drift, conscience)
  • Alignment Trace Events (AAP) — post-hoc trace analysis from the observer (verification, escalation, policy)
Both use the same registration endpoint and table. A single webhook endpoint can subscribe to events from both systems.
AIP Checkpoint ──→ Gateway  ──→ Signed POST (X-AIP-Signature) ──→ Your Endpoint
AAP Trace      ──→ Observer ──→ Signed POST (X-AAP-Signature) ──→ Your Endpoint

                                       ├── PagerDuty
                                       ├── Slack
                                       ├── Datadog
                                       └── Custom handler
Webhook notifications are available on the Enterprise plan. Contact sales to enable this feature.

Quick Start

Get your first webhook firing in under 5 minutes: 1. Create an endpoint in your organization settings, or via the API:
curl -X POST https://api.mnemom.ai/v1/orgs/{org_id}/webhooks \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-server.com/webhooks/mnemom",
    "description": "Production alerts",
    "event_types": ["integrity.violation", "drift.detected", "trace.failed"]
  }'
This example subscribes to AIP integrity violations, drift alerts, and AAP trace failures — all at one endpoint. 2. Copy the signing secret from the response — it’s shown only once:
{
  "endpoint_id": "whe-a1b2c3d4",
  "url": "https://your-server.com/webhooks/mnemom",
  "signing_secret": "a1b2c3d4e5f6...",
  "event_types": ["integrity.violation", "drift.detected"],
  "is_active": true
}
Copy the signing_secret immediately. It is not retrievable after creation. If you lose it, use the rotate secret endpoint to generate a new one.
3. Send a test event to verify connectivity:
curl -X POST https://api.mnemom.ai/v1/orgs/{org_id}/webhooks/whe-a1b2c3d4/test \
  -H "Authorization: Bearer $TOKEN"
4. Verify the signature on your server (see Signature Verification below).

Event Catalog

Mnemom emits 28 event types across two systems: AIP (integrity checkpoints from the gateway) and AAP (alignment traces from the observer), plus platform events for drift, reputation, teams, and billing.

Integrity Events (AIP)

These events fire from the gateway during real-time request interception.
Event TypeDescriptionTrigger
integrity.checkpointAn integrity checkpoint was recordedEvery stored AIP checkpoint
integrity.violationA boundary violation was detectedCheckpoint verdict = boundary_violation
drift.detectedBehavioral drift detected in a session3+ consecutive non-clear verdicts
drift.resolvedA drift alert was acknowledgedOrg member acknowledges alert
conscience.escalationConscience value conflict during analysisCheckpoint has conscience conflicts
conscience.values_updatedOrg conscience values were modifiedCreate, update, delete, or mode change
agent.pausedAgent was paused (manually or by auto-containment)Containment pause action
agent.resumedAgent was resumed or reactivatedContainment resume/reactivate action
agent.killedAgent was killedContainment kill action
AIP webhook payloads are signed with X-AIP-Signature and include X-AIP-Version.

Alignment Trace Events (AAP)

These events fire from the observer after post-hoc trace analysis.
Event TypeDescriptionTrigger
trace.createdNew alignment trace recordedEvery trace submitted to Supabase
trace.verifiedTrace passed verification checksverification.verified === true
trace.failedTrace failed verification checksverification.verified === false
trace.escalation_requiredEscalation condition detectedtrace.escalation.required === true
policy.violationPolicy evaluation resulted in denialpolicyResult.verdict === 'fail'
AAP webhook payloads are signed with X-AAP-Signature and include X-AAP-Version. Use the trace.* wildcard to subscribe to all trace events, or * for everything.
A single registration can subscribe to both AIP and AAP events. For example, event_types: ["integrity.violation", "trace.failed"] will receive gateway violations and observer trace failures at the same endpoint. The signature header (X-AIP-Signature vs X-AAP-Signature) tells you which system sent the event.

Platform Events

Event TypeDescriptionTrigger
reputation.score_changedReputation score changed significantlyScore changed by more than 10 points
reputation.grade_changedReputation letter grade changedGrade transition (e.g., BBB to A)
quota.warningUsage approaching plan limit (80%+)Cron check on billing period
quota.exceededUsage has exceeded plan limit (100%+)Cron check on billing period
quota.risk_exceededRisk usage exceeded plan limitRisk engine billing check
quota.risk_warningRisk usage approaching limit (80%+)Risk engine billing check
subscription.status_changedSubscription status changedPlan upgrade, downgrade, or cancellation
team.createdTeam was createdTeam CRUD
team.archivedTeam was archivedTeam CRUD
team.member_addedAgent added to teamRoster change
team.member_removedAgent removed from teamRoster change
team.card_updatedTeam alignment card changedCard update
team_reputation.score_changedTeam score changed significantlyScore delta > 10 points
team_reputation.grade_changedTeam letter grade changedGrade transition
quota.team_reputation_exceededTeam reputation usage exceeded plan limitCron billing check
quota.team_reputation_warningTeam reputation usage approaching limit (80%+)Cron billing check
Subscribe to specific event types when creating an endpoint, or leave event_types empty to receive all events.

Payload Envelope

Every webhook delivery uses the same envelope structure:
{
  "id": "evt-a1b2c3d4",
  "type": "integrity.violation",
  "created_at": "2026-02-17T14:30:00.000Z",
  "account_id": "ba-x1y2z3w4",
  "data": {
    // Event-specific payload (see examples below)
  }
}
FieldTypeDescription
idstringUnique event ID (evt-xxxxxxxx). Use for idempotency.
typestringOne of the 28 event types above
created_atstringISO 8601 timestamp
account_idstringBilling account that owns the resource
dataobjectEvent-specific payload

Example Payloads

{
  "id": "evt-vl7k2m9x",
  "type": "integrity.violation",
  "created_at": "2026-02-17T14:30:00.000Z",
  "account_id": "ba-x1y2z3w4",
  "data": {
    "checkpoint_id": "ic-abc12345",
    "agent_id": "smolt-agent01",
    "session_id": "sess-def67890",
    "verdict": "boundary_violation",
    "concerns": [
      {
        "category": "autonomy_violation",
        "severity": "high",
        "description": "Agent attempted to bypass escalation trigger"
      }
    ],
    "reasoning_summary": "Agent's reasoning shows intent to take action outside defined autonomy envelope."
  }
}
{
  "id": "evt-cp3j8n2w",
  "type": "integrity.checkpoint",
  "created_at": "2026-02-17T14:30:00.000Z",
  "account_id": "ba-x1y2z3w4",
  "data": {
    "checkpoint_id": "ic-ghi34567",
    "agent_id": "smolt-agent01",
    "session_id": "sess-def67890",
    "verdict": "clear",
    "concerns": [],
    "reasoning_summary": "Agent reasoning is consistent with declared values and autonomy envelope."
  }
}
{
  "id": "evt-dr9p4k1q",
  "type": "drift.detected",
  "created_at": "2026-02-17T14:31:00.000Z",
  "account_id": "ba-x1y2z3w4",
  "data": {
    "alert_id": "ida-drift-abc123",
    "agent_id": "smolt-agent01",
    "session_id": "sess-def67890",
    "severity": "high",
    "drift_direction": "value_erosion",
    "sustained_checks": 7,
    "message": "Detected 7 consecutive non-clear verdicts in session sess-def67890"
  }
}
{
  "id": "evt-rs2m7h5v",
  "type": "drift.resolved",
  "created_at": "2026-02-17T15:00:00.000Z",
  "account_id": "ba-x1y2z3w4",
  "data": {
    "alert_id": "ida-drift-abc123",
    "org_id": "org-xyz98765",
    "acknowledged_by": "user-uuid-1234"
  }
}
{
  "id": "evt-ce6t3w8r",
  "type": "conscience.escalation",
  "created_at": "2026-02-17T14:30:05.000Z",
  "account_id": "ba-x1y2z3w4",
  "data": {
    "checkpoint_id": "ic-jkl45678",
    "agent_id": "smolt-agent01",
    "session_id": "sess-def67890",
    "conflicts": [
      {
        "value": "transparency",
        "description": "Agent reasoning conflicts with declared transparency commitment"
      }
    ],
    "verdict": "review_needed"
  }
}
{
  "id": "evt-qw1n5b9d",
  "type": "quota.warning",
  "created_at": "2026-02-17T06:00:00.000Z",
  "account_id": "ba-x1y2z3w4",
  "data": {
    "usage_percent": 85,
    "checks_used": 12750,
    "checks_included": 15000
  }
}
{
  "id": "evt-qx4m8g2j",
  "type": "quota.exceeded",
  "created_at": "2026-02-17T06:00:00.000Z",
  "account_id": "ba-x1y2z3w4",
  "data": {
    "usage_percent": 105,
    "checks_used": 15750,
    "checks_included": 15000
  }
}
{
  "id": "evt-ss7k3p1w",
  "type": "subscription.status_changed",
  "created_at": "2026-02-17T10:15:00.000Z",
  "account_id": "ba-x1y2z3w4",
  "data": {
    "status": "active",
    "previous_plan_id": "plan-team",
    "new_plan_id": "plan-enterprise",
    "cancel_at_period_end": false
  }
}
{
  "id": "evt-cv2m8n4x",
  "type": "conscience.values_updated",
  "created_at": "2026-02-19T16:00:00.000Z",
  "account_id": "ba-x1y2z3w4",
  "data": {
    "org_id": "org-abc123",
    "action": "create",
    "value_id": "cv-def45678",
    "actor": "user-xyz789"
  }
}
{
  "id": "evt-rs4n8k2p",
  "type": "reputation.score_changed",
  "created_at": "2026-02-21T14:00:00.000Z",
  "account_id": "ba-x1y2z3w4",
  "data": {
    "agent_id": "agent-xyz",
    "score_before": 770,
    "score_after": 782,
    "grade": "A",
    "components": {
      "integrity_ratio": 920,
      "compliance": 850,
      "drift_stability": 700,
      "trace_completeness": 650,
      "coherence_compatibility": 390
    }
  }
}
{
  "id": "evt-rg3k7m2x",
  "type": "reputation.grade_changed",
  "created_at": "2026-02-21T14:00:00.000Z",
  "account_id": "ba-x1y2z3w4",
  "data": {
    "agent_id": "agent-xyz",
    "grade_before": "BBB",
    "grade_after": "A",
    "score": 702
  }
}
{
  "id": "evt-tc1m4k7x",
  "type": "team.created",
  "created_at": "2026-02-25T10:00:00.000Z",
  "account_id": "ba-x1y2z3w4",
  "data": {
    "team_id": "team-abc123",
    "org_id": "org-xyz789",
    "name": "Support Pipeline Alpha",
    "member_count": 3,
    "agent_ids": ["agent-a", "agent-b", "agent-c"]
  }
}
{
  "id": "evt-ta2n5j8w",
  "type": "team.archived",
  "created_at": "2026-02-25T12:00:00.000Z",
  "account_id": "ba-x1y2z3w4",
  "data": {
    "team_id": "team-abc123",
    "org_id": "org-xyz789",
    "name": "Support Pipeline Alpha"
  }
}
{
  "id": "evt-ma3p6h9v",
  "type": "team.member_added",
  "created_at": "2026-02-25T10:15:00.000Z",
  "account_id": "ba-x1y2z3w4",
  "data": {
    "team_id": "team-abc123",
    "agent_id": "agent-d",
    "actor_id": "user-xyz789",
    "member_count": 4
  }
}
{
  "id": "evt-mr4q7g1u",
  "type": "team.member_removed",
  "created_at": "2026-02-25T11:00:00.000Z",
  "account_id": "ba-x1y2z3w4",
  "data": {
    "team_id": "team-abc123",
    "agent_id": "agent-b",
    "actor_id": "user-xyz789",
    "member_count": 3
  }
}
{
  "id": "evt-cu5r8f2t",
  "type": "team.card_updated",
  "created_at": "2026-02-25T10:30:00.000Z",
  "account_id": "ba-x1y2z3w4",
  "data": {
    "team_id": "team-abc123",
    "card_id": "card-def456",
    "card_source": "auto_derived",
    "actor_id": "user-xyz789"
  }
}
{
  "id": "evt-ts6s9e3r",
  "type": "team_reputation.score_changed",
  "created_at": "2026-02-25T06:00:00.000Z",
  "account_id": "ba-x1y2z3w4",
  "data": {
    "team_id": "team-abc123",
    "score_before": 790,
    "score_after": 812,
    "grade": "AA",
    "components": {
      "coherence_history": 880,
      "member_quality": 790,
      "operational_record": 850,
      "structural_stability": 720,
      "assessment_density": 640
    }
  }
}
{
  "id": "evt-tg7t1d4q",
  "type": "team_reputation.grade_changed",
  "created_at": "2026-02-25T06:00:00.000Z",
  "account_id": "ba-x1y2z3w4",
  "data": {
    "team_id": "team-abc123",
    "grade_before": "A",
    "grade_after": "AA",
    "score": 812
  }
}
{
  "id": "evt-qe8u2c5p",
  "type": "quota.team_reputation_exceeded",
  "created_at": "2026-02-25T06:00:00.000Z",
  "account_id": "ba-x1y2z3w4",
  "data": {
    "usage_percent": 110,
    "computations_used": 220,
    "computations_included": 200
  }
}
{
  "id": "evt-qw9v3b6n",
  "type": "quota.team_reputation_warning",
  "created_at": "2026-02-25T06:00:00.000Z",
  "account_id": "ba-x1y2z3w4",
  "data": {
    "usage_percent": 85,
    "computations_used": 170,
    "computations_included": 200
  }
}

AAP Trace Event Payloads

AAP trace events use a different payload structure from AIP events. The envelope includes event (most specific event type), all_events (all applicable types for this trace), and a trace object with verification and policy results.
{
  "event": "trace.created",
  "all_events": ["trace.created"],
  "timestamp": "2026-03-03T14:30:00.000Z",
  "trace": {
    "trace_id": "tr-a1b2c3d4",
    "agent_id": "smolt-agent01",
    "session_id": "sess-def67890",
    "decision": {
      "reasoning": "Agent selected the most transparent response option",
      "alternatives_count": 3
    },
    "verification": null,
    "escalation": null,
    "policy": null
  }
}
{
  "event": "trace.verified",
  "all_events": ["trace.created", "trace.verified"],
  "timestamp": "2026-03-03T14:30:01.000Z",
  "trace": {
    "trace_id": "tr-e5f6g7h8",
    "agent_id": "smolt-agent01",
    "session_id": "sess-def67890",
    "decision": {
      "reasoning": "Agent reasoning aligns with declared values",
      "alternatives_count": 2
    },
    "verification": {
      "verified": true,
      "warnings": []
    },
    "escalation": null,
    "policy": null
  }
}
{
  "event": "trace.failed",
  "all_events": ["trace.created", "trace.failed"],
  "timestamp": "2026-03-03T14:30:02.000Z",
  "trace": {
    "trace_id": "tr-i9j0k1l2",
    "agent_id": "smolt-agent01",
    "session_id": "sess-def67890",
    "decision": {
      "reasoning": "Agent bypassed transparency requirements",
      "alternatives_count": 4
    },
    "verification": {
      "verified": false,
      "warnings": [
        "Decision conflicts with alignment card boundary: transparency_commitment",
        "No escalation was triggered despite high-risk action"
      ]
    },
    "escalation": null,
    "policy": null
  }
}
{
  "event": "trace.escalation_required",
  "all_events": ["trace.created", "trace.failed", "trace.escalation_required"],
  "timestamp": "2026-03-03T14:30:03.000Z",
  "trace": {
    "trace_id": "tr-m3n4o5p6",
    "agent_id": "smolt-agent01",
    "session_id": "sess-def67890",
    "decision": {
      "reasoning": "Agent attempted action requiring human oversight",
      "alternatives_count": 2
    },
    "verification": {
      "verified": false,
      "warnings": ["Escalation trigger was not activated"]
    },
    "escalation": {
      "required": true,
      "reason": "Action exceeds autonomy envelope",
      "triggered": false
    },
    "policy": null
  }
}
{
  "event": "policy.violation",
  "all_events": ["trace.created", "trace.failed", "policy.violation"],
  "timestamp": "2026-03-03T14:30:04.000Z",
  "trace": {
    "trace_id": "tr-q7r8s9t0",
    "agent_id": "smolt-agent01",
    "session_id": "sess-def67890",
    "decision": {
      "reasoning": "Agent invoked restricted tool without authorization",
      "alternatives_count": 1
    },
    "verification": {
      "verified": false,
      "warnings": ["Tool usage violates policy constraints"]
    },
    "escalation": null,
    "policy": {
      "verdict": "fail",
      "violations": 2,
      "warnings": 1
    }
  }
}
AAP events are signed with X-AAP-Signature (not X-AIP-Signature). The HMAC-SHA256 algorithm is identical — only the header name differs. Use the header name to distinguish which system sent the webhook.

Security

HMAC-SHA256 Signing

Every webhook delivery includes three headers for signature verification:
HeaderDescription
X-Webhook-IdUnique event ID (same as payload.id)
X-Webhook-TimestampUnix timestamp (seconds) when the payload was signed
X-Webhook-SignatureHMAC-SHA256 signature in format v1={hex}
The signature is computed over the string {timestamp}.{raw_body} using your endpoint’s signing secret as the HMAC key. This follows the Stripe webhook signing convention.

Replay Protection

Always verify that the timestamp is within an acceptable window (recommended: 5 minutes) to prevent replay attacks. Reject any delivery where X-Webhook-Timestamp is more than 300 seconds from your server’s current time.

Constant-Time Comparison

Use a constant-time comparison function when verifying signatures to prevent timing attacks. All standard libraries provide one — see the verification examples below.

Signature Verification

Verify webhook signatures in your endpoint handler to ensure payloads are authentic and untampered. Below are examples in four languages.
const crypto = require('crypto');

function verifyWebhookSignature(req, signingSecret) {
  const timestamp = req.headers['x-webhook-timestamp'];
  const signature = req.headers['x-webhook-signature'];
  const rawBody = req.rawBody; // Must be raw string, not parsed JSON

  // 1. Check timestamp freshness (5-minute tolerance)
  const now = Math.floor(Date.now() / 1000);
  if (Math.abs(now - parseInt(timestamp, 10)) > 300) {
    throw new Error('Timestamp too old — possible replay attack');
  }

  // 2. Compute expected signature
  const signatureInput = `${timestamp}.${rawBody}`;
  const expected = 'v1=' + crypto
    .createHmac('sha256', signingSecret)
    .update(signatureInput)
    .digest('hex');

  // 3. Constant-time comparison
  if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) {
    throw new Error('Invalid signature');
  }

  return JSON.parse(rawBody);
}
Always verify signatures against the raw request body (the exact bytes received), not a re-serialized JSON object. JSON serialization can alter key ordering, whitespace, or Unicode escaping, which will cause signature mismatches.

Delivery & Retries

First Delivery

Mnemom attempts inline delivery immediately when an event is emitted. Most webhooks arrive within seconds of the triggering event. If inline delivery fails, the event enters the retry queue.

Retry Schedule

Failed deliveries are retried with exponential backoff:
AttemptDelayCumulative
1 (initial)Immediate0s
210 seconds10s
330 seconds40s
42 minutes2m 40s
510 minutes12m 40s
61 hour1h 12m 40s
After 6 attempts, the delivery is marked as failed (terminal).

Permanent vs. Retryable Failures

ResponseBehavior
2xxSuccess. Delivery marked as delivered.
429Rate limited. Retries with at least 60s backoff.
4xx (except 429)Permanent failure. No retries. Fix your endpoint.
5xxRetryable. Follows backoff schedule.
Timeout (>10s)Retryable. Your endpoint must respond within 10 seconds.

Auto-Disable

If an endpoint accumulates 100 consecutive failures, it is automatically disabled. The account owner receives an email notification. To resume deliveries:
  1. Fix the underlying issue with your endpoint
  2. Re-enable the endpoint in organization settings (or via PATCH with is_active: true)
  3. The failure counter resets when you re-enable

Idempotency

Use the id field in the payload envelope as an idempotency key. The same event may be delivered more than once (e.g., after a redeliver request). Your handler should deduplicate using the event ID.

Ordering

Webhook deliveries are best-effort ordered by creation time. Due to retries and network variance, events may arrive out of order. Use the created_at timestamp for ordering if your use case requires it.

Testing

Test Delivery Button

Every endpoint has a “Test” action that sends a synthetic webhook.test event with a test payload. Use this to verify connectivity and signature verification without triggering a real integrity event.
curl -X POST https://api.mnemom.ai/v1/orgs/{org_id}/webhooks/{endpoint_id}/test \
  -H "Authorization: Bearer $TOKEN"
Response:
{
  "success": true,
  "status": 200,
  "latency_ms": 145,
  "error": null
}

Development Tools

For local development, use webhook.site or ngrok to expose a local endpoint:
# Start ngrok tunnel
ngrok http 3000

# Use the HTTPS URL as your webhook endpoint
# https://abc123.ngrok.io/webhooks/mnemom

Delivery Log

View the delivery history for any endpoint to debug issues:
curl https://api.mnemom.ai/v1/orgs/{org_id}/webhooks/deliveries?endpoint_id=whe-a1b2c3d4 \
  -H "Authorization: Bearer $TOKEN"
Each delivery record includes: status, HTTP response code, attempt count, latency, and error details.

Redelivery

Redeliver a failed event to retry with the same payload:
curl -X POST https://api.mnemom.ai/v1/orgs/{org_id}/webhooks/deliveries/{delivery_id}/redeliver \
  -H "Authorization: Bearer $TOKEN"

Integration Examples

PagerDuty

Route integrity violations to PagerDuty as incidents:
app.post('/webhooks/mnemom', (req, res) => {
  verify(req); // Verify signature first

  const event = req.body;

  if (event.type === 'integrity.violation') {
    fetch('https://events.pagerduty.com/v2/enqueue', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        routing_key: process.env.PAGERDUTY_ROUTING_KEY,
        event_action: 'trigger',
        payload: {
          summary: `Integrity violation: ${event.data.agent_id}`,
          severity: 'critical',
          source: 'mnemom',
          custom_details: event.data,
        },
      }),
    });
  }

  res.sendStatus(200);
});

Slack

Post alerts to a Slack channel via incoming webhook:
app.post('/webhooks/mnemom', (req, res) => {
  verify(req);

  const event = req.body;
  const emoji = {
    'integrity.violation': ':rotating_light:',
    'drift.detected': ':warning:',
    'conscience.escalation': ':brain:',
    'quota.warning': ':chart_with_upwards_trend:',
    'trace.failed': ':x:',
    'trace.escalation_required': ':exclamation:',
    'policy.violation': ':no_entry:',
  }[event.type] || ':bell:';

  fetch(process.env.SLACK_WEBHOOK_URL, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      text: `${emoji} *${event.type}*\n${JSON.stringify(event.data, null, 2)}`,
    }),
  });

  res.sendStatus(200);
});

Datadog

Send custom events to Datadog:
app.post('/webhooks/mnemom', (req, res) => {
  verify(req);

  const event = req.body;

  fetch(`https://api.datadoghq.com/api/v1/events`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'DD-API-KEY': process.env.DD_API_KEY,
    },
    body: JSON.stringify({
      title: `Mnemom: ${event.type}`,
      text: JSON.stringify(event.data),
      tags: [`event_type:${event.type}`, `account:${event.account_id}`],
      alert_type: event.type.includes('violation') ? 'error' : 'info',
    }),
  });

  res.sendStatus(200);
});

Troubleshooting

  • Ensure you’re verifying against the raw request body, not re-serialized JSON
  • Check that your signing secret is correct — it was only shown once at creation time. If lost, rotate the secret.
  • Verify the timestamp header is being read correctly (it’s in Unix seconds, not milliseconds)
Webhook endpoints must use HTTPS. HTTP URLs are rejected at creation time. For local development, use ngrok or a similar tunneling tool.
Your endpoint must respond within 10 seconds. If processing takes longer, return 200 immediately and process the event asynchronously (e.g., via a background job queue).
HTTP 4xx responses (except 429) are treated as permanent failures and are not retried. Common causes:
  • 401/403 — Your auth middleware is blocking the request. Mnemom webhooks don’t include bearer tokens.
  • 404 — The endpoint URL path is incorrect.
  • 400 — Your request validation is rejecting the payload format.
After 100 consecutive delivery failures, the endpoint is automatically disabled. Fix the underlying issue, then re-enable the endpoint. The failure counter resets on re-enable.
  • Verify the endpoint is active (is_active: true)
  • Check that the event type is included in the endpoint’s event_types (or that event_types is empty for all events)
  • Confirm the triggering action occurred on an agent linked to an Enterprise billing account
  • Check the delivery log for failed attempts

FAQ

Mnemom does not impose explicit rate limits on outbound deliveries. However, if your endpoint returns 429 (Too Many Requests), we respect that signal and back off for at least 60 seconds before retrying.
Events are delivered in best-effort order. Due to retries and network conditions, events may arrive out of order. Use the created_at field for sequencing.
Webhook payloads are typically under 4 KB. The maximum payload size is 64 KB.
Use the rotate secret endpoint: POST /v1/orgs/{org_id}/webhooks/{endpoint_id}/rotate-secret. The new secret is returned once. Update your verification code before new deliveries arrive.
Yes, up to 5 endpoints per organization. Each endpoint can subscribe to different event types.
Delivery records are retained for 30 days. Older records are automatically purged.
Events are queued and retried according to the backoff schedule. If your endpoint recovers within the retry window (~1 hour), all events will be delivered. Beyond that, they are marked as failed but remain in the delivery log for redelivery.

API Reference

EndpointDescription
POST /orgs//webhooksCreate webhook endpoint
GET /orgs//webhooksList webhook endpoints
GET /orgs//webhooks/Get endpoint details
PATCH /orgs//webhooks/Update endpoint
DELETE /orgs//webhooks/Delete endpoint
POST …/rotate-secretRotate signing secret
POST …/testSend test delivery
GET …/deliveriesDelivery log
POST …/redeliverRedeliver failed event
GET /admin/webhooks/healthPlatform health (admin)