Fires when a patient sends a message in the patient portal (any channel: clinical, support, billing, or shipping). ownerEntity is the Patient; targetEntity is the Affiliate. The eventType is message-from-patient-received.
This is the counterpart to Message from Clinical Team Received (message-from-admin-practitioner-received), which fires in the opposite direction (team → patient).
Field guarantees
| Field | Guarantee |
|---|---|
eventData.patientConversationId, message, type, channelType, sender | ✅ Always present (v1) |
eventData.senderRole | ✅ Always "patient" for this event |
message in v2 | ⛔ Not delivered — blocked as PHI |
patient_conversation_id, message_type, channel_type in v2 | ✅ Always present when set in eventData |
The message body is v1-only. v2 correctly stripsmessage(PHI) and does not deliversender/senderRole. v2 deliverspatient_conversation_id,message_type(fromeventData.type), andchannel_typeso you can correlate the thread and filter by channel — see Field Guarantees.
v1 payload (legacy)
{
"ownerEntity": { "id": "pat::ebbd2a07-xxxx-xxxx-xxxx-affaecf2b315", "firstName": "<PATIENT_FIRST_NAME>", "…": "patient document" },
"ownerModel": "Patient",
"targetEntity": "aff::96d23b23-xxxx-xxxx-xxxx-7759de5abcbb",
"targetEntityModel": "Affiliate",
"eventTitle": "Message from Patient Received.",
"eventDescription": "Webhook event to inform affiliate that a patient sent a message in the portal.",
"eventType": "message-from-patient-received",
"eventData": {
"patientConversationId": "pcv::bd6e11fd-xxxx-xxxx-xxxx-a35959104ec3",
"message": "When will my prescription arrive?",
"type": "MESG",
"channelType": "clinical",
"sender": "pcv::bd6e11fd-xxxx-xxxx-xxxx-a35959104ec3",
"senderRole": "patient"
}
}eventData field | Type | Always? | Notes |
|---|---|---|---|
patientConversationId | string | ✅ | Conversation id |
message | string | ✅ | Message body (PHI) |
type | string | ✅ | e.g. MESG (normal text) |
channelType | string | ✅ | clinical, support, billing, or shipping |
sender | string | ✅ | Patient conversation id (patient SendBird user id) |
senderRole | string | ✅ | Always "patient" |
v2 payload
Sanitized envelope. message is blocked as PHI; sender / senderRole are not delivered. patientConversationId aliases to patient_conversation_id, type to message_type, and channelType to channel_type.
{
"event_type": "message-from-patient-received",
"event_id": "event::xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"api_version": "2026-08-09",
"timestamp": "2026-05-30T14:00:00.000Z",
"affiliate_id": "aff::96d23b23-xxxx-xxxx-xxxx-7759de5abcbb",
"patient_id": "pat::ebbd2a07-xxxx-xxxx-xxxx-affaecf2b315",
"patient_external_id": "ext-patient-123",
"patient_marketing_consent": false,
"is_returning_patient": false,
"patient_conversation_id": "pcv::bd6e11fd-xxxx-xxxx-xxxx-a35959104ec3",
"message_type": "MESG",
"channel_type": "clinical"
}| Field | Delivered in v2 | Notes |
|---|---|---|
| Envelope + patient identity | ✅ | |
patient_conversation_id | ✅ | Correlate the thread |
message_type | ✅ | From eventData.type — e.g. MESG |
channel_type | ✅ | From eventData.channelType — filter by clinical / support / billing / shipping |
message, sender, senderRole | ⛔ | message blocked as PHI; sender identity not on the allowlist |
