> ## Documentation Index
> Fetch the complete documentation index at: https://docs.junction.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Cancelling an Order

> Cancel lab test orders based on their current status and collection method, with guidance on timing to avoid unnecessary costs.

Order cancellation depends on the current status of your order and its collection method. Orders follow a finite state machine (FSM) pattern with specific rules governing when cancellation is permitted.

<Warning>
  **Important timing considerations to avoid financial costs:**

  * **At-home phlebotomy**: Appointments cancelled more than 24 hours in advance will be fully refunded. Cancellations made less than 24 hours before the scheduled appointment are non-refundable.
  * **Testkits**: Cancel before shipment to avoid fees. Testkits typically ship within the same business day if orders are placed before 1pm EST.
  * **Walk-in tests**: Can generally be cancelled until sample collection begins.
  * **On-site collection**: Cancel before the collection event.
</Warning>

## When Orders Can Be Cancelled

### ✅ Generally Cancellable States

All collection methods allow cancellation during these early phases:

* `ordered` - Initial order placement
* `requisition_created` - After requisition form is generated
* `requisition_bypassed` - When requisition is bypassed
* `awaiting_registration` - For registrable testkits

### ❌ Never Cancellable (Terminal States)

Orders **cannot** be cancelled once they reach these states:

* **Already cancelled**: `cancelled`, `do_not_process`
* **Completed**: `completed`, `partial_results`
* **Failed**: `lost`, `sample_error`, `failure_to_deliver_to_customer`, `failure_to_deliver_to_lab`

## Collection method-specific rules

<Tabs>
  <Tab title="Walk-In Tests">
    **✅ Can cancel:**

    * `received.walk_in_test.ordered`
    * `received.walk_in_test.requisition_created`
    * `received.walk_in_test.requisition_bypassed`
    * `collecting_sample.walk_in_test.appointment_scheduled`
    * `collecting_sample.walk_in_test.appointment_cancelled`
    * `collecting_sample.walk_in_test.appointment_pending`

    **❌ Cannot cancel once collection begins:**

    * `cancelled.walk_in_test.cancelled` - Already cancelled
    * `completed.walk_in_test.completed` - Order completed
    * `sample_with_lab.walk_in_test.partial_results` - Has partial results
    * `collecting_sample.walk_in_test.redraw_available` - Order marked as final but has missing results
    * `failed.walk_in_test.sample_error` - Sample error occurred

    <Info>Cancelling a walk-in test order does **not** automatically cancel PSC appointments to prevent a poor patient experience, as it could lead to a patient arriving and their appointment being cancelled. Use the [PSC appointment cancellation endpoint](/api-reference/lab-testing/psc-scheduling/appointment-psc-cancelling) if you need to cancel the appointment separately. Orders can be reinstated by our support team if a patient shows up for an appointment related to a cancelled order.</Info>
  </Tab>

  <Tab title="At-Home Phlebotomy">
    **✅ Can cancel:**

    * `received.at_home_phlebotomy.ordered`
    * `received.at_home_phlebotomy.requisition_created`
    * `received.at_home_phlebotomy.requisition_bypassed`
    * `collecting_sample.at_home_phlebotomy.appointment_pending`
    * `collecting_sample.at_home_phlebotomy.appointment_scheduled`
    * `collecting_sample.at_home_phlebotomy.appointment_cancelled`
    * `collecting_sample.at_home_phlebotomy.draw_completed`

    **❌ Cannot cancel once collection begins:**

    * `cancelled.at_home_phlebotomy.cancelled` - Already cancelled
    * `completed.at_home_phlebotomy.completed` - Order completed
    * `sample_with_lab.at_home_phlebotomy.partial_results` - Has partial results
    * `failed.at_home_phlebotomy.sample_error` - Sample error occurred

    <Warning>You can cancel the order directly - the system will automatically cancel any scheduled at-home phlebotomy appointments. Appointments cancelled with less than 24 hours' notice are non-refundable.</Warning>
  </Tab>

  <Tab title="Testkits">
    **✅ Can cancel:**

    * `received.testkit.ordered`
    * `received.testkit.awaiting_registration`
    * `received.testkit.requisition_created`
    * `received.testkit.requisition_bypassed`
    * `received.testkit.testkit_registered`

    **❌ Cannot cancel once shipped:**

    * `collecting_sample.testkit.out_for_delivery`
    * `collecting_sample.testkit.transit_customer`
    * `collecting_sample.testkit.with_customer`
    * `collecting_sample.testkit.transit_lab`
    * `sample_with_lab.testkit.delivered_to_lab`

    <Warning>Testkits become non-cancellable once they enter the shipping phase to avoid logistics costs. Testkits typically ship within the same business day if orders are placed before 1pm EST.</Warning>
  </Tab>

  <Tab title="On-Site Collection">
    **✅ Can cancel:**

    * `received.on_site_collection.ordered`
    * `received.on_site_collection.requisition_created`
    * `received.on_site_collection.requisition_bypassed`
    * `collecting_sample.on_site_collection.draw_completed`

    **❌ Cannot cancel once collection begins:**

    * `cancelled.on_site_collection.cancelled` - Already cancelled
    * `completed.on_site_collection.completed` - Order completed
    * `sample_with_lab.on_site_collection.partial_results` - Has partial results
    * `failed.on_site_collection.sample_error` - Sample error occurred
  </Tab>
</Tabs>

## How to Cancel

### Cancel Appointment (Optional - For Reference Only)

<Info>
  **Note**: You can skip this step and go directly to [cancelling the order](#cancel-the-order). The system will automatically cancel at-home phlebotomy appointments when you cancel the order, but **will not** automatically cancel walk-in PSC appointments to avoid a poor patient experience where they arrive and their appointment is cancelled.
</Info>

If you need to cancel only the appointment (without cancelling the entire order), use the appropriate endpoint for your collection method:

* **At-home phlebotomy**: [Appointment Cancellation endpoint](/api-reference/lab-testing/at-home-phlebotomy/appointment-cancelling)
* **Walk-in tests (PSC)**: [PSC Appointment Cancellation endpoint](/api-reference/lab-testing/psc-scheduling/appointment-psc-cancelling)

#### At-Home Phlebotomy Appointment Cancellation

<CodeGroup>
  ```bash cURL theme={null}
  curl --request PATCH \
       --url '{{BASE_URL}}/v3/order/<order_id>/phlebotomy/appointment/cancel' \
       --header 'accept: application/json' \
       --header 'x-vital-api-key: {YOUR_KEY}' \
       --data '{"cancellation_reason_id": "7dfd7da5-ed6e-40bb-a7e4-c8003f0c10a9"}'
  ```

  ```python Python theme={null}
  from junction import Junction
  from junction.environment import JunctionEnvironment

  client = Junction(
      api_key="YOUR_API_KEY",
      environment=JunctionEnvironment.SANDBOX,
  )

  client.lab_tests.cancel_phlebotomy_appointment(
      "<order_id>",
      cancellation_reason_id="<cancellation_reason_id>",
  )
  ```

  ```typescript TypeScript theme={null}
  import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk";

  const client = new JunctionClient({
      apiKey: "YOUR_API_KEY",
      environment: JunctionEnvironment.Sandbox,
  });

  const data = await client.labTests.cancelPhlebotomyAppointment({
      orderId: "<order_id>",
      cancellationReasonId: "<cancellation_reason_id>",
  });
  ```

  ```java Java theme={null}
  import com.junction.api.Junction;
  import com.junction.api.core.Environment;
  import com.junction.api.resources.labtests.requests.ApiApiV1EndpointsVitalApiLabTestingOrdersHelpersAppointmentCancelRequest;

  Junction client = Junction.builder()
      .apiKey("YOUR_API_KEY")
      .environment(Environment.SANDBOX)
      .build();

  var data = client.labTests().cancelPhlebotomyAppointment(
      "<order_id>",
      ApiApiV1EndpointsVitalApiLabTestingOrdersHelpersAppointmentCancelRequest.builder()
          .cancellationReasonId("<cancellation_reason_id>")
          .build()
  );
  ```

  ```go Go theme={null}
  import (
      "context"

      junction "github.com/junction-api/junction-go"
      "github.com/junction-api/junction-go/client"
      "github.com/junction-api/junction-go/option"
  )

  c := client.NewClient(
      option.WithApiKey("YOUR_API_KEY"),
      option.WithBaseURL(junction.Environments.Sandbox),
  )

  response, err := c.LabTests.CancelPhlebotomyAppointment(context.TODO(), &junction.ApiApiV1EndpointsVitalApiLabTestingOrdersHelpersAppointmentCancelRequest{
      OrderId:              "<order_id>",
      CancellationReasonId: "<cancellation_reason_id>",
  })
  if err != nil {
      return err
  }
  fmt.Printf("Received data %s\n", response)
  ```
</CodeGroup>

#### Walk-In Test (PSC) Appointment Cancellation

For walk-in tests scheduled at Patient Service Centers, use the PSC appointment cancellation endpoint:

<CodeGroup>
  ```bash cURL theme={null}
  curl --request DELETE \
       --url '{{BASE_URL}}/v3/order/<order_id>/appointment/psc/cancel' \
       --header 'accept: application/json' \
       --header 'x-vital-api-key: {YOUR_KEY}'
  ```

  ```python Python theme={null}
  from junction import Junction
  from junction.environment import JunctionEnvironment

  client = Junction(
      api_key="YOUR_API_KEY",
      environment=JunctionEnvironment.SANDBOX,
  )

  client.lab_tests.cancel_psc_appointment(
      "<order_id>",
      cancellation_reason_id="<cancellation_reason_id>",
  )
  ```

  ```typescript TypeScript theme={null}
  import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk";

  const client = new JunctionClient({
      apiKey: "YOUR_API_KEY",
      environment: JunctionEnvironment.Sandbox,
  });

  const data = await client.labTests.cancelPscAppointment({
      orderId: "<order_id>",
      cancellationReasonId: "<cancellation_reason_id>",
  });
  ```

  ```java Java theme={null}
  import com.junction.api.Junction;
  import com.junction.api.core.Environment;
  import com.junction.api.resources.labtests.requests.VitalCoreClientsLabTestGetlabsSchemaAppointmentCancelRequest;

  Junction client = Junction.builder()
      .apiKey("YOUR_API_KEY")
      .environment(Environment.SANDBOX)
      .build();

  var data = client.labTests().cancelPscAppointment(
      "<order_id>",
      VitalCoreClientsLabTestGetlabsSchemaAppointmentCancelRequest.builder()
          .cancellationReasonId("<cancellation_reason_id>")
          .build()
  );
  ```

  ```go Go theme={null}
  import (
      "context"

      junction "github.com/junction-api/junction-go"
      "github.com/junction-api/junction-go/client"
      "github.com/junction-api/junction-go/option"
  )

  c := client.NewClient(
      option.WithApiKey("YOUR_API_KEY"),
      option.WithBaseURL(junction.Environments.Sandbox),
  )

  response, err := c.LabTests.CancelPscAppointment(context.TODO(), &junction.VitalCoreClientsLabTestGetlabsSchemaAppointmentCancelRequest{
      OrderId:              "<order_id>",
      CancellationReasonId: "<cancellation_reason_id>",
  })
  if err != nil {
      return err
  }
  fmt.Printf("Received data %s\n", response)
  ```
</CodeGroup>

### Cancel the Order

Use the [order cancellation endpoint](/api-reference/lab-testing/cancel-order) to cancel any lab test order.

<Info>
  **Automatic Appointment Handling**:

  * **At-home phlebotomy**: Appointments are automatically cancelled when you cancel the order
  * **Walk-in PSC**: Appointments are **not** automatically cancelled to prevent poor patient experience if they show up. Orders can be reinstated if needed.
</Info>

<CodeGroup>
  ```bash cURL theme={null}
  curl --request DELETE \
       --url {{BASE_URL}}/v3/lab_test/<order_id>/cancel \
       --header 'Accept: application/json' \
       --header 'x-vital-api-key: <API_KEY>' \
       --header 'Content-Type: application/json'
  ```

  ```python Python theme={null}
  from junction import Junction
  from junction.environment import JunctionEnvironment

  client = Junction(
      api_key="YOUR_API_KEY",
      environment=JunctionEnvironment.SANDBOX,
  )

  data = client.lab_tests.cancel_order("<order_id>")
  ```

  ```typescript TypeScript theme={null}
  import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk";

  const client = new JunctionClient({
      apiKey: "YOUR_API_KEY",
      environment: JunctionEnvironment.Sandbox,
  });

  const data = await client.labTests.cancelOrder({ orderId: "<order_id>" });
  ```

  ```java Java theme={null}
  import com.junction.api.Junction;
  import com.junction.api.core.Environment;

  Junction client = Junction.builder()
      .apiKey("YOUR_API_KEY")
      .environment(Environment.SANDBOX)
      .build();

  var data = client.labTests().cancelOrder("<order_id>");
  ```

  ```go Go theme={null}
  import (
      "context"

      junction "github.com/junction-api/junction-go"
      "github.com/junction-api/junction-go/client"
      "github.com/junction-api/junction-go/option"
  )

  c := client.NewClient(
      option.WithApiKey("YOUR_API_KEY"),
      option.WithBaseURL(junction.Environments.Sandbox),
  )

  response, err := c.LabTests.CancelOrder(context.TODO(), &junction.CancelOrderLabTestsRequest{
      OrderId: "<order_id>",
  })
  if err != nil {
      return err
  }
  fmt.Printf("Received data %s\n", response)
  ```
</CodeGroup>

## Error Handling

When attempting to cancel an order that cannot be cancelled, you'll receive an error response:

```json Error Response theme={null}
{
  "error": "Bad Request",
  "message": "Transition from current_status to cancelled is not allowed",
  "status_code": 400
}
```

**Common reasons for cancellation failure:**

* Order is already in a terminal state (completed, failed, or cancelled)
* Testkit has already shipped
* Sample has been collected or is with the lab
* Results are already available (partial or complete)

## Checking Cancellation Eligibility

Before attempting cancellation, check the order's current status using the [get order endpoint](/api-reference/lab-testing/get-order):

```bash Check Order Status theme={null}
curl --request GET \
     --url {{BASE_URL}}/v3/order/<order_id> \
     --header 'x-vital-api-key: <API_KEY>'
```

Look for these indicators in the response:

* `status` field shows the current high-level status
* `events` array shows the detailed state progression
* Orders in early states (`ordered`, `requisition_created`) are typically cancellable
* Orders with `cancelled`, `completed`, or `failed` status cannot be cancelled

## Response Examples

### Successful Cancellation

```json Cancellation Success Response theme={null}
{
        "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "user_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "patient_details": {"dob": "2020-01-01", "gender": "male"},
        "patient_address": {
            "receiver_name": "John Doe",
            "first_line": "123 Main St.",
            "second_line": "Apt. 208",
            "city": "San Francisco",
            "state": "CA",
            "zip": "91189",
            "country": "United States",
            "phone_number": "+1123456789",
        },
        "details": {
            "type": "testkit",
            "data": {
                "id": "a655f0e4-6405-4a1d-80b7-66f06c2108a7",
                "shipment": {
                    "id": "d55210cc-3d9f-4115-8262-5013f700c7be",
                    "outbound_tracking_number": "<outbound_tracking_number>",
                    "outbound_tracking_url": "<outbound_tracking_url>",
                    "inbound_tracking_number": "<inbound_tracking_number>",
                    "inbound_tracking_url": "<inbound_tracking_url>",
                    "outbound_courier": "usps",
                    "inbound_courier": "usps",
                    "notes": "<notes>",
                    "created_at": "2020-01-01T00:00:00.000Z",
                    "updated_at": "2020-01-01T00:00:00.000Z",
                },
                "created_at": "2020-01-01T00:00:00Z",
                "updated_at": "2020-01-01T00:00:00Z",
            },
        },
        "diagnostic_lab_test": {
            "name": "Lipids Panel",
            "description": "Cholesterol test",
            "method": "testkit",
        },
        "sample_id": "123456789",
        "notes": "This is a note",
        "created_at": "2020-01-01T00:00:00Z",
        "updated_at": "2020-01-01T00:00:00Z",
        "status": "cancelled",
        "events": [
            {
                "id": 1,
                "created_at": "2022-01-01T00:00:00Z",
                "status": "received.testkit.ordered",
            },
            {
                "id": 2,
                "created_at": "2022-01-01T00:00:00Z",
                "status": "cancelled.testkit.cancelled",
            }
        ],
}
```

### Successful Appointment Cancellation

```json Appointment Cancellation Response theme={null}
{
    "id": "413d7205-f8a9-42ed-aa4a-edb99e481ca0",
    "user_id": "202b2c2f-fb4c-44dc-a4f8-621186fde227",
    "address": {
        "first_line": "West Lincoln Street",
        "second_line": "",
        "city": "Phoenix",
        "state": "AZ",
        "zip_code": "85004",
        "unit": "14"
    },
    "location": {
        "lng": -112.0772235,
        "lat": 33.4421912
    },
    "start_at": "2023-05-17T20:00:00+00:00",
    "end_at": "2023-05-17T22:00:00+00:00",
    "iana_timezone": "America/Phoenix",
    "type": "phlebotomy",
    "provider": "getlabs",
    "status": "cancelled",
    "provider_id": "e89eb489-7382-4966-bb14-7ab4763eba6c",
    "can_reschedule": true
}
```

## Related Resources

* [Order Lifecycle Overview](/lab/workflow/lab-test-lifecycle)
* [API Reference: Cancel Order](/api-reference/lab-testing/cancel-order)
* [API Reference: Cancel At-Home Appointment](/api-reference/lab-testing/at-home-phlebotomy/appointment-cancelling)
* [API Reference: Cancel PSC Appointment](/api-reference/lab-testing/psc-scheduling/appointment-psc-cancelling)
* [Webhooks for Order Events](/lab/testkits/webhooks)

***

*For questions about specific cancellation scenarios, please contact support at [support@junction.com](mailto:support@junction.com)*
