Message Effect

The Message effect provides a unified way to create, edit, and transmit messages between users (patients or staff) within the Canvas platform. It supports standalone creation, immediate send after creating, edits, and dedicated send operations.

Build a Message with the attributes you want to set, then return one of its methods from your handler: create(), create_and_send(), edit(), or send().

Methods #

create() → Effect #

Creates a message without sending it.

  • content, sender_id, and recipient_id are required, and content cannot be empty.
  • message_id must not be set.

create_and_send() → Effect #

Creates the message and sends it in one operation.

  • content, sender_id, and recipient_id are required, and content cannot be empty.
  • message_id must not be set.
  • When the recipient is a patient, the patient needs an eligible contact point. See Sending to a patient.

edit() → Effect #

Changes an existing message.

  • message_id is required, and must be the id of an existing message.
  • Only the attributes you set on the effect are changed. Attributes you leave unset keep their current values.

send() → Effect #

Sends a message that was already created, if you separated creating it from sending it.

  • Set message_id to the message to send.
  • When the recipient is a patient, the patient needs an eligible contact point. See Sending to a patient.

Sending to a patient #

When create_and_send() or send() sends a message to a patient, Canvas notifies the patient the same way it does for a message sent from the chart: a text message or email to each of the patient’s phone numbers and email addresses that is eligible. A contact point is eligible when all three of these are true:

  • has_consent is True
  • last_verified is set
  • state is "active"

If the patient has no eligible contact point, Canvas cannot deliver the message. The message is saved but not sent, it appears as a draft in the patient’s chart, and the effect fails.

To avoid this, check the patient’s contact points before sending, and use create() instead when none is eligible:

has_eligible_contact = patient.telecom.filter(
    has_consent=True,
    last_verified__isnull=False,
    state="active",
).exists()

message = Message(content=content, sender_id=staff.id, recipient_id=patient.id)
effect = message.create_and_send() if has_eligible_contact else message.create()

Instances set up to deliver patient messages through a plugin, rather than through Canvas, do not send these notifications.

create() on its own never notifies the patient.

Attributes #

AttributeTypeDescriptionRequired
message_idstr or UUID or NoneUnique identifier of an existing message. Must be unset when creating a new message.For edit() and send()
contentstr or NoneThe text body of the message. Cannot be empty.For create() and create_and_send()
sender_idstr or UUIDID of the user (Patient or Staff) who is sending the message.Yes
recipient_idstr or UUIDID of the user (Patient or Staff) who will receive the message.Yes
readdatetime or NoneTimestamp indicating when the message was read by the recipient. Defaults to None (unread).No

Validation & Errors #

Before any effect is emitted, the model runs these checks:

  • Sender and Recipient Exist Verifies that both sender_id and recipient_id belong to either a Patient or a Staff record.
  • Create vs. Edit Constraints
    • Create and Create-and-Send must not include message_id.
    • Create and Create-and-Send must include non-empty content (content cannot be blank or whitespace-only).
    • Edit operations must include a valid message_id that already exists in the database.

Caveats #

  • Role Constraints: Sender and Recipient must always be one of Patient or Staff. Patient-to-Patient messaging is not allowed.
  • UI Refresh Required: Due to system constraints, editing a message requires a manual UI refresh for updated content to display.
  • No Attachments Supported: The Message effect does not yet support attachments.
  • Immediate Post for Patient-to-Staff: Messages created from a Patient to Staff cannot be drafted and will immediately appear in the timeline. This means that CREATE_AND_SEND and SEND effects will fail in these scenarios. You should only use the CREATE method for Patient-to-Staff messaging.

Example Usage #

from canvas_sdk.v1.data.message import Message as MessageModel
from canvas_sdk.v1.data.patient import Patient
from canvas_sdk.v1.data.staff import Staff

from canvas_sdk.effects.note.message import Message

staff = Staff.objects.first()
patient = Patient.objects.first()

Create (originate) only #

m1 = Message(
    content="Your lab results are available.",
    sender_id=staff.id,
    recipient_id=patient.id
)
effect_create = m1.create()

Create and send in one step #

m2 = Message(
    content="Your appointment is confirmed.",
    sender_id=staff.id,
    recipient_id=patient.id
)
effect_create_and_send = m2.create_and_send()

m = MessageModel.objects.get(message_id="msg-1234")

Edit an existing message #

m3 = Message(
    message_id=m.id,
    content="Updated: Your appointment has moved to 3pm."
)
effect_edit = m3.edit()

Send an existing message #

m4 = Message(message_id=m.id)
effect_send = m4.send()