Webhooks
React to ingestion, entity and quality events in your own systems.
Register an HTTPS endpoint and Chordian will post events to it as they happen.
Events
| Event | Fires when |
|---|---|
memory.ingest.completed | A document finished indexing |
memory.ingest.dlp_flagged | The perimeter masked something during ingest |
memory.ingest.auto_routed | Content was classified — includes needs_review |
memory.entity.created | A new entity entered the graph |
memory.entity.contradiction_detected | Two sources disagreed |
memory.entity.contradiction_resolved | Someone resolved a disagreement |
memory.health.assessed | A health score was computed |
Delivery
Deliveries are signed with HMAC-SHA256 and retried on failure at 1s, 2s, 4s, 8s and 30s. After five failures the delivery is dead-lettered rather than dropped, so an outage on your side is recoverable rather than silent data loss.
Verify every delivery
An unverified webhook endpoint is an unauthenticated write to your system.
import { createHmac, timingSafeEqual } from 'node:crypto';
export function verify(rawBody: string, signature: string, secret: string) {
const expected = createHmac('sha256', secret).update(rawBody).digest('hex');
const a = Buffer.from(expected);
const b = Buffer.from(signature);
// Length check first: timingSafeEqual throws on a length mismatch.
return a.length === b.length && timingSafeEqual(a, b);
}Two details that are easy to get wrong:
- Verify against the raw body, before any JSON parsing. Re-serialising changes the bytes and the signature will not match.
- Compare in constant time. A plain
===leaks how much of the signature was correct, one request at a time.
Be idempotent
Retries mean your endpoint will occasionally see the same event twice. Key on the event id and make reprocessing a no-op — this is cheaper to build now than to debug later.
Respond fast
Acknowledge with 2xx immediately and do the work asynchronously. A slow endpoint
gets treated as a failing one, which turns your latency problem into a retry storm.