Skip to main content

AsyncJob $cancel

The $cancel operation allows you to cancel a running asynchronous job. This is useful when you need to stop a long-running operation that is no longer needed.

Use Cases

  • Resource Management: Cancel jobs that are no longer needed to free up server resources
  • Error Recovery: Stop a job that was started with incorrect parameters
  • User Control: Allow users to cancel long-running exports or operations they initiated

Invoke the $cancel operation

[base]/AsyncJob/[id]/$cancel

For example:

curl -X POST 'https://api.medplum.com/fhir/R4/AsyncJob/job-id/$cancel' \
-H "Content-Type: application/fhir+json" \
-H "Authorization: Bearer MY_ACCESS_TOKEN"

Parameters

This operation has no input parameters. The job ID is specified in the URL path.

Output

The operation returns an OperationOutcome indicating success or failure.

Successful Response

{
"resourceType": "OperationOutcome",
"issue": [
{
"severity": "information",
"code": "informational",
"details": {
"text": "All OK"
}
}
]
}

Behavior

The operation behavior depends on the current status of the AsyncJob:

Current StatusBehavior
acceptedJob is cancelled, status changes to cancelled
cancelledNo action taken (already cancelled)
OtherError returned - job cannot be cancelled

Status Transitions

accepted → cancelled (via $cancel)
note

Only jobs with accepted status can be cancelled. Jobs that are already completed, failed, or in other terminal states cannot be cancelled.

Error Responses

Job Already Completed

If the job has already completed or is in a non-cancellable state:

{
"resourceType": "OperationOutcome",
"issue": [
{
"severity": "error",
"code": "invalid",
"details": {
"text": "AsyncJob cannot be cancelled if status is not 'accepted', job had status 'completed'"
}
}
]
}

Job Not Found

If the AsyncJob doesn't exist or you don't have access:

{
"resourceType": "OperationOutcome",
"issue": [
{
"severity": "error",
"code": "not-found",
"details": {
"text": "Not found"
}
}
]
}

AsyncJob Lifecycle

AsyncJobs are created by various long-running operations:

  1. Bulk FHIR Export - $export operations
  2. Project Expunge - $expunge with everything=true
  3. Reindex Operations - $reindex operations
  4. Other Async Operations - Various operations that run asynchronously

Example: Cancel a Bulk Export

# Start a bulk export
curl -X GET 'https://api.medplum.com/fhir/R4/$export' \
-H "Authorization: Bearer MY_ACCESS_TOKEN" \
-H "Prefer: respond-async"

# Response includes Content-Location header
# Content-Location: https://api.medplum.com/fhir/R4/AsyncJob/abc123

# Cancel the export if needed
curl -X POST 'https://api.medplum.com/fhir/R4/AsyncJob/abc123/$cancel' \
-H "Authorization: Bearer MY_ACCESS_TOKEN"