PortalInvitation

The PortalInvitation model represents a patient portal invite or password reset link that Canvas created for a user. Canvas creates one each time it creates a portal link to send, including through Send Invite, even when the send then fails, and each time a plugin mints a link with patient_portal_http.get_login_url(). The user is usually a patient, or a representative’s login when a patient shares portal access. Use it to see whether a patient opened their link, set a password with it, or let it expire, and to find patients who need a new link.

The model records the link’s history, not the link: you can’t read its URL from it. To react to a link as its state changes, handle the portal invitation events.

Basic usage #

To get an invitation by identifier, use the get method on the PortalInvitation model manager:

from canvas_sdk.v1.data import PortalInvitation

invitation = PortalInvitation.objects.get(id="d2194110-5c9a-4842-8733-ef09ea5ead11")

A user’s invitations are available from the CanvasUser through the portal_invitations accessor:

from canvas_sdk.v1.data import Patient

patient = Patient.objects.get(id="b80b1cdc2e6a4aca90ccebc02e683f35")

invitations = patient.user.portal_invitations.order_by("-created")

Filtering #

Invitations can be filtered by any attribute that exists on the model.

By status #

Filter on status with a PortalInvitationStatus value. For example, to find links that expired before the patient ever opened them:

from canvas_sdk.v1.data import PortalInvitation, PortalInvitationStatus

expired_unopened = PortalInvitation.objects.filter(
    status=PortalInvitationStatus.EXPIRED, first_opened_at__isnull=True
)

Links a patient can still use #

is_redeemable is true while a link hasn’t been claimed and hasn’t expired. Check it before you send a patient another link:

from canvas_sdk.v1.data import Patient

patient = Patient.objects.get(id="b80b1cdc2e6a4aca90ccebc02e683f35")

has_live_link = patient.user.portal_invitations.filter(is_redeemable=True).exists()

Status #

Each invitation has one status, chosen in this order:

  1. claimed when the link was used to set a password.
  2. expired when the link has passed expires_at or can no longer be used. A link that expired after the patient opened it stays expired; check first_opened_at to tell the two apart.
  3. opened when the patient opened the link at least once.
  4. pending otherwise.

A link that Canvas couldn’t use when someone opened it records the time and reason in last_rejected_at and last_rejection_reason. Those fields don’t change status, first_opened_at, or is_redeemable.

Opening a link that was already used to set a password records the reason already_claimed, and status stays claimed. A link that lapsed without being claimed records expired.

Links created before Canvas recorded claims have no claimed_at. A link of that age that was used to set a password shows status expired, and reopening it records expired, not already_claimed. Before you send a new link in response to expired, check is_portal_registered on the CanvasUser to confirm the patient hasn’t already registered.

Attributes #

PortalInvitation #

Field NameTypeDescription
idUUIDThe target ID on portal invitation events
dbidInteger 
createdDateTimeWhen the link was created
modifiedDateTimeWhen the link was last opened, claimed, or refused. Passing expires_at doesn’t change it
userCanvasUserThe user the link signs in
expires_atDateTimeWhen the link stops working
first_opened_atDateTimeWhen the link was first opened successfully, or None if it never was
first_opened_user_agentStringThe browser user agent of that first open, or None
claimed_atDateTimeWhen the link was used to set a password, or None
last_rejected_atDateTimeWhen Canvas last couldn’t use the link after it was opened, or None
last_rejection_reasonPortalInvitationRejectionReasonWhy Canvas last couldn’t use the link, or None
statusPortalInvitationStatusSee Status
is_redeemableBooleanWhether the link can still be used: not claimed and not expired

Enumeration types #

PortalInvitationStatus #

ValueLabel
pendingPending
openedOpened
claimedClaimed
expiredExpired

PortalInvitationRejectionReason #

ValueLabelDescription
expiredExpiredThe link had passed expires_at or could no longer be used when it was opened
different_accountDifferent accountAnother account was signed in on the browser that opened it
already_claimedAlready claimedThe link was already used to set a password, so the patient is registered