Skip to main content
Chirp delivers webhooks as HTTP POST requests to your endpoint whenever a subscribed event occurs. This page documents every event type across SMS, WhatsApp, and Calling, including the payload schema and when each event fires.
New events are opt-in. Existing webhook configurations only receive the events they were created with. To receive any of the events marked New below, update your webhook’s events array via the Update Webhook endpoint or the dashboard.

Delivery behavior

All events share the same delivery contract:
PropertyValue
MethodPOST
Content-Typeapplication/json
Timeout5 seconds
Retry attempts5 (exponential backoff)
DeduplicationEvents may be delivered more than once; use event + payload IDs to deduplicate

Event categories


SMS Messages

SMS message events fire for inbound and outbound SMS/MMS messages.

messages.sms.received

Fires immediately when an inbound SMS or MMS message arrives on one of your phone numbers.
messages.sms.received
{
  "event": "messages.sms.received",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "message": {
      "id": "msg_sms_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "direction": "inbound",
      "from": "+15551234567",
      "to": "+15559876543",
      "text": "Hello!",
      "type": "sms",
      "mediaUrl": null,
      "mediaId": null,
      "receivedAt": "2024-01-15T10:30:00.000Z",
      "sentAt": null,
      "completedAt": null,
      "occurredAt": "2024-01-15T10:30:00.000Z"
    },
    "app": { "id": "app_2DbBs7GWhGvVNJGrDXr5RG0mBWI", "name": "My App" }
  }
}
For MMS, type is mms and mediaUrl / mediaId reference the attached media.

messages.sms.sent

Fires when a message you sent has been accepted by the carrier.
messages.sms.sent
{
  "event": "messages.sms.sent",
  "timestamp": "2024-01-15T10:30:01.000Z",
  "data": {
    "message": {
      "id": "msg_sms_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "direction": "outbound",
      "from": "+15559876543",
      "to": "+15551234567",
      "text": "Hi back!",
      "type": "sms",
      "mediaUrl": null,
      "mediaId": null,
      "receivedAt": null,
      "sentAt": "2024-01-15T10:30:01.000Z",
      "completedAt": null,
      "occurredAt": "2024-01-15T10:30:01.000Z"
    },
    "app": { "id": "app_2DbBs7GWhGvVNJGrDXr5RG0mBWI", "name": "My App" }
  }
}

messages.sms.delivered

Fires when the carrier confirms delivery to the recipient’s device.
messages.sms.delivered
{
  "event": "messages.sms.delivered",
  "timestamp": "2024-01-15T10:30:05.000Z",
  "data": {
    "message": {
      "id": "msg_sms_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "direction": "outbound",
      "from": "+15559876543",
      "to": "+15551234567",
      "text": "Hi back!",
      "type": "sms",
      "mediaUrl": null,
      "mediaId": null,
      "receivedAt": null,
      "sentAt": "2024-01-15T10:30:01.000Z",
      "completedAt": "2024-01-15T10:30:05.000Z",
      "occurredAt": "2024-01-15T10:30:05.000Z"
    },
    "app": { "id": "app_2DbBs7GWhGvVNJGrDXr5RG0mBWI", "name": "My App" }
  }
}

messages.sms.failed

Fires when message delivery fails. The error field uses the same structure as API error responses.
messages.sms.failed
{
  "event": "messages.sms.failed",
  "timestamp": "2024-01-15T10:30:05.000Z",
  "data": {
    "message": {
      "id": "msg_sms_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "direction": "outbound",
      "from": "+15559876543",
      "to": "+15551234567",
      "text": "Hi back!",
      "type": "sms",
      "mediaUrl": null,
      "mediaId": null,
      "receivedAt": null,
      "sentAt": "2024-01-15T10:30:01.000Z",
      "completedAt": null,
      "occurredAt": "2024-01-15T10:30:05.000Z"
    },
    "app": { "id": "app_2DbBs7GWhGvVNJGrDXr5RG0mBWI", "name": "My App" },
    "error": {
      "type": "provider_error",
      "code": "message_undeliverable",
      "message": "Message could not be delivered",
      "provider": {
        "source": "telnyx",
        "code": "40010",
        "message": "Destination unreachable"
      }
    }
  }
}

WhatsApp Messages

WhatsApp message events use a single payload shape (data.message) for both inbound and outbound messages. The direction and timestamp fields tell you which lifecycle stage you’re at.

messages.whatsapp.received

Fires immediately when an inbound WhatsApp message arrives on one of your phone numbers.
messages.whatsapp.received
{
  "event": "messages.whatsapp.received",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "message": {
      "id": "msg_wa_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "direction": "inbound",
      "recipientType": "individual",
      "from": "+15551234567",
      "to": "+15559876543",
      "text": "Hello!",
      "type": "text",
      "media": null,
      "audio": null,
      "sticker": null,
      "location": null,
      "button": null,
      "contacts": null,
      "reaction": null,
      "interactive": null,
      "order": null,
      "system": null,
      "context": null,
      "receivedAt": "2024-01-15T10:30:00.000Z",
      "sentAt": null,
      "occurredAt": "2024-01-15T10:30:00.000Z",
      "conversationWindow": null
    },
    "app": { "id": "app_2DbBs7GWhGvVNJGrDXr5RG0mBWI", "name": "My App" }
  }
}
For media messages (type is image, video, audio, document, sticker, location, contacts, reaction, interactive, order, or system), the corresponding nested object on data.message is populated. See Receiving WhatsApp messages for examples of every type.

messages.whatsapp.sent

Fires when a message you sent has been accepted by WhatsApp servers.
messages.whatsapp.sent
{
  "event": "messages.whatsapp.sent",
  "timestamp": "2024-01-15T10:30:01.000Z",
  "data": {
    "message": {
      "id": "msg_wa_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "direction": "outbound",
      "recipientType": "individual",
      "from": "+15559876543",
      "to": "+15551234567",
      "text": "Hi back!",
      "type": "text",
      "sentAt": "2024-01-15T10:30:01.000Z",
      "occurredAt": "2024-01-15T10:30:01.000Z",
      "conversationWindow": null
    },
    "app": { "id": "app_2DbBs7GWhGvVNJGrDXr5RG0mBWI", "name": "My App" }
  }
}

messages.whatsapp.delivered

Fires when WhatsApp confirms the message was delivered to the recipient’s device.
messages.whatsapp.delivered
{
  "event": "messages.whatsapp.delivered",
  "timestamp": "2024-01-15T10:30:05.000Z",
  "data": {
    "message": {
      "id": "msg_wa_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "direction": "outbound",
      "recipientType": "individual",
      "from": "+15559876543",
      "to": "+15551234567",
      "text": "Hi back!",
      "type": "text",
      "sentAt": "2024-01-15T10:30:01.000Z",
      "occurredAt": "2024-01-15T10:30:05.000Z",
      "conversationWindow": {
        "category": "service",
        "expiresAt": "2024-01-16T10:30:05.000Z"
      }
    },
    "app": { "id": "app_2DbBs7GWhGvVNJGrDXr5RG0mBWI", "name": "My App" }
  }
}

messages.whatsapp.read

Fires when the recipient opens and reads the message.
messages.whatsapp.read
{
  "event": "messages.whatsapp.read",
  "timestamp": "2024-01-15T10:30:10.000Z",
  "data": {
    "message": {
      "id": "msg_wa_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "direction": "outbound",
      "recipientType": "individual",
      "from": "+15559876543",
      "to": "+15551234567",
      "text": "Hi back!",
      "type": "text",
      "sentAt": "2024-01-15T10:30:01.000Z",
      "occurredAt": "2024-01-15T10:30:10.000Z"
    },
    "app": { "id": "app_2DbBs7GWhGvVNJGrDXr5RG0mBWI", "name": "My App" }
  }
}

messages.whatsapp.failed

Fires when message delivery fails. The error field uses the same structure as API error responses.
messages.whatsapp.failed
{
  "event": "messages.whatsapp.failed",
  "timestamp": "2024-01-15T10:30:05.000Z",
  "data": {
    "message": {
      "id": "msg_wa_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "direction": "outbound",
      "recipientType": "individual",
      "from": "+15559876543",
      "to": "+15551234567",
      "text": "Hi back!",
      "type": "text",
      "sentAt": "2024-01-15T10:30:01.000Z",
      "occurredAt": "2024-01-15T10:30:05.000Z"
    },
    "app": { "id": "app_2DbBs7GWhGvVNJGrDXr5RG0mBWI", "name": "My App" },
    "error": {
      "type": "provider_error",
      "code": "message_undeliverable",
      "message": "Message could not be delivered",
      "provider": {
        "source": "meta",
        "code": 131026,
        "message": "Message Undeliverable"
      }
    }
  }
}
When Meta returns vague failure codes such as account_restricted or display_name_not_approved, Chirp enriches the error.provider field with Health Status details. See WhatsApp webhooks for the enriched shape.

WhatsApp Templates

Template events fire when Meta updates a template’s status, quality, category, or components.

templates.whatsapp.created

Fires when a template is approved or first synced to Chirp.
templates.whatsapp.created
{
  "event": "templates.whatsapp.created",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "template": {
      "id": "wht_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "metaTemplateId": "123456789012345",
      "name": "order_confirmation",
      "language": "en_US",
      "category": "UTILITY",
      "status": "APPROVED",
      "qualityScore": "GREEN"
    },
    "whatsappBusinessProfile": {
      "id": "wabp_2DbBs7GWhGvVNJGrDXr5RG0mBWI"
    },
    "apps": [
      { "id": "app_2DbBs7GWhGvVNJGrDXr5RG0mBWI", "name": "My App" }
    ]
  }
}

templates.whatsapp.updated

Fires when any template field changes: status, quality score, category, or components. The change.type field describes what changed.
templates.whatsapp.updated (quality change)
{
  "event": "templates.whatsapp.updated",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "template": {
      "id": "wht_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "metaTemplateId": "123456789012345",
      "name": "order_confirmation",
      "language": "en_US",
      "category": "UTILITY",
      "status": "PAUSED",
      "qualityScore": "RED"
    },
    "whatsappBusinessProfile": {
      "id": "wabp_2DbBs7GWhGvVNJGrDXr5RG0mBWI"
    },
    "apps": [
      { "id": "app_2DbBs7GWhGvVNJGrDXr5RG0mBWI", "name": "My App" }
    ],
    "change": {
      "type": "quality",
      "previousQualityScore": "GREEN",
      "newQualityScore": "RED",
      "pauseInfo": {
        "title": "FIRST_PAUSE",
        "description": "Template paused due to low quality rating"
      }
    }
  }
}

templates.whatsapp.deleted

Fires when a template is deleted from Meta.
templates.whatsapp.deleted
{
  "event": "templates.whatsapp.deleted",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "template": {
      "id": "wht_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "metaTemplateId": "123456789012345",
      "name": "order_confirmation",
      "language": "en_US",
      "category": "UTILITY",
      "status": "REJECTED",
      "qualityScore": null
    },
    "whatsappBusinessProfile": {
      "id": "wabp_2DbBs7GWhGvVNJGrDXr5RG0mBWI"
    },
    "apps": [],
    "change": {
      "type": "status",
      "statusEvent": "DELETED"
    }
  }
}

templates.whatsapp.connected

Fires when an existing Meta template is linked to one of your Chirp apps.
templates.whatsapp.connected
{
  "event": "templates.whatsapp.connected",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "template": {
      "id": "wht_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "metaTemplateId": "123456789012345",
      "name": "order_confirmation",
      "language": "en_US",
      "category": "UTILITY",
      "status": "APPROVED",
      "qualityScore": "GREEN"
    },
    "whatsappBusinessProfile": {
      "id": "wabp_2DbBs7GWhGvVNJGrDXr5RG0mBWI"
    },
    "apps": [
      { "id": "app_2DbBs7GWhGvVNJGrDXr5RG0mBWI", "name": "My App" }
    ]
  }
}

WhatsApp Contacts

Contact events track the lifecycle of contacts you’ve interacted with via WhatsApp.

contacts.whatsapp.created

Fires when Chirp first sees a contact (first message sent or received with that phone number).
contacts.whatsapp.created
{
  "event": "contacts.whatsapp.created",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "contact": {
      "id": "waco_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "phoneNumber": "+15551234567",
      "profileName": "John Doe",
      "firstSeenAt": "2024-01-15T10:30:00.000Z",
      "lastSeenAt": "2024-01-15T10:30:00.000Z"
    },
    "whatsappPhoneNumber": {
      "id": "wapn_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "displayPhoneNumber": "+15559876543"
    },
    "app": { "id": "app_2DbBs7GWhGvVNJGrDXr5RG0mBWI", "name": "My App" }
  }
}

contacts.whatsapp.updated

Fires when a contact’s profile name changes.
contacts.whatsapp.updated
{
  "event": "contacts.whatsapp.updated",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "contact": {
      "id": "waco_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "phoneNumber": "+15551234567",
      "profileName": "Johnny D",
      "firstSeenAt": "2024-01-01T09:00:00.000Z",
      "lastSeenAt": "2024-01-15T10:30:00.000Z"
    },
    "whatsappPhoneNumber": {
      "id": "wapn_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "displayPhoneNumber": "+15559876543"
    },
    "app": { "id": "app_2DbBs7GWhGvVNJGrDXr5RG0mBWI", "name": "My App" },
    "change": {
      "field": "profile_name",
      "previousValue": "John Doe",
      "newValue": "Johnny D"
    }
  }
}

contacts.whatsapp.deleted

Fires when a contact is removed (e.g., opt-out or data deletion).
contacts.whatsapp.deleted
{
  "event": "contacts.whatsapp.deleted",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "contact": {
      "id": "waco_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "phoneNumber": "+15551234567",
      "profileName": "John Doe",
      "firstSeenAt": "2024-01-01T09:00:00.000Z",
      "lastSeenAt": "2024-01-14T18:00:00.000Z"
    },
    "whatsappPhoneNumber": {
      "id": "wapn_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "displayPhoneNumber": "+15559876543"
    },
    "app": { "id": "app_2DbBs7GWhGvVNJGrDXr5RG0mBWI", "name": "My App" }
  }
}

whatsapp.contact.preferences_updated New

Fires when a contact changes their marketing message preferences (opt-in/opt-out). Meta delivers this in real-time.
whatsapp.contact.preferences_updated
{
  "event": "whatsapp.contact.preferences_updated",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "contact": {
      "id": "wac_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "phoneNumber": "+15551234567"
    },
    "preferences": {
      "marketing": {
        "status": "stop",
        "updatedAt": "2024-01-15T10:30:00.000Z"
      }
    },
    "app": { "id": "app_2DbBs7GWhGvVNJGrDXr5RG0mBWI", "name": "My App" }
  }
}
preferences.marketing.status is "stop" when the contact opts out of marketing messages and "resume" when they opt back in. Stop sending marketing messages immediately to remain compliant with WhatsApp’s policies.

whatsapp.contact.automatic_event New

Fires when a Click-to-WhatsApp (CTWA) ad triggers a conversion event (e.g., Purchase). Used for ads attribution. Meta delivers this in real-time.
whatsapp.contact.automatic_event
{
  "event": "whatsapp.contact.automatic_event",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "eventName": "Purchase",
    "ctwaClid": "AYABCxxx",
    "occurredAt": "2024-01-15T10:30:00.000Z",
    "phoneNumberId": "106540352242922"
  }
}
ctwaClid is the click ID from the ad — pass it back to Meta’s Conversions API to close the attribution loop. It is null for Status ad placements.

WhatsApp Groups

Group events fire when WhatsApp groups owned by your phone numbers change. Every payload includes the affected group, the owning whatsappPhoneNumber, and the app. See WhatsApp Groups for the corresponding REST API.

groups.whatsapp.created

Fires when a new group is created and owned by one of your phone numbers.
groups.whatsapp.created
{
  "event": "groups.whatsapp.created",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "group": {
      "id": "wag_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "subject": "Support Team",
      "description": "Customer support group",
      "joinApprovalMode": "auto_approve",
      "inviteLink": "https://chat.whatsapp.com/abc123",
      "suspended": false,
      "totalParticipantCount": 5,
      "createdAt": "2024-01-15T10:30:00.000Z"
    },
    "whatsappPhoneNumber": {
      "id": "wapn_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "displayPhoneNumber": "+15559876543"
    },
    "app": { "id": "app_2DbBs7GWhGvVNJGrDXr5RG0mBWI", "name": "My App" }
  }
}

groups.whatsapp.deleted

Fires when a group is deleted. The payload shape is identical to groups.whatsapp.created with event set to groups.whatsapp.deleted.

groups.whatsapp.suspended

Fires when WhatsApp suspends a group (e.g., for policy violations). The payload shape is identical to groups.whatsapp.created with group.suspended set to true.

groups.whatsapp.suspension_cleared

Fires when WhatsApp lifts a previous suspension. The payload shape is identical to groups.whatsapp.created with group.suspended set to false.

groups.whatsapp.participant_added

Fires when one or more participants join the group.
groups.whatsapp.participant_added
{
  "event": "groups.whatsapp.participant_added",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "group": {
      "id": "wag_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "subject": "Support Team",
      "description": "Customer support group",
      "joinApprovalMode": "auto_approve",
      "inviteLink": "https://chat.whatsapp.com/abc123",
      "suspended": false,
      "totalParticipantCount": 6,
      "createdAt": "2024-01-15T10:30:00.000Z"
    },
    "participants": [
      { "waId": "15551234567", "joinedAt": "2024-01-15T10:30:00.000Z" }
    ],
    "whatsappPhoneNumber": {
      "id": "wapn_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "displayPhoneNumber": "+15559876543"
    },
    "app": { "id": "app_2DbBs7GWhGvVNJGrDXr5RG0mBWI", "name": "My App" }
  }
}
participants[].waId is the participant’s WhatsApp ID (phone number without the +). joinedAt may be null when WhatsApp does not provide a timestamp.

groups.whatsapp.participant_removed

Fires when one or more participants are removed by an admin.
groups.whatsapp.participant_removed
{
  "event": "groups.whatsapp.participant_removed",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "group": {
      "id": "wag_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "subject": "Support Team",
      "description": "Customer support group",
      "joinApprovalMode": "auto_approve",
      "inviteLink": "https://chat.whatsapp.com/abc123",
      "suspended": false,
      "totalParticipantCount": 5,
      "createdAt": "2024-01-15T10:30:00.000Z"
    },
    "participants": [
      { "waId": "15551234567", "joinedAt": "2024-01-15T10:30:00.000Z" }
    ],
    "initiatedBy": "business",
    "whatsappPhoneNumber": {
      "id": "wapn_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "displayPhoneNumber": "+15559876543"
    },
    "app": { "id": "app_2DbBs7GWhGvVNJGrDXr5RG0mBWI", "name": "My App" }
  }
}
initiatedBy is "business" when an admin removed the participant, or "participant" when the participant left voluntarily (in which case groups.whatsapp.participant_left typically fires instead).

groups.whatsapp.participant_left

Fires when a single participant voluntarily leaves the group.
groups.whatsapp.participant_left
{
  "event": "groups.whatsapp.participant_left",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "group": {
      "id": "wag_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "subject": "Support Team",
      "description": "Customer support group",
      "joinApprovalMode": "auto_approve",
      "inviteLink": "https://chat.whatsapp.com/abc123",
      "suspended": false,
      "totalParticipantCount": 4,
      "createdAt": "2024-01-15T10:30:00.000Z"
    },
    "participant": { "waId": "15551234567", "joinedAt": "2024-01-15T10:30:00.000Z" },
    "whatsappPhoneNumber": {
      "id": "wapn_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "displayPhoneNumber": "+15559876543"
    },
    "app": { "id": "app_2DbBs7GWhGvVNJGrDXr5RG0mBWI", "name": "My App" }
  }
}

groups.whatsapp.join_request_created

Fires when someone requests to join a group whose joinApprovalMode is approval_required.
groups.whatsapp.join_request_created
{
  "event": "groups.whatsapp.join_request_created",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "group": {
      "id": "wag_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "subject": "Support Team",
      "description": "Customer support group",
      "joinApprovalMode": "approval_required",
      "inviteLink": "https://chat.whatsapp.com/abc123",
      "suspended": false,
      "totalParticipantCount": 5,
      "createdAt": "2024-01-15T10:30:00.000Z"
    },
    "joinRequest": {
      "id": "wagjr_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "waId": "15551234567",
      "createdAt": "2024-01-15T10:30:00.000Z"
    },
    "whatsappPhoneNumber": {
      "id": "wapn_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "displayPhoneNumber": "+15559876543"
    },
    "app": { "id": "app_2DbBs7GWhGvVNJGrDXr5RG0mBWI", "name": "My App" }
  }
}
Approve or reject the request via POST /v1/whatsapp/groups/{groupId}/join-requests/approve or /reject.

groups.whatsapp.join_request_revoked

Fires when a pending join request is revoked (either by the requester or the admin). The payload shape is identical to groups.whatsapp.join_request_created with event set to groups.whatsapp.join_request_revoked.

groups.whatsapp.settings_updated

Fires when the group subject, description, or profile picture changes.
groups.whatsapp.settings_updated
{
  "event": "groups.whatsapp.settings_updated",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "group": {
      "id": "wag_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "subject": "Customer Support",
      "description": "Customer support group",
      "joinApprovalMode": "auto_approve",
      "inviteLink": "https://chat.whatsapp.com/abc123",
      "suspended": false,
      "totalParticipantCount": 5,
      "createdAt": "2024-01-15T10:30:00.000Z"
    },
    "changes": {
      "subject": {
        "text": "Customer Support",
        "updateSuccessful": true
      }
    },
    "whatsappPhoneNumber": {
      "id": "wapn_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "displayPhoneNumber": "+15559876543"
    },
    "app": { "id": "app_2DbBs7GWhGvVNJGrDXr5RG0mBWI", "name": "My App" }
  }
}
changes may contain any of subject, description, or profilePicture. When an update fails, updateSuccessful is false and the corresponding errors array is populated.

WhatsApp Account

Account events fire when a WhatsApp Business Account (WABA) is connected or disconnected via Embedded Signup, or when Meta raises an alert.

whatsapp.account.connected

Fires immediately when a customer completes Embedded Signup and grants your app access to their WABA.
whatsapp.account.connected
{
  "event": "whatsapp.account.connected",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "whatsappBusinessProfile": {
      "id": "wabp_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "metaWabaId": "1234567890",
      "businessName": "My Business"
    },
    "phoneNumbers": [
      {
        "id": "wapn_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
        "displayPhoneNumber": "+15551234567"
      }
    ],
    "state": "user_123_signup_abc",
    "metadata": {
      "externalUserId": "user_123",
      "businessName": "Acme Corp"
    }
  }
}
state and metadata are values you passed during the Embedded Signup flow to correlate the event with your internal user.

whatsapp.account.disconnected

Fires when a WABA is disconnected — either by the customer revoking access or by your app removing it.
whatsapp.account.disconnected
{
  "event": "whatsapp.account.disconnected",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "whatsappBusinessProfile": {
      "id": "wabp_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "metaWabaId": "1234567890",
      "businessName": "My Business"
    },
    "phoneNumbers": [
      {
        "id": "wapn_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
        "displayPhoneNumber": "+15551234567"
      }
    ]
  }
}

whatsapp.account.alert_raised New

Fires when Meta raises a compliance or policy alert against a WABA or phone number. Meta delivers this in real-time.
whatsapp.account.alert_raised
{
  "event": "whatsapp.account.alert_raised",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "whatsappBusinessProfile": {
      "id": "wabp_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "metaWabaId": "1234567890",
      "businessName": "My Business"
    },
    "alert": {
      "entityType": "WABA",
      "entityId": "1234567890",
      "alertType": "ACCOUNT_REVIEW",
      "alertSeverity": "WARNING",
      "alertStatus": "ACTIVE",
      "alertDescription": "Your account is under review."
    }
  }
}
Any field in alert may be null if Meta does not provide it for that alert type.

WhatsApp WABA

whatsapp.waba.review_updated New

Fires when Meta completes a policy review of the WABA. Meta delivers this in real-time.
whatsapp.waba.review_updated
{
  "event": "whatsapp.waba.review_updated",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "whatsappBusinessProfile": {
      "id": "wabp_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "metaWabaId": "1234567890",
      "businessName": "My Business"
    },
    "review": {
      "decision": "APPROVED",
      "decidedAt": "2024-01-15T10:30:00.000Z"
    }
  }
}
review.decision is one of APPROVED, REJECTED, PENDING, or DEFERRED.

whatsapp.waba.capability_changed New

Fires when a WABA capability value changes — for example, when your daily conversation limit is upgraded. Meta delivers this in real-time.
whatsapp.waba.capability_changed
{
  "event": "whatsapp.waba.capability_changed",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "whatsappBusinessProfile": {
      "id": "wabp_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "metaWabaId": "1234567890",
      "businessName": "My Business"
    },
    "capability": "max_daily_conversations_per_business",
    "oldValue": "1000",
    "newValue": "10000"
  }
}
oldValue is null if this is the first time Chirp has observed the capability.

WhatsApp Phone Numbers

Phone number events track quality, name verification, security, and registration changes.

whatsapp.phone_number.name_updated New

Fires when Meta makes a decision on a display name change request. Meta delivers this in real-time.
whatsapp.phone_number.name_updated
{
  "event": "whatsapp.phone_number.name_updated",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "phoneNumberId": "wapn_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
    "metaPhoneNumberId": "123456789",
    "displayPhoneNumber": "+15551234567",
    "nameStatus": "APPROVED",
    "requestedVerifiedName": "My Business Name",
    "nameRejectionReason": null,
    "nameDecisionAt": "2024-01-15T10:30:00.000Z"
  }
}
nameStatus is one of APPROVED, REJECTED, PENDING, or DEFERRED. When nameStatus is REJECTED, nameRejectionReason contains Meta’s reason code.

whatsapp.phone_number.quality_changed New

Fires when Meta updates the quality rating or throughput tier for a phone number. Meta delivers this in real-time.
whatsapp.phone_number.quality_changed
{
  "event": "whatsapp.phone_number.quality_changed",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "phoneNumberId": "wapn_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
    "displayPhoneNumber": "+15551234567",
    "qualityRating": "GREEN",
    "qualityEvent": "FLAGGED",
    "throughputTier": "STANDARD"
  }
}
qualityRating is GREEN, YELLOW, or RED, or null for newly-onboarded phones with no rating yet. qualityEvent describes what triggered the change: FLAGGED, ONBOARDED, ONBOARDING, UPGRADE, or THROUGHPUT_UPGRADE.

whatsapp.phone_number.security_event New

Fires when a two-step verification PIN event occurs on a phone number. Meta delivers this in real-time.
whatsapp.phone_number.security_event
{
  "event": "whatsapp.phone_number.security_event",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "phoneNumberId": "wapn_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
    "displayPhoneNumber": "+15551234567",
    "eventType": "PIN_CHANGED",
    "requester": "61555822107539"
  }
}
eventType is one of:
  • PIN_CHANGED — two-step PIN was changed
  • PIN_RESET_REQUEST — a PIN reset was requested
  • PIN_REQUEST_SUCCESS — PIN reset completed successfully
requester is the Meta Business Suite user ID who triggered the event, or null if not provided by Meta.

whatsapp.phone_number.deregistered New

Fires when Chirp detects that a phone number’s verification status has changed from verified to unverified. This event is poll-driven — phones with messages in the last 7 days are checked every 15 minutes; idle phones every 6 hours. Delivery may lag by up to ~6 hours for idle numbers.
whatsapp.phone_number.deregistered
{
  "event": "whatsapp.phone_number.deregistered",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "phoneNumberId": "wapn_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
    "metaPhoneNumberId": "123456789",
    "displayPhoneNumber": "+15551234567",
    "previousVerified": true,
    "currentVerified": false
  }
}
A deregistered phone number cannot send or receive WhatsApp messages until it is re-registered. If you receive this event, re-register the phone number via the Chirp API or dashboard as soon as possible.

Partner & Payment

These events are delivered as-is from Meta. Chirp logs them for observability but does not currently take automated action on them.

whatsapp.partner_solution.updated New

Fires when a Meta multi-partner solution linked to the WABA is created or updated. Meta delivers this in real-time.
whatsapp.partner_solution.updated
{
  "event": "whatsapp.partner_solution.updated",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "event": "SOLUTION_CREATED",
    "solutionId": "774485461512159",
    "solutionStatus": "ACTIVE"
  }
}

whatsapp.payment_config.updated New

Fires when the payment gateway configuration for the WABA changes. Meta delivers this in real-time.
whatsapp.payment_config.updated
{
  "event": "whatsapp.payment_config.updated",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "whatsappBusinessProfile": {
      "id": "wabp_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "metaWabaId": "1234567890",
      "businessName": "My Business"
    },
    "configurationName": "razorpay-prod",
    "providerName": "razorpay",
    "status": "Active"
  }
}

Calling

Calling events track the lifecycle of voice calls. Every payload includes an eventId for idempotency and a data.call object with the call’s identifiers and channel routing. See Calling Webhooks Setup for handler examples.

calls.initiated

Fires when a call is created (outbound) or an incoming call is received (inbound).
calls.initiated
{
  "event": "calls.initiated",
  "eventId": "evt_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "call": {
      "id": "call_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "direction": "outbound",
      "from": "+15551234567",
      "to": "+15559876543",
      "fromChannel": "pstn",
      "toChannel": "pstn"
    },
    "app": { "id": "app_2DbBs7GWhGvVNJGrDXr5RG0mBWI" }
  }
}

calls.ringing

Fires when an outbound call is ringing at the destination.

calls.answered

Fires when the call is answered. The data.call object includes answeredAt and answeredBy.

calls.completed

Fires when a call ends normally. The data.call object includes duration, endReason, and endedAt.

calls.failed

Fires when a call fails. The payload includes a data.error object with type, code, and message.

calls.no_answer

Fires when no one answers a ringing outbound call before it times out.

calls.participant_joined

Fires when a participant joins the call.
calls.participant_joined
{
  "event": "calls.participant_joined",
  "eventId": "evt_0LjJA5OEpQDDVRQzLFz3ZO8uJEQ",
  "timestamp": "2024-01-15T10:30:05.000Z",
  "data": {
    "call": {
      "id": "call_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "direction": "outbound",
      "from": "+15551234567",
      "to": "+15559876543",
      "fromChannel": "pstn",
      "toChannel": "pstn"
    },
    "participant": {
      "id": "part_abc123",
      "type": "phone",
      "displayName": "John Doe",
      "phoneNumber": "+15559876543",
      "joinedAt": "2024-01-15T10:30:05.000Z"
    },
    "app": { "id": "app_2DbBs7GWhGvVNJGrDXr5RG0mBWI" }
  }
}

calls.participant_left

Fires when a participant leaves the call. The participant object includes duration and leftAt.

calls.recording.completed

Fires when a call recording has finished processing and a signed download URL is available.
calls.recording.completed
{
  "event": "calls.recording.completed",
  "eventId": "evt_2NlLC7QGrSFFXTSBNHB5BQ0wLGS",
  "timestamp": "2024-01-15T10:33:00.000Z",
  "data": {
    "call": {
      "id": "call_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "direction": "outbound",
      "from": "+15551234567",
      "to": "+15559876543",
      "fromChannel": "pstn",
      "toChannel": "pstn"
    },
    "recording": {
      "id": "call_rec_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "duration": 120,
      "url": "https://storage.buildwithchirp.com/recordings/call_rec_2DbBs7GWhGvVNJGrDXr5RG0mBWI.mp4?signed=...",
      "format": "mp4",
      "size": 1048576
    },
    "app": { "id": "app_2DbBs7GWhGvVNJGrDXr5RG0mBWI" }
  }
}

calls.voicemail.received

Fires when a voicemail is left. The payload includes the audio URL and an optional transcription.
Recording and voicemail url fields are time-limited signed URLs. To access them later, use the Recordings API to mint a fresh URL.

Full event list

EventCategoryTriggerCadence
messages.sms.receivedSMS MessagesTelnyx webhookReal-time
messages.sms.sentSMS MessagesInternalReal-time
messages.sms.deliveredSMS MessagesTelnyx webhookReal-time
messages.sms.failedSMS MessagesTelnyx webhookReal-time
messages.whatsapp.receivedWhatsApp MessagesMeta webhookReal-time
messages.whatsapp.sentWhatsApp MessagesInternalReal-time
messages.whatsapp.deliveredWhatsApp MessagesMeta webhookReal-time
messages.whatsapp.readWhatsApp MessagesMeta webhookReal-time
messages.whatsapp.failedWhatsApp MessagesMeta webhookReal-time
templates.whatsapp.createdTemplatesMeta webhookReal-time
templates.whatsapp.updatedTemplatesMeta webhookReal-time
templates.whatsapp.deletedTemplatesMeta webhookReal-time
templates.whatsapp.connectedTemplatesInternalReal-time
contacts.whatsapp.createdContactsInternalReal-time
contacts.whatsapp.updatedContactsInternalReal-time
contacts.whatsapp.deletedContactsInternalReal-time
whatsapp.contact.preferences_updatedContactsMeta webhookReal-time
whatsapp.contact.automatic_eventContactsMeta webhookReal-time
groups.whatsapp.createdGroupsMeta webhookReal-time
groups.whatsapp.deletedGroupsMeta webhookReal-time
groups.whatsapp.suspendedGroupsMeta webhookReal-time
groups.whatsapp.suspension_clearedGroupsMeta webhookReal-time
groups.whatsapp.participant_addedGroupsMeta webhookReal-time
groups.whatsapp.participant_removedGroupsMeta webhookReal-time
groups.whatsapp.participant_leftGroupsMeta webhookReal-time
groups.whatsapp.join_request_createdGroupsMeta webhookReal-time
groups.whatsapp.join_request_revokedGroupsMeta webhookReal-time
groups.whatsapp.settings_updatedGroupsMeta webhookReal-time
whatsapp.account.connectedAccountInternalReal-time
whatsapp.account.disconnectedAccountInternalReal-time
whatsapp.account.alert_raisedAccountMeta webhookReal-time
whatsapp.waba.review_updatedWABAMeta webhookReal-time
whatsapp.waba.capability_changedWABAMeta webhookReal-time
whatsapp.phone_number.name_updatedPhone NumbersMeta webhookReal-time
whatsapp.phone_number.quality_changedPhone NumbersMeta webhookReal-time
whatsapp.phone_number.security_eventPhone NumbersMeta webhookReal-time
whatsapp.phone_number.deregisteredPhone NumbersPoll≤15 min (active) / ≤6 h (idle)
whatsapp.partner_solution.updatedPartner & PaymentMeta webhookReal-time
whatsapp.payment_config.updatedPartner & PaymentMeta webhookReal-time
calls.initiatedCallingInternalReal-time
calls.ringingCallingInternalReal-time
calls.answeredCallingInternalReal-time
calls.completedCallingInternalReal-time
calls.failedCallingInternalReal-time
calls.no_answerCallingInternalReal-time
calls.participant_joinedCallingLiveKitReal-time
calls.participant_leftCallingLiveKitReal-time
calls.recording.completedCallingLiveKitNear real-time
calls.voicemail.receivedCallingInternalReal-time
✦ New events — must be explicitly added to your webhook’s events array to receive.