Webhooks

Subscribe to ConvoMem events to react to new memories and conversation state changes in real time.

Webhooks let your systems react the moment ConvoMem fires an event — without polling. Webhook endpoints are configured in the dashboard (Settings → Webhooks). They cannot be managed via an org API key.

Each endpoint belongs to one agent and receives only that agent's events. Choose the events to subscribe to when you create the endpoint.

Events

Every event's data includes customerId.

Customers

EventFires whenKey data fields
customer.createdA customer is created, explicitly or automatically on first contactcustomerId, name, email, phone, externalId

Capture

EventFires whenKey data fields
capture.startedA capture job begins processingcaptureId, customerId, conversationId
capture.completedA capture job finishescaptureId, customerId, conversationId, saved, skipped
capture.failedA capture job fails after its final retrycaptureId, customerId, conversationId, error
memory.capturedA capture saved at least one new memorycaptureId, customerId, conversationId, saved, skipped

Memory lifecycle

These events never include memory text — fetch the memory if you need its content.

EventFires whenKey data fields
memory.createdA memory is createdeventId, memoryId, customerId, version, operation, cause, status, occurredAt
memory.updatedA memory changessame as above
memory.supersededA newer memory replaces this onesame as above, plus supersededById
memory.deletedA memory is deletedsame as above
commitment.overdueA commitment made to the customer passes its due datecommitmentId, insightId, customerId, conversationId, dueAt, humanAgentId

Conversations

EventFires whenKey data fields
conversation.completedA conversation is ended, including when it idle-closesconversationId, customerId, outcome
conversation.escalatedA conversation is escalatedconversationId, customerId, reason

Leads

Fired by lead playbooks configured in the dashboard.

EventFires whenKey data fields
lead.createdA playbook detects a new lead in a conversationid, templateId, templateName, customerId, conversationId, score, priority, status
lead.updatedA lead is re-evaluated or editedsame as above
lead.status_changedA lead's status changessame as above
lead.disqualifiedA lead is marked DISQUALIFIEDsame as above

Event payload

Every delivery is a POST with X-ConvoMem-Signature and X-ConvoMem-Event headers:

memory.captured
{
  "event": "memory.captured",
  "createdAt": "2026-06-17T10:00:00.000Z",
  "data": {
    "customerId": "f3b39d1b-2522-4a00-98df-8cdde783ba12",
    "conversationId": "87c53d10-85f8-4447-920f-b1e847c23a1a",
    "captureId": "0b6f4c1e-3d2a-4e8b-a7c9-5f1d2e3b4a6c",
    "saved": 3,
    "skipped": 0
  }
}

Verifying signatures

The signature is sha256=<HMAC-SHA256(rawBody, webhookSecret)>. Always verify before processing — anyone who learns your URL could otherwise POST to it.

Compute the HMAC over the raw bytes of the request body, not a re-serialized object.

verify.ts
import crypto from 'node:crypto'
 
function verifyWebhook(
  rawBody: Buffer | string,
  signatureHeader: string,
  secret: string,
): boolean {
  const sig = signatureHeader.replace('sha256=', '')
  const digest = crypto
    .createHmac('sha256', secret)
    .update(rawBody)
    .digest('hex')
  const a = Buffer.from(sig, 'hex')
  const b = Buffer.from(digest, 'hex')
  return a.length === b.length && crypto.timingSafeEqual(a, b)
}
verify.py
import hmac, hashlib
 
def verify_webhook(raw_body: bytes, signature_header: str, secret: str) -> bool:
    expected = signature_header.replace("sha256=", "")
    computed = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, computed)

Delivery semantics

  • Retries — non-2xx or timeout triggers up to 3 retries with exponential backoff.
  • Idempotency — deliveries are at-least-once and can repeat. De-duplicate on eventId for memory.* events, captureId for capture events, and (event, conversationId) for conversation events.
  • SSRF protection — destination URLs must be https://. Loopback, private, and cloud metadata addresses are rejected.
  • Timeout — your endpoint must respond within 10 s.
  • Capture — triggers capture.* and memory.captured
  • Conversations — triggers conversation.completed and conversation.escalated
  • Authentication — API key scopes and security model