Appointment $cancel
Alpha
The $cancel operation is currently in alpha.
The $cancel operation cancels an Appointment by atomically setting its status to cancelled and deleting all Slot resources it references in a single FHIR transaction.
Use Cases
- Patient-initiated cancellation: Cancel a scheduled appointment at the patient's request and free the provider's time
- Staff-initiated cancellation: Cancel an appointment from an admin or scheduling workflow
- Automated cancellation: Programmatically cancel appointments based on external triggers (e.g., provider unavailability, EHR integration)
Invoke the $cancel operation
[base]/R4/Appointment/:id/$cancel
- TypeScript
- cURL
import { MedplumClient } from '@medplum/core';
import type { Appointment } from '@medplum/fhirtypes';
const medplum = new MedplumClient();
const appointment = await medplum.post<Appointment>(
medplum.fhirUrl('Appointment', 'my-appointment-id', '$cancel')
);
curl -X POST 'https://api.medplum.com/fhir/R4/Appointment/my-appointment-id/$cancel' \
-H "Authorization: Bearer MY_ACCESS_TOKEN"
Parameters
This operation takes no input parameters. The appointment to cancel is identified by the id in the URL.
Constraints
- The Appointment must have
status: bookedorstatus: pending. All other statuses are rejected. - All
Slotresources referenced byAppointment.slotmust exist and be readable by the caller.
Output
Returns 200 OK with the updated Appointment resource directly:
- One
Appointmentwithstatus: cancelled
All Slot resources that were referenced by the Appointment are deleted and do not appear in the response.
Example Response
{
"resourceType": "Appointment",
"id": "my-appointment-id",
"status": "cancelled",
"start": "2026-03-10T09:00:00.000Z",
"end": "2026-03-10T10:00:00.000Z",
"participant": [
{ "actor": { "reference": "Practitioner/dr-smith" }, "status": "tentative" },
{ "actor": { "reference": "Patient/my-patient-id" }, "status": "accepted" }
]
}
Cancellation Logic
$cancel performs the following steps inside a serializable transaction:
- Reads the Appointment identified by the URL
id - Loads all
Slotresources listed inAppointment.slot - Validates that the Appointment's
statusisbookedorpending - Sets the Appointment's
statustocancelledand saves it - Deletes all referenced Slots
- Returns the updated Appointment
The transaction uses serializable isolation for safety when there are concurrent scheduling operations affecting the same appointment.
Error Responses
Appointment Not Found
{
"resourceType": "OperationOutcome",
"issue": [{ "severity": "error", "code": "not-found", "details": { "text": "Not found" } }]
}
Appointment Not in Cancelable State
{
"resourceType": "OperationOutcome",
"issue": [{ "severity": "error", "code": "invalid", "details": { "text": "Appointment cannot be canceled in 'arrived' status" } }]
}
Referenced Slot Not Found
{
"resourceType": "OperationOutcome",
"issue": [{ "severity": "error", "code": "invalid", "details": { "text": "Loading slots failed" } }]
}
Related
- Appointment
$book- Book an Appointment (the inverse operation) - Appointment
$find- Find available slots - Scheduling Overview - High-level scheduling concepts
AppointmentresourceSlotresource