Skip to content

Events

A single canonical registry of events flows across all 21 apps. Any app can emit; any app can subscribe.

Count: 101 event types (as of 2026-04-16) Transport: HMAC-SHA256 signed webhooks — see /integration/webhooksTyped payloads: @r-bsoftware/ecosystem-sdk/event-payloads

Shape of an event

ts
{
  eventId: string        // UUID for idempotency
  eventType: string      // e.g., "payment.received"
  timestamp: string      // ISO 8601
  source: string         // Emitting app slug
  organizationId: string // RBS org ID
  data: EventDataOf<eventType>  // Strongly typed
}

Naming convention

<domain>.<verb> — past-tense verb. Examples:

  • payment.received, payment.failed, payment.refunded
  • subscription.activated, subscription.cancelled, subscription.trial_expiring
  • cfdi.stamped, cfdi.cancelled, cfdi.failed
  • customer.created, customer.updated, customer.linked
  • deal.created, deal.updated, deal.billing_charged
  • booking.created, booking.cancelled, appointment.completed

Consuming events

ts
import { createWebhookHandler } from '@r-bsoftware/ecosystem-sdk'
import type { EventDataOf } from '@r-bsoftware/ecosystem-sdk/event-payloads'

export const POST = createWebhookHandler({
  secret: process.env.WEBHOOK_SECRET!,
  handlers: {
    'payment.received': async (event) => {
      const data = event.data as EventDataOf<'payment.received'>
      // data.amountCents, data.currency, data.invoiceId — typed
    },
  }
})

Emitting events

Each emitting app posts to the Camino webhook fan-out or direct-delivers to registered subscribers. The createWebhookSender factory in the SDK handles signing + retries.

Full registry

The complete 101-event registry, with payload shape and emitter app per event, lives at /reference/events.

Source of truth

  • Registry JSON: ecosystem-sdk/packages/mcp-server/src/registry/events.json (canonical; 101 entries)
  • Typed payloads: @r-bsoftware/ecosystem-sdk/event-payloads
  • SDK factories: webhook-sender.ts, webhook-handler.ts

Gotchas

  • Never invent event names locally. Add to the registry first, regen types, then emit. Mancha emitted appointment_done for three sprints before we reconciled to appointment.completed.
  • Payload drift is real. Always cast event.data as EventDataOf<'<name>'> — don't hand-type. The SDK types are the source of truth.
  • Unknown event types must be ignored, not rejected with 4xx. The ecosystem grows; older handlers should return 200 for unrecognized types.

Red Broom Software Ecosystem