Palamond Docs
Resource Modeling

Appointments

The scheduling spine, computed availability, and reschedule as cancel plus rebook.

On Palamond the Appointment is the scheduling spine: it is the source of truth for a scheduled moment. It exists before any Encounter, and the Encounter is created later, only when the visit actually begins (see Encounters and Tasks). You read appointments from the record plane; every change goes through a scheduling endpoint.

Visits are scheduled by the care team, or issued by the platform when care calls for one: starting an assessment creates its intake visit, and activating a care plan creates the plan's scheduled visits. Your app does not book; it reads the visits the patient has, moves them, and cancels them.

Shape

FieldPurpose
statusproposed (requested, no time yet), booked, fulfilled, or cancelled.
appointmentTypeVisit modality: sync (live) or async (store-and-forward).
start / endThe booked window. A booked appointment must carry both.
participantThe patient, plus the assigned practitioner and/or the owning care team.
supportingInformationRelated resources, such as the CarePlan this visit belongs to.
cancelationReasonWhy an appointment was cancelled.

Modality is coded on appointmentType using the shared modality system. Import the coordinates rather than hardcoding them.

Read modality codes from the shared module
import {
  ENCOUNTER_MODALITY_SYSTEM,
  ENCOUNTER_MODALITY_CODES,
} from '@palamond/sdk/codes';
// ENCOUNTER_MODALITY_CODES.sync === 'sync'
// ENCOUNTER_MODALITY_CODES.async === 'async'

Availability

Open time is computed by the platform, never pre-materialized: recurring working hours minus booked appointments minus blocked time, resolved per organization and timezone. You do not query for free slots yourself. Ask availability.list for open times across a care team or a single practitioner, and it returns open windows for a given visit length (or per-day counts for a calendar with view: 'days'). This is how a patient picks the new time for a reschedule; pass excludeAppointment so the visit being moved counts as free.

const availability = await palamond.availability.list({
  careTeam: `CareTeam/${careTeamId}`,
  durationMin: 20,
  excludeAppointment: `Appointment/${appointment.id}`,
});
// { view: 'slots', memberCount, hasAvailability, slots: [{ start, end, practitioner }] }

Because open time is derived, a slot you were shown can be taken by someone else before you act on it. Rescheduling re-validates the slot server-side and answers 409 conflict if it is no longer free, so you never double-book. Handle that by re-fetching availability.

An asynchronous visit (modality: 'async') has no calendar slot; its work reaches the patient as tasks. The full reschedule flow, including error handling, is in Reschedule or Cancel a Visit.

Reading a patient's appointments

Searches are scoped to the signed-in patient automatically. Filter out terminal statuses to show what is upcoming.

const upcoming = await palamond.searchResources('Appointment', {
  'status:not': 'cancelled',
  _sort: 'date',
});

To list the appointments for a care plan, search on the supporting-information link:

const planVisits = await palamond.searchResources('Appointment', {
  'supporting-info': `CarePlan/${carePlanId}`,
});

Cancel

Cancel with appointments.cancel. The platform cascades: any not-yet-picked-up work is cancelled with it, and a materialized Encounter (if the visit had already started) is cancelled too. You do not have to unwind those yourself.

await palamond.appointments.cancel(appointment.id, {
  reason: 'Feeling better',
});

Reschedule is cancel plus rebook

Palamond does not move an appointment in place. appointments.reschedule cancels the original and books a fresh appointment at the new time, then returns the replacement. This keeps the model clean: the platform regenerates the right tasks and encounter for the new slot, instead of trying to patch the old ones.

const replacement = await palamond.appointments.reschedule(appointment.id, {
  start: newSlot.start,
  end: newSlot.end,
  practitioner: newSlot.practitioner.reference,
});

The two appointments are linked so the history stays auditable:

  • the cancelled original carries a "rescheduled to" reference pointing at the replacement,
  • the replacement carries a "rescheduled from" reference pointing back.
Read the reschedule links
import {
  APPOINTMENT_RESCHEDULED_TO_EXTENSION_URL,
  APPOINTMENT_RESCHEDULED_FROM_EXTENSION_URL,
} from '@palamond/sdk/codes';

const replacementRef = original.extension?.find(
  (e) => e.url === APPOINTMENT_RESCHEDULED_TO_EXTENSION_URL,
)?.valueReference?.reference;

Treat a rescheduled appointment as immutable history: do not reopen a cancelled appointment. Follow the "rescheduled to" link to find the current visit instead.

Starting the visit

The visit Encounter does not exist when the visit is scheduled. When the visit begins, materialize it idempotently with POST /v1/appointments/{id}/encounter; see Encounters and Tasks.

On this page