Webhook events
The full catalog of webhook event types Moonborn emits. Sixteen real events covering persona lifecycle, generation, billing, marketplace, moderation, and system test pings.
Every Moonborn webhook delivery carries an event of one of the
following types. The full list lives in source as
WEBHOOK_EVENT_TYPES; this page is the human-readable view.
Persona lifecycle (6)
| Type | When |
|---|---|
persona.created | A new persona finished the generation pipeline. |
persona.updated | A persona's mutable metadata changed (slug, visibility, etc.). |
persona.deleted | Persona soft-deleted (enters 30-day grace). |
persona.archived | Persona archived (read-only; lineage preserved). |
persona.regenerated | Pipeline re-ran from a chosen step. |
persona.audit_failed | Audit verdict dropped below threshold, OR drift detection alerted on a chat reply. |
persona.audit_failed is overloaded — data.reason carries either
audit_below_threshold, provocation_test_failed, or voice_drift.
Inspect the reason field; the schema is otherwise the same.
Generation pipeline (3)
| Type | When |
|---|---|
generation.run.started | Pipeline run kicked off. |
generation.run.completed | Pipeline run finished successfully. |
generation.run.failed | Pipeline run failed terminally (after retries). |
These fire on every persona generation, refine, fork. Subscribe
to them only if you're tracking pipeline observability — for normal
persona lifecycle, the persona.* events are usually enough.
Subscription / billing (3)
| Type | When |
|---|---|
subscription.upgraded | Plan moved up a tier (e.g. Pro → Team). |
subscription.downgraded | Plan moved down a tier. |
subscription.cancelled | Subscription cancelled (effective end of period). |
Marketplace (2)
| Type | When |
|---|---|
marketplace.persona.published | Listing passed moderation; visible publicly. |
marketplace.persona.purchased | Paid listing bought (Enterprise commerce). |
Moderation (1)
| Type | When |
|---|---|
moderation.flagged | Any moderation stage produced a non-pass verdict (input intent, output content, impersonation, PII). |
System (1)
| Type | When |
|---|---|
webhook.endpoint.test_ping | Fired by POST /v1/webhooks/{id}/ping for connectivity tests. |
Wildcard
Subscribe with events: ['*'] to receive every event type. Useful
for audit-log archival or generic event streaming; not recommended
for production handlers (you'll do if/else over 16+ types).
Envelope shape
Every event ships in the same envelope:
{
"id": "evt_01H...",
"type": "persona.audit_failed",
"occurredAt": "2026-05-16T12:00:00Z",
"orgId": "org_...",
"workspaceId": "ws_...",
"data": { /* type-specific */ }
}id is unique + idempotent — use it as your dedupe key on retries.
Delivery semantics
- HMAC-SHA256 signed (
X-Moonborn-Signatureheader). - Five retries with exponential backoff (1m → 2m → 5m → 30m → 2h).
- Dead-letter after five failures; replayable from the dashboard or
POST /v1/webhooks/{id}/deliveries/{id}/replay.
See the Webhooks integration for setup + the Webhook signature verification guide for production receivers.
Honest scope
Sixteen event types. No more. We do not emit:
- Per-message chat events (too high-volume; use SSE streaming on the chat endpoint instead).
- Per-step pipeline events (use SSE on
POST /v1/personas?stream=true). - User-action events (no
member.invited-style events today).
If you need a type that isn't here, the audit log is the broader record. Webhooks emit the edge-triggered subset that's worth pushing.