Skip to main content

Webhook Events

Complete list of available webhook events with their payloads.

Event Types

appointment.created

Triggered when a new appointment is created.

Payload:

{
"id": "evt_abc123",
"type": "appointment.created",
"created": "2026-01-21T14:30:00Z",
"data": {
"object": {
"id": 12345,
"departmentId": 5,
"department": {
"id": 5,
"name": "Passport Service",
"organization": {
"id": 1,
"name": "Ministry of Interior"
}
},
"dateTime": "2026-01-25T14:30:00",
"status": "SCHEDULED",
"name": "Jean Dupont",
"phone": "+224621234567",
"email": "jean.dupont@example.gn",
"qrCode": "https://moncreneau.gn/qr/12345",
"createdAt": "2026-01-21T14:30:00Z",
"creditsUsed": 1
}
}
}

Use Cases:

  • Send confirmation SMS
  • Create entry in your CRM
  • Notify team of new appointment

appointment.updated

Triggered when an appointment is modified (date, time, information).

Payload:

{
"id": "evt_def456",
"type": "appointment.updated",
"created": "2026-01-22T10:15:00Z",
"data": {
"object": {
"id": 12345,
"departmentId": 5,
"dateTime": "2026-01-26T10:00:00",
"status": "SCHEDULED",
"name": "Jean Dupont",
"phone": "+224621234567",
"updatedAt": "2026-01-22T10:15:00Z",
"changes": {
"dateTime": {
"from": "2026-01-25T14:30:00",
"to": "2026-01-26T10:00:00"
}
}
}
}
}

Use Cases:

  • Send change notification
  • Update calendars
  • Log modifications

appointment.cancelled

Triggered when an appointment is cancelled.

Payload:

{
"id": "evt_ghi789",
"type": "appointment.cancelled",
"created": "2026-01-23T16:45:00Z",
"data": {
"object": {
"id": 12345,
"departmentId": 5,
"dateTime": "2026-01-25T14:30:00",
"status": "CANCELLED",
"name": "Jean Dupont",
"phone": "+224621234567",
"cancelledAt": "2026-01-23T16:45:00Z",
"cancelledBy": "user",
"cancelReason": "Last minute impediment",
"creditsRefunded": 1
}
}
}

Use Cases:

  • Notify user of cancellation
  • Free up the slot
  • Refund/credit user

appointment.validated

Triggered when an appointment is validated by staff (presence confirmed).

Payload:

{
"id": "evt_jkl012",
"type": "appointment.validated",
"created": "2026-01-25T14:35:00Z",
"data": {
"object": {
"id": 12345,
"departmentId": 5,
"dateTime": "2026-01-25T14:30:00",
"status": "VALIDATED",
"name": "Jean Dupont",
"phone": "+224621234567",
"validatedAt": "2026-01-25T14:35:00Z",
"validatedBy": {
"id": 42,
"name": "Agent Martin"
}
}
}
}

Use Cases:

  • Mark appointment as honored
  • Generate invoice
  • Update statistics

appointment.completed

Triggered when an appointment is marked as completed.

Payload:

{
"id": "evt_mno345",
"type": "appointment.completed",
"created": "2026-01-25T15:00:00Z",
"data": {
"object": {
"id": 12345,
"departmentId": 5,
"dateTime": "2026-01-25T14:30:00",
"status": "COMPLETED",
"name": "Jean Dupont",
"phone": "+224621234567",
"completedAt": "2026-01-25T15:00:00Z",
"duration": 30,
"notes": "Document issued"
}
}
}

Use Cases:

  • Send satisfaction email
  • Archive file
  • Request feedback

Filter Events

When creating a webhook from the web interface, select only necessary events:

  • Go to Settings → Webhooks
  • Select only the events relevant to your integration
  • This reduces unnecessary traffic and improves performance

Event Handling

Route by Type

function handleWebhook(event) {
switch (event.type) {
case 'appointment.created':
return handleAppointmentCreated(event.data.object);

case 'appointment.cancelled':
return handleAppointmentCancelled(event.data.object);

case 'appointment.validated':
return handleAppointmentValidated(event.data.object);

default:
console.log(`Unhandled event: ${event.type}`);
}
}

Idempotence

Use event ID to avoid duplicates:

async function processWebhook(event) {
// Check if already processed
const exists = await db.webhookEvents.findOne({
eventId: event.id
});

if (exists) {
console.log(`Event ${event.id} already processed`);
return;
}

// Process event
await processEvent(event);

// Mark as processed
await db.webhookEvents.create({
eventId: event.id,
processedAt: new Date()
});
}

Next Steps