Note Effects

The Canvas SDK provides effects to facilitate creating, updating, and managing visit notes, appointments, and schedule events. Below you’ll find detailed documentation for each effect type and their operations.

Note Effect #

The Note effect facilitates the creation and updating of visit notes for patients.

Build a Note with the attributes the operation needs, then return one of its methods from your handler. Each section below covers one method and lists its attributes: create(), update(), push_charges(), lock(), sign(), unlock(), check_in(), no_show(), delete(), undelete(), discharge(), and upsert_metadata(). Faxing a note uses a separate FaxNoteEffect, covered under Fax Note.

Create Note #

create() → Effect

Creates a new note. Can be passed an optional UUID as instance_id from the uuid.uuid4 library, or will be assigned one if not present. Passing a user-set UUID as the instance_id allows for assigning commands to the note in the same plugin action.

Attributes #

AttributeTypeDescriptionRequired
instance_idUUID or strIdentifier for the noteNo
note_type_idUUID or strIdentifier for the note typeYes
datetime_of_servicedatetime.datetimeWhen the service was providedYes
patient_idstrIdentifier for the patientYes
practice_location_idUUID or strIdentifier for the practice locationYes
provider_idstrIdentifier for the providerYes
titlestr or NoneOptional title for the noteNo
supervising_provider_idstr or NoneStaff identifier for the supervising providerNo

Implementation Details #

  • Validates that the note type exists and has an appropriate category
  • Ensures the patient exists in the system
  • Verifies that the practice location and provider are valid
  • If supervising_provider_id is provided, validates that the Staff record exists

Example Usage #

import datetime

from canvas_sdk.effects.note.note import Note
from canvas_sdk.handlers.base import BaseHandler


class MyHandler(BaseHandler):
    def compute(self):
        note_effect = Note(
            note_type_id="note-type-uuid",
            datetime_of_service=datetime.datetime.now(),
            patient_id="patient-uuid",
            practice_location_id="practice-location-uuid",
            provider_id="provider-uuid"
        )

        return [note_effect.create()]

To create a note and add commands to it in the same compute(), give the note an instance_id you generate, use that same value as each command’s note_uuid, and return the note’s create() effect before the command effects. Canvas applies a handler’s effects in the order they are returned, so the note exists by the time the commands are originated:

import datetime
import uuid

from canvas_sdk.commands import PlanCommand
from canvas_sdk.effects.note.note import Note
from canvas_sdk.handlers.base import BaseHandler


class MyHandler(BaseHandler):
    def compute(self):
        note_id = str(uuid.uuid4())

        note_effect = Note(
            instance_id=note_id,
            note_type_id="note-type-uuid",
            datetime_of_service=datetime.datetime.now(),
            patient_id="patient-uuid",
            practice_location_id="practice-location-uuid",
            provider_id="provider-uuid",
        )
        plan = PlanCommand(note_uuid=note_id, narrative="Follow up in two weeks")

        return [note_effect.create(), plan.originate()]

Update Note #

update() → Effect

Updates an existing note. Only certain fields can be modified after creation.

Attributes #

AttributeTypeDescriptionRequiredUpdatable
instance_idUUID or strIdentifier of the note to updateYesNo
titlestr or NoneUpdated title for the noteNoYes
datetime_of_servicedatetime.datetimeUpdated service date/timeNoYes
practice_location_idUUID or strUpdated practice locationNoYes
provider_idstrUpdated providerNoYes
supervising_provider_idstr or NoneStaff identifier for the supervising providerNoYes

Note: patient_id and note_type_id cannot be updated after creation.

Example Usage #

import datetime

from canvas_sdk.effects.note.note import Note
from canvas_sdk.handlers.base import BaseHandler


class MyHandler(BaseHandler):
    def compute(self):
        note_effect = Note(instance_id="existing-note-uuid")
        note_effect.title = "Updated Consultation Notes"
        note_effect.datetime_of_service = datetime.datetime.now()

        return [note_effect.update()]

Fax Note #

FaxNoteEffect.apply() → Effect

Sends an existing note via fax to a specified recipient. This effect allows you to transmit patient notes to external healthcare providers or facilities.

Attributes #

AttributeTypeDescriptionRequired
note_idUUID or strIdentifier of the note to faxYes
recipient_namestrName of the fax recipientYes
recipient_fax_numberstrFax number of the recipient. Should include the country codeYes
include_coversheetboolWhether to include a coversheet with the faxNo
subjectstr or NoneSubject line for the coversheet (required if coversheet used)No
commentstr or NoneAdditional comments for coversheet (required if coversheet used)No
location_idUUID or str or NonePractice location ID (required if coversheet used)No

Implementation Details #

  • Validates that the note exists in the system
  • If include_coversheet is True, the following fields become required:
    • subject: The subject line for the coversheet
    • comment: Additional comments to include on the coversheet
    • location_id: The practice location identifier (must exist in the system)
  • Validates that the practice location exists if provided
  • The fax is recorded as a NoteActionEvent on the note, so a plugin reads whether it was delivered through note.action_events. See Faxes sent by a plugin

Example Usage #

from canvas_sdk.effects.fax.note import FaxNoteEffect
from canvas_sdk.handlers.base import BaseHandler


class MyHandler(BaseHandler):
    def compute(self):
        # Basic fax without coversheet
        fax_effect = FaxNoteEffect(
            note_id="existing-note-uuid",
            recipient_name="Dr. Jane Smith",
            recipient_fax_number="15551234567"
        )

        return [fax_effect.apply()]

Example with Coversheet #

from canvas_sdk.effects.fax.note import FaxNoteEffect
from canvas_sdk.handlers.base import BaseHandler


class MyHandler(BaseHandler):
    def compute(self):
        # Fax with coversheet
        fax_effect = FaxNoteEffect(
            note_id="existing-note-uuid",
            recipient_name="Dr. Jane Smith",
            recipient_fax_number="15551234567",
            include_coversheet=True,
            subject="Patient Referral - Follow-up Care",
            comment="Please review attached consultation notes for continuing care.",
            location_id="practice-location-uuid"
        )

        return [fax_effect.apply()]

Note state transitions #

The state change effects below (push charges, lock, sign, unlock, check in, no show, delete, undelete, and discharge) each move a note to a new state, and each is accepted only from certain current states. Which transitions a note allows depends on its note type’s category, and on whether the type is billable or requires a signature. An effect applied from any other state raises ValueError: Invalid state transition.

EffectMoves the note toAllowed from
push_charges()PSHNEW, CVD, PSH, ULK, UND. Billable encounter note types only, and only when the Push charges button is enabled.
lock()LKDNEW, CVD, ULK, UND, and also PSH for encounter notes. Appointment notes lock only from NSW.
sign()SGNLKD, or SGN to sign again. Note types with is_sig_required only.
unlock()ULKLKD, and also SGN for note types with is_sig_required. On appointment notes, unlocking moves LKD back to NSW.
check_in()CVDBKD, RVT, NSW. Appointment notes only.
no_show()NSWBKD, RVT. Appointment notes only.
delete()DLTNEW, CVD, ULK, UND, and also PSH for encounter notes. Appointment notes delete only from SCH.
undelete()UNDDLT. Not available for appointment notes.
discharge()DSCNEW, CVD, ULK, UND. Inpatient notes only.

Notes in the remaining categories, such as message, letter, data, and search notes, accept none of these effects.

Push Charges #

push_charges() → Effect

Pushes the charges from the Note to its associated Claim in the Revenue module. Has the exact same effect as clicking on the Push charges button in the Note footer.

Attributes #

AttributeTypeDescriptionRequired
instance_idUUID or strIdentifier of the note to updateYes

Note: instance_id must be a valid, existing Note, and its NoteTypeVersion must have is_billable = True.

Example Usage #

import datetime

from canvas_sdk.effects.note.note import Note
from canvas_sdk.handlers.base import BaseHandler


class MyHandler(BaseHandler):
    def compute(self):
        note_effect = Note(instance_id="existing-note-uuid")
        return [note_effect.push_charges()]

To change the charge amount on a claim that already exists, use the UpdateClaimLineItem effect. Alternatively, add BillingLineItems to the patient’s note and then push charges so the claim is updated appropriately. The FHIR Claim API only supports changing the queue or adding a comment, so charge amounts cannot be edited there.

To move a claim into a specific revenue queue from a plugin — for example, to route contract-based claims that do not go through a clearinghouse into a queue your team works manually — use ClaimEffect.move_to_queue().

Lock #

lock() → Effect

Locks an existing note, preventing further modifications. Has the exact same effect as clicking on the Lock button in the Note footer.

Attributes #

AttributeTypeDescriptionRequired
instance_idUUID or strIdentifier of the note to lockYes

Note: instance_id must be a valid, existing Note that is not already locked.

Example Usage #

from canvas_sdk.effects.note.note import Note
from canvas_sdk.handlers.base import BaseHandler


class MyHandler(BaseHandler):
    def compute(self):
        note_effect = Note(instance_id="existing-note-uuid")
        return [note_effect.lock()]

Validating before a note is locked or signed #

To conditionally allow or block a note from being locked or signed — for example, requiring that a specific command or CPT code is present, that the signer is on the patient’s care team, or that the signer holds a matching state license — use the NOTE_STATE_CHANGE_EVENT_PRE_CREATE validation-error effect. When the validation fails, the effect prevents the state change and surfaces an error to the user. See the pre-lock-validation example plugin.

For example, to block a lock until the note has a billing line item:

from canvas_sdk.effects import Effect
from canvas_sdk.effects.validation import EventValidationError
from canvas_sdk.events import EventType
from canvas_sdk.handlers import BaseHandler
from canvas_sdk.v1.data.billing import BillingLineItem, BillingLineItemStatus


class RequireCptBeforeLock(BaseHandler):
    RESPONDS_TO = EventType.Name(EventType.NOTE_STATE_CHANGE_EVENT_PRE_CREATE)

    def compute(self) -> list[Effect]:
        if self.event.context.get("state") != "LKD":
            return []

        has_line_item = BillingLineItem.objects.filter(
            note__id=self.event.context["note_id"],
            status=BillingLineItemStatus.ACTIVE,
        ).exists()
        if has_line_item:
            return []

        error = EventValidationError()
        error.add_error("Add a CPT code before locking this note.")
        return [error.apply()]

Sign #

sign() → Effect

Signs an existing note, marking it as reviewed and approved by the provider. Has the exact same effect as clicking on the Sign button in the Note footer.

Attributes #

AttributeTypeDescriptionRequired
instance_idUUID or strIdentifier of the note to signYes

Note: instance_id must be a valid, existing Note that is not already signed.

Example Usage #

from canvas_sdk.effects.note.note import Note
from canvas_sdk.handlers.base import BaseHandler


class MyHandler(BaseHandler):
    def compute(self):
        note_effect = Note(instance_id="existing-note-uuid")
        return [note_effect.sign()]

To lock and sign a note in a single plugin action, return the lock() effect before the sign() effect:

# inside compute()
note = Note(instance_id="existing-note-uuid")
return [note.lock(), note.sign()]

Unlock #

unlock() → Effect

Unlocks a previously locked/signed note, allowing modifications again. Has the exact same effect as clicking on the Unlock/Amend button in the Note footer.

Attributes #

AttributeTypeDescriptionRequired
instance_idUUID or strIdentifier of the note to unlockYes

Note: instance_id must be a valid, existing Note that is currently locked.

Example Usage #

from canvas_sdk.effects.note.note import Note
from canvas_sdk.handlers.base import BaseHandler


class MyHandler(BaseHandler):
    def compute(self):
        note_effect = Note(instance_id="existing-note-uuid")
        return [note_effect.unlock()]

Check In #

check_in() → Effect

Marks a patient as checked in for their appointment. Has the exact same effect as clicking on the Check In button in the Appointment note.

Attributes #

AttributeTypeDescriptionRequired
instance_idUUID or strIdentifier of the note for check-inYes

Note: instance_id must be a valid, existing Note associated with an appointment.

Example Usage #

from canvas_sdk.effects.note.note import Note
from canvas_sdk.handlers.base import BaseHandler


class MyHandler(BaseHandler):
    def compute(self):
        note_effect = Note(instance_id="existing-note-uuid")
        return [note_effect.check_in()]

No Show #

no_show() → Effect

Marks an appointment as a no-show when the patient does not arrive. Has the exact same effect as marking an appointment as No Show in the Appointment note.

Attributes #

AttributeTypeDescriptionRequired
instance_idUUID or strIdentifier of the note to mark no-showYes

Note: instance_id must be a valid, existing Note associated with an appointment.

Example Usage #

from canvas_sdk.effects.note.note import Note
from canvas_sdk.handlers.base import BaseHandler


class MyHandler(BaseHandler):
    def compute(self):
        note_effect = Note(instance_id="existing-note-uuid")
        return [note_effect.no_show()]

Delete #

delete() → Effect

Deletes an existing note. Has the exact same effect as clicking on the Delete button in the Note footer.

Attributes #

AttributeTypeDescriptionRequired
instance_idUUID or strIdentifier of the note to deleteYes

Note: instance_id must be a valid, existing Note whose current state allows deletion (e.g. NEW, CONVERTED, UNLOCKED, PUSHED, or UNDELETED).

Example Usage #

from canvas_sdk.effects.note.note import Note
from canvas_sdk.handlers.base import BaseHandler


class MyHandler(BaseHandler):
    def compute(self):
        note_effect = Note(instance_id="existing-note-uuid")
        return [note_effect.delete()]

Undelete #

undelete() → Effect

Restores a previously deleted note. Has the exact same effect as clicking on the Restore button on a deleted note.

Attributes #

AttributeTypeDescriptionRequired
instance_idUUID or strIdentifier of the note to restoreYes

Note: instance_id must be a valid, existing Note that is currently in the DELETED state.

Example Usage #

from canvas_sdk.effects.note.note import Note
from canvas_sdk.handlers.base import BaseHandler


class MyHandler(BaseHandler):
    def compute(self):
        note_effect = Note(instance_id="existing-note-uuid")
        return [note_effect.undelete()]

Discharge #

discharge() → Effect

Locks and discharges an inpatient note. Has the exact same effect as clicking on the Lock and discharge button in the Inpatient note footer.

Attributes #

AttributeTypeDescriptionRequired
instance_idUUID or strIdentifier of the inpatient note to dischargeYes

Note: instance_id must be a valid, existing Note whose NoteTypeVersion.category is INPATIENT, and whose current state allows discharge (NEW, CONVERTED, UNLOCKED, or UNDELETED).

Example Usage #

from canvas_sdk.effects.note.note import Note
from canvas_sdk.handlers.base import BaseHandler


class MyHandler(BaseHandler):
    def compute(self):
        note_effect = Note(instance_id="existing-inpatient-note-uuid")
        return [note_effect.discharge()]

Upsert Metadata #

upsert_metadata(key: str, value: str) → Effect

Creates or updates a metadata entry for the specified note. For detailed documentation on note metadata management, see NoteMetadata Effect.

Parameters #

ParameterTypeDescriptionRequired
instance_idUUID or strIdentifier of the note (set on the Note effect)Yes
keystrUnique identifier for the metadata entry within the note contextYes
valuestrThe metadata value to storeYes

Example Usage #

from canvas_sdk.effects.note.note import Note
from canvas_sdk.handlers.base import BaseHandler


class MyHandler(BaseHandler):
    def compute(self):
        note = Note(instance_id="existing-note-uuid")
        return [note.upsert_metadata(key="my_plugin:custom_key", value="custom_value")]

ScheduleEvent Effect #

The ScheduleEvent effect enables creating, updating, and deleting schedule events for providers, with optional patient association.

Build a ScheduleEvent with the attributes the operation needs, then return one of its methods from your handler: create(), covered here, or update(), reschedule(), or delete().

create() → Effect creates a schedule event with the attributes below.

Attributes #

AttributeTypeDescriptionRequired
note_type_idUUID or strIdentifier for the note type (must be of category SCHEDULE_EVENT)Yes
patient_idstr or NoneIdentifier for the patient (if applicable)Conditional
descriptionstr or NoneCustom description for the eventConditional
start_timedatetime.datetimeStart time of the eventYes
duration_minutesintDuration of the event in minutesYes
practice_location_idUUID or strIdentifier for the practice locationYes
provider_idstrIdentifier for the providerYes
statusAppointmentProgressStatus or NoneStatus of the eventNo
external_identifierslist[AppointmentIdentifier] or NoneExternal system identifiersNo

Implementation Details #

  • Validates that the note type exists and is of category SCHEDULE_EVENT
  • Ensures patient is provided if the note type requires it
  • Verifies that custom descriptions are only used for note types that allow them
  • Validates that the practice location and provider exist

Example Usage #

import datetime

from canvas_sdk.effects.note.appointment import ScheduleEvent
from canvas_sdk.handlers.base import BaseHandler


class MyHandler(BaseHandler):
    def compute(self):
        schedule_event_effect = ScheduleEvent(
            note_type_id="schedule-event-note-type-uuid",
            patient_id="patient-uuid",  # Optional depending on note type
            description="Team meeting",  # Optional depending on note type
            start_time=datetime.datetime.now(),
            duration_minutes=30,
            practice_location_id="practice-location-uuid",
            provider_id="provider-uuid"
        )

        return [schedule_event_effect.create()]

Update Schedule Event #

update() → Effect

Updates an existing schedule event in place.

Attributes #

AttributeTypeDescriptionRequired
instance_idUUID or strIdentifier of the event to updateYes
start_timedatetime.datetimeNew start timeNo
duration_minutesintNew duration in minutesNo
descriptionstr or NoneUpdated descriptionNo
practice_location_idUUID or strNew practice locationNo
provider_idstrNew providerNo
statusAppointmentProgressStatus or NoneUpdated statusNo

Example Usage #

import datetime

from canvas_sdk.effects.note import AppointmentIdentifier
from canvas_sdk.effects.note.appointment import ScheduleEvent
from canvas_sdk.effects.note.base import AppointmentIdentifier
from canvas_sdk.handlers.base import BaseHandler


class MyHandler(BaseHandler):
    def compute(self):
        schedule_event_effect = ScheduleEvent(instance_id="existing-event-uuid")
        schedule_event_effect.start_time = datetime.datetime.now() + datetime.timedelta(days=1)
        schedule_event_effect.duration_minutes = 60
        schedule_event_effect.description = "Rescheduled team meeting"
        schedule_event_effect.external_identifiers = [
            AppointmentIdentifier(system="test_system", value="123TEST")
        ]

        return [schedule_event_effect.update()]

Reschedule Schedule Event #

reschedule() → Effect

Reschedules an existing schedule event by creating a new event and cancelling the original. This maintains the event history and ensures proper tracking of rescheduled events.

Attributes #

AttributeTypeDescriptionRequired
instance_idUUID or strIdentifier of the event to rescheduleYes
start_timedatetime.datetimeNew start timeNo
duration_minutesintNew duration in minutesNo
descriptionstr or NoneUpdated descriptionNo
practice_location_idUUID or strNew practice locationNo
provider_idstrNew providerNo
statusAppointmentProgressStatus or NoneUpdated statusNo
external_identifierslist[AppointmentIdentifier] or NoneUpdated external identifiersNo

Note: At least one field (besides instance_id) must be modified.

Example Usage #

import datetime

from canvas_sdk.effects.note.appointment import ScheduleEvent
from canvas_sdk.handlers.base import BaseHandler


class MyHandler(BaseHandler):
    def compute(self):
        schedule_event_effect = ScheduleEvent(instance_id="existing-event-uuid")
        schedule_event_effect.start_time = datetime.datetime.now() + datetime.timedelta(hours=3)
        schedule_event_effect.duration_minutes = 45

        return [schedule_event_effect.reschedule()]

Delete Schedule Event #

delete() → Effect

Marks a schedule event as cancelled.

Example Usage #

import datetime

from canvas_sdk.effects.note.appointment import ScheduleEvent
from canvas_sdk.handlers.base import BaseHandler


class MyHandler(BaseHandler):
    def compute(self):
        schedule_event_effect = ScheduleEvent(instance_id="existing-event-uuid")

        return [schedule_event_effect.delete()]

Appointment Effect #

The Appointment effect facilitates creating, updating, and cancelling patient appointments with providers.

Build an Appointment with the attributes the operation needs, then return one of its methods from your handler: create(), covered here, or update(), reschedule(), cancel(), or revert().

create() → Effect creates an appointment with the attributes below.

Attributes #

AttributeTypeDescriptionRequired
appointment_note_type_idUUID or strIdentifier for the appointment note type (must be of category ENCOUNTER and scheduleable)Yes
patient_idstrIdentifier for the patientYes
meeting_linkstr or NoneLink for virtual appointmentsNo
start_timedatetime.datetimeStart time of the appointmentYes
duration_minutesintDuration of the appointment in minutesYes
practice_location_idUUID or strIdentifier for the practice locationYes
provider_idstrIdentifier for the providerYes
statusAppointmentProgressStatus or NoneStatus of the appointmentNo
external_identifierslist[AppointmentIdentifier] or NoneExternal system identifiersNo

Implementation Details #

  • Validates that the appointment note type exists, is of category ENCOUNTER, and is scheduleable
  • Ensures the patient exists in the system
  • Verifies that the practice location and provider exist

Example Usage #

import datetime
from canvas_sdk.effects.note.appointment import Appointment
from canvas_sdk.handlers.base import BaseHandler


class MyHandler(BaseHandler):
    def compute(self):
        appointment_effect = Appointment(
            appointment_note_type_id="appointment-note-type-uuid",
            patient_id="patient-uuid",
            meeting_link="https://zoom.us/example-link",  # Optional
            start_time=datetime.datetime.now(),
            duration_minutes=60,
            practice_location_id="practice-location-uuid",
            provider_id="provider-uuid"
        )

        return appointment_effect.create()

Update Appointment #

update() → Effect

Updates an existing appointment in place.

Attributes #

AttributeTypeDescriptionRequired
instance_idUUID or strIdentifier of appointment to updateYes
start_timedatetime.datetimeNew start timeNo
duration_minutesintNew duration in minutesNo
meeting_linkstr or NoneUpdated meeting linkNo
practice_location_idUUID or strNew practice locationNo
provider_idstrNew providerNo
statusAppointmentProgressStatus or NoneUpdated statusNo
external_identifierslist[AppointmentIdentifier] or NoneUpdated external identifiersNo

Note: patient_id cannot be updated after creation.

Example Usage #

import datetime

from canvas_sdk.effects.note import AppointmentIdentifier
from canvas_sdk.effects.note.appointment import Appointment
from canvas_sdk.handlers.base import BaseHandler


class MyHandler(BaseHandler):
    def compute(self):
        appointment_effect = Appointment(instance_id="existing-appointment-uuid")
        appointment_effect.start_time = datetime.datetime.now() + datetime.timedelta(hours=2)
        appointment_effect.duration_minutes = 45
        appointment_effect.meeting_link = "https://new-meeting-link.com"
        appointment_effect.external_identifiers = [
            AppointmentIdentifier(system="my_external_system", value="appt-12345")
        ]

        return appointment_effect.update()

Reschedule Appointment #

reschedule() → Effect

Reschedules an existing appointment by creating a new appointment and cancelling the original. This maintains the appointment history and ensures proper tracking of rescheduled appointments.

Attributes #

AttributeTypeDescriptionRequired
instance_idUUID or strIdentifier of appointment to rescheduleYes
start_timedatetime.datetimeNew start timeNo
duration_minutesintNew duration in minutesNo
meeting_linkstr or NoneUpdated meeting linkNo
practice_location_idUUID or strNew practice locationNo
provider_idstrNew providerNo
statusAppointmentProgressStatus or NoneUpdated statusNo
external_identifierslist[AppointmentIdentifier] or NoneUpdated external identifiersNo

Note: At least one field (besides instance_id) must be modified. patient_id cannot be updated after creation.

Example Usage #

import datetime

from canvas_sdk.effects.note.appointment import Appointment
from canvas_sdk.handlers.base import BaseHandler


class MyHandler(BaseHandler):
    def compute(self):
        appointment_effect = Appointment(instance_id="existing-appointment-uuid")
        appointment_effect.start_time = datetime.datetime.now() + datetime.timedelta(days=1)
        appointment_effect.duration_minutes = 60

        return appointment_effect.reschedule()

Cancel Appointment #

cancel() → Effect

Cancels an existing appointment and updates its status.

Attributes #

AttributeTypeDescriptionRequired
instance_idUUID or strIdentifier of the appointment to cancelYes

Note: instance_id must be a valid, existing Appointment whose current state allows cancellation. An appointment can only be cancelled when it is in the BOOKED or REVERTED state.

Example Usage #

from canvas_sdk.effects.note.appointment import Appointment
from canvas_sdk.handlers.base import BaseHandler


class MyHandler(BaseHandler):
    def compute(self):
        appointment_effect = Appointment(instance_id="existing-appointment-uuid")

        return appointment_effect.cancel()

Revert Appointment #

revert() → Effect

Reverts a booked or checked-in appointment back to a state where it can be checked in, cancelled, rescheduled, or marked as no-show.

Attributes #

AttributeTypeDescriptionRequired
instance_idUUID or strIdentifier of the appointment to revertYes

Note: instance_id must be a valid, existing Appointment whose current state allows reversion. An appointment can only be reverted when it is in the CANCELLED, CONVERTED, or NOSHOW state.

Example Usage #

from canvas_sdk.effects.note.appointment import Appointment
from canvas_sdk.handlers.base import BaseHandler


class MyHandler(BaseHandler):
    def compute(self):
        appointment_effect = Appointment(instance_id="existing-appointment-uuid")

        return appointment_effect.revert()

Managing Appointment Labels #

Canvas supports adding up to 3 labels per appointment for categorization and workflow automation. Labels can be managed programmatically using the appointment label effects.

For detailed documentation on appointment label management, see Appointment Label Effects.

Quick Example #

from canvas_sdk.effects.note.appointment import AddAppointmentLabel, RemoveAppointmentLabel
from canvas_sdk.events import EventType
from canvas_sdk.handlers.base import BaseHandler

class MyHandler(BaseHandler):

    RESPONDS_TO = [EventType.Name(EventType.APPOINTMENT_LABEL_ADDED), EventType.Name(EventType.APPOINTMENT_LABEL_REMOVED)]

    def compute(self):
        # Add labels to an appointment
        add_effect = AddAppointmentLabel(
            appointment_id="appointment-uuid",
            labels={"URGENT", "FOLLOW_UP"}
        )

        # Remove labels from an appointment
        remove_effect = RemoveAppointmentLabel(
            appointment_id="appointment-uuid",
            labels={"CANCELLED"}
        )

        return [add_effect.apply(), remove_effect.apply()]

Validation #

All effects perform comprehensive validation before execution:

  1. Entity Existence: Validates that referenced entities (patients, providers, practice locations, note types) exist in the system
  2. Type Compatibility: Ensures note types are appropriate for the intended operation:
    • Visit notes cannot use APPOINTMENT, SCHEDULE_EVENT, MESSAGE, or LETTER note types
    • Schedule events must use SCHEDULE_EVENT note types
    • Appointments must use ENCOUNTER note types that are scheduleable
  3. Field Requirement Enforcement: The system validates conditional field requirements based on note type configurations:
    • Patient Association Requirements: For note types with is_patient_required=True, the system enforces that a valid patient ID is provided. This is particularly important for schedule events that may or may not be associated with specific patients.
    • Custom Description Validation: When a note type has allow_custom_title=False, the system prevents custom descriptions from being added. This ensures adherence to standardized naming conventions for certain types of appointments and events.
    • Required Field Validation: All required fields are checked for proper values and formats before the effect is executed.
  4. Update Restrictions: Certain fields cannot be modified after creation:
    • Notes: patient_id and note_type_id are immutable
    • Appointments: patient_id is immutable
    • All Effects: At least one field must be modified for an update operation to succeed