Documentation
Receive real-time notifications when events occur in the Cari platform.
Redis-backed event bus with publish/subscribe pattern.
Cari uses an internal event bus (Redis-backed) to propagate events between microservices. Key domain events are published as event envelopes that services consume asynchronously. The platform also supports inbound webhooks from external services like Stripe, LiveKit, and mobile money providers.
Internally, Cari uses a publish/subscribe pattern where events flow through a Redis queue. Each event is wrapped in an EventEnvelope containing metadata about the event and a typed payload:
{
"id": "event-uuid",
"topic": "cari.auth.user_created",
"timestamp": "2026-04-18T10:30:00Z",
"payload": {
"user_id": "user-uuid",
"email": "newuser@example.com",
"registration_role": "DOCTOR"
}
}Events published by Cari services for data synchronization and workflow automation.
cari.auth.user_created
Fired when a new user registers. Consumed by the Doctors service to auto-create a doctor profile when the registration role is DOCTOR.
cari.organization.member_added
Fired when a member is added to an organization. Consumed by the Doctors service to link doctor profiles to organizations.
Appointment booked
An appointment has been confirmed
Appointment cancelled
An appointment was cancelled
Appointment rescheduled
An appointment time was changed
Lab result received
A new lab result was ingested via HL7v2
Prescription created
A new prescription was written
Clinical record updated
A patient record was modified
Leave approved
A leave request was approved (consumed via /api/workforce/webhooks/leave-approved for roster updates).
Signature-verified webhook endpoints for external services.
Cari receives webhooks from external services. These endpoints verify signatures and process incoming events from third-party platforms.
POST /api/webhooks/stripe // Stripe sends events for: // - checkout.session.completed // - invoice.payment_succeeded // - invoice.payment_failed // - customer.subscription.updated // - customer.subscription.deleted // The webhook handler verifies the Stripe signature header // and processes subscription/payment state changes.
POST /api/webhooks/livekit // LiveKit sends events for telemedicine sessions: // - room_started — A video room was created // - room_finished — A video room ended // - participant_joined — A participant entered the room // - participant_left — A participant left the room // - track_published — A media track was published // Signature verification is performed inside the handler.
// Orange Money payment callbacks POST /api/payments/webhooks/orange-money // MTN MoMo payment callbacks POST /api/payments/webhooks/mtn-momo // These endpoints receive payment status updates: // - Payment successful // - Payment failed // - Payment pending/timeout
// WhatsApp Business API webhook verification GET /webhook // WhatsApp incoming message handler POST /webhook // Handles: // - Incoming patient messages // - Delivery receipts // - Read receipts
// Resend email delivery events POST /api/gtm/webhooks/resend // Inbound lead capture from external forms POST /api/gtm/webhooks/inbound
Consistent metadata wrapper for all internal events.
All internal events follow a consistent envelope format. The envelope contains metadata about the event and a typed payload:
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"topic": "cari.auth.user_created",
"timestamp": "2026-04-18T10:30:00Z",
"source_service": "cari-auth",
"payload": {
// Topic-specific payload
}
}
// Example: User Created Event
{
"id": "event-uuid",
"topic": "cari.auth.user_created",
"timestamp": "2026-04-18T10:30:00Z",
"payload": {
"user_id": "user-uuid",
"email": "doctor@hospital.org",
"first_name": "Sarah",
"last_name": "Chen",
"registration_role": "DOCTOR"
}
}
// Example: Organization Member Added
{
"id": "event-uuid",
"topic": "cari.organization.member_added",
"timestamp": "2026-04-18T11:00:00Z",
"payload": {
"organization_id": "org-uuid",
"user_id": "user-uuid",
"role": "ORG:DOCTOR"
}
}Capture failed events for inspection, retry, or discard.
When an event fails to process (deserialization errors, handler failures), it is automatically sent to the Dead Letter Queue (DLQ) instead of being lost. Administrators can inspect, retry, or discard failed events.
// List all failed events
GET /admin/dlq
// Check DLQ depth and alert status
GET /admin/dlq/depth
// Response:
{
"depth": 3,
"alert": true,
"oldest_event": "2026-04-17T08:15:00Z"
}
// Retry a failed event (re-queues for processing)
POST /admin/dlq/:id/retry
// Discard a failed event permanently
DELETE /admin/dlq/:id{
"id": "dlq-entry-uuid",
"event_id": "original-event-uuid",
"topic": "cari.auth.user_created",
"original_payload": "{ ... raw JSON ... }",
"error": "Failed to parse envelope: missing field 'email'",
"created_at": "2026-04-17T08:15:00Z"
}Configure webhook URLs in each external service dashboard.
To receive webhook notifications from external services integrated with Cari, you need to configure the webhook URL in each service's dashboard:
Go to your Stripe Dashboard > Developers > Webhooks. Add endpoint: https://api.cari.care/api/webhooks/stripe
Choose: checkout.session.completed, invoice.payment_succeeded, customer.subscription.*
Copy the webhook signing secret and set it as the STRIPE_WEBHOOK_SECRET environment variable.
In your LiveKit server configuration, set the webhook URL to https://api.cari.care/api/webhooks/livekit
Ensure the API key and secret match your LiveKit configuration. The handler verifies webhook signatures using the LiveKit SDK.
In Meta Business Manager, configure the webhook callback URL.
The verify endpoint (GET /webhook) handles the Meta verification challenge.
The handler endpoint (POST /webhook) processes incoming messages.
Guidelines for reliable webhook handling.
Respond quickly
Return a 200 status within 5 seconds. Process heavy logic asynchronously.
Handle duplicates
Use the event id field for idempotency. The same event may be delivered more than once.
Verify signatures
Always verify webhook signatures before processing. Never trust unsigned payloads.
Monitor the DLQ
Regularly check /admin/dlq/depth for failed events that need attention.
Use HTTPS
All webhook endpoints must use HTTPS. HTTP endpoints will be rejected.
Always verify webhook signatures before processing any event payload. Unsigned payloads may have been tampered with or sent by unauthorized sources.