diff --git a/packages/esm-patient-chart-app/src/actions-buttons/start-visit.component.tsx b/packages/esm-patient-chart-app/src/actions-buttons/start-visit.component.tsx
index 806b76116d..08f57f984c 100644
--- a/packages/esm-patient-chart-app/src/actions-buttons/start-visit.component.tsx
+++ b/packages/esm-patient-chart-app/src/actions-buttons/start-visit.component.tsx
@@ -14,7 +14,9 @@ const StartVisitOverflowMenuItem: React.FC<StartVisitOverflowMenuItemProps> = ({
   const { currentVisit } = useVisit(patient?.id);
   const isDeceased = Boolean(patient?.deceasedDateTime);
 
-  const handleLaunchModal = useCallback(() => launchPatientWorkspace('start-visit-workspace-form'), []);
+  const handleLaunchModal = useCallback(() => launchPatientWorkspace('start-visit-workspace-form', {
+    openedFrom: "patient-chart-start-visit",
+  }), []);
 
   return (
     !currentVisit &&
diff --git a/packages/esm-patient-chart-app/src/actions-buttons/start-visit.test.tsx b/packages/esm-patient-chart-app/src/actions-buttons/start-visit.test.tsx
index 932dbc6735..37d70d604c 100644
--- a/packages/esm-patient-chart-app/src/actions-buttons/start-visit.test.tsx
+++ b/packages/esm-patient-chart-app/src/actions-buttons/start-visit.test.tsx
@@ -38,7 +38,9 @@ describe('StartVisitOverflowMenuItem', () => {
 
     await user.click(startVisitButton);
     expect(launchPatientWorkspace).toHaveBeenCalledTimes(1);
-    expect(launchPatientWorkspace).toHaveBeenCalledWith('start-visit-workspace-form');
+    expect(launchPatientWorkspace).toHaveBeenCalledWith('start-visit-workspace-form', {
+      openedFrom: 'patient-chart-start-visit',
+    });
   });
 
   it('should not show start visit button for a deceased patient', () => {
diff --git a/packages/esm-patient-chart-app/src/config-schema.ts b/packages/esm-patient-chart-app/src/config-schema.ts
index ee3158d05e..e21dac645f 100644
--- a/packages/esm-patient-chart-app/src/config-schema.ts
+++ b/packages/esm-patient-chart-app/src/config-schema.ts
@@ -128,11 +128,6 @@ export const esmPatientChartSchema = {
     _default: '159947AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
     _type: Type.ConceptUuid,
   },
-  visitQueueNumberAttributeUuid: {
-    _type: Type.ConceptUuid,
-    _description: 'The UUID of the visit attribute that contains the visit queue number.',
-    _default: 'c61ce16f-272a-41e7-9924-4c555d0932c5',
-  },
   visitTypeResourceUrl: {
     _type: Type.String,
     _default: '/etl-latest/etl/patient/',
@@ -156,9 +151,8 @@ export interface ChartConfig {
   showAllEncountersTab: boolean;
   showExtraVisitAttributesSlot: boolean;
   showRecommendedVisitTypeTab: boolean;
-  showServiceQueueFields: boolean;
-  showUpcomingAppointments: boolean;
-  visitQueueNumberAttributeUuid: string;
+  showServiceQueueFields: boolean; // used by extension from esm-service-queues-app
+  showUpcomingAppointments: boolean; // used by extension from esm-appointments-app
   visitTypeResourceUrl: string;
   visitAttributeTypes: Array<{
     displayInThePatientBanner: boolean;
diff --git a/packages/esm-patient-chart-app/src/routes.json b/packages/esm-patient-chart-app/src/routes.json
index 99417cfb16..5973d07f33 100644
--- a/packages/esm-patient-chart-app/src/routes.json
+++ b/packages/esm-patient-chart-app/src/routes.json
@@ -122,6 +122,7 @@
     },
     {
       "name": "start-visit-workspace-form",
+      "slot": "start-visit-workspace-form-slot",
       "component": "startVisitForm",
       "meta": {
         "title": "Start a visit"
diff --git a/packages/esm-patient-chart-app/src/visit-header/visit-header.component.tsx b/packages/esm-patient-chart-app/src/visit-header/visit-header.component.tsx
index dcbe615505..f91a20d637 100644
--- a/packages/esm-patient-chart-app/src/visit-header/visit-header.component.tsx
+++ b/packages/esm-patient-chart-app/src/visit-header/visit-header.component.tsx
@@ -118,7 +118,7 @@ const PatientInfo: React.FC<PatientInfoProps> = ({ patient }) => {
 };
 
 function launchStartVisitForm() {
-  launchPatientWorkspace('start-visit-workspace-form');
+  launchPatientWorkspace('start-visit-workspace-form', {openedFrom: "patient-chart-start-visit"});
 }
 
 const VisitHeader: React.FC<{ patient: fhir.Patient }> = ({ patient }) => {
diff --git a/packages/esm-patient-chart-app/src/visit-header/visit-header.test.tsx b/packages/esm-patient-chart-app/src/visit-header/visit-header.test.tsx
index d715f721cd..3ba87bc084 100644
--- a/packages/esm-patient-chart-app/src/visit-header/visit-header.test.tsx
+++ b/packages/esm-patient-chart-app/src/visit-header/visit-header.test.tsx
@@ -84,7 +84,9 @@ describe('Visit header', () => {
     expect(startVisitButton).toBeInTheDocument();
 
     await user.click(startVisitButton);
-    expect(launchPatientWorkspace).toHaveBeenCalledWith('start-visit-workspace-form');
+    expect(launchPatientWorkspace).toHaveBeenCalledWith('start-visit-workspace-form', {
+      openedFrom: 'patient-chart-start-visit',
+    });
   });
 
   test('should display a truncated name when the patient name is very long', async () => {
diff --git a/packages/esm-patient-chart-app/src/visit/hooks/useMutateAppointments.tsx b/packages/esm-patient-chart-app/src/visit/hooks/useMutateAppointments.tsx
deleted file mode 100644
index 6d7f545a3e..0000000000
--- a/packages/esm-patient-chart-app/src/visit/hooks/useMutateAppointments.tsx
+++ /dev/null
@@ -1,25 +0,0 @@
-import { useCallback } from 'react';
-import { useSWRConfig } from 'swr';
-import { restBaseUrl } from '@openmrs/esm-framework';
-
-// this is copied directly from a similar hook in the appointments-app in patient management; ideally at some point we could import that hook directly
-const appointmentUrlMatcher = `${restBaseUrl}/appointment`;
-
-export function useMutateAppointments() {
-  const { mutate } = useSWRConfig();
-  // this mutate is intentionally broad because there may be many different keys that need to be invalidated when appointments are updated
-  const mutateAppointments = useCallback(
-    () =>
-      mutate((key) => {
-        return (
-          (typeof key === 'string' && key.startsWith(appointmentUrlMatcher)) ||
-          (Array.isArray(key) && key[0].startsWith(appointmentUrlMatcher))
-        );
-      }),
-    [mutate],
-  );
-
-  return {
-    mutateAppointments,
-  };
-}
diff --git a/packages/esm-patient-chart-app/src/visit/hooks/useServiceQueue.tsx b/packages/esm-patient-chart-app/src/visit/hooks/useServiceQueue.tsx
index 04786dbab7..2d4afa3874 100644
--- a/packages/esm-patient-chart-app/src/visit/hooks/useServiceQueue.tsx
+++ b/packages/esm-patient-chart-app/src/visit/hooks/useServiceQueue.tsx
@@ -1,61 +1,5 @@
 import { openmrsFetch, restBaseUrl, toDateObjectStrict, toOmrsIsoString } from '@openmrs/esm-framework';
 
-export async function saveQueueEntry(
-  visitUuid: string,
-  queueUuid: string,
-  patientUuid: string,
-  priority: string,
-  status: string,
-  sortWeight: number,
-  locationUuid: string,
-  visitQueueNumberAttributeUuid: string,
-  abortController?: AbortController,
-) {
-  await Promise.all([
-    generateVisitQueueNumber(locationUuid, visitUuid, queueUuid, visitQueueNumberAttributeUuid, abortController),
-  ]);
-
-  return openmrsFetch(`${restBaseUrl}/visit-queue-entry`, {
-    method: 'POST',
-    headers: {
-      'Content-Type': 'application/json',
-    },
-    body: {
-      visit: { uuid: visitUuid },
-      queueEntry: {
-        status: {
-          uuid: status,
-        },
-        priority: {
-          uuid: priority,
-        },
-        queue: {
-          uuid: queueUuid,
-        },
-        patient: {
-          uuid: patientUuid,
-        },
-        startedAt: toDateObjectStrict(toOmrsIsoString(new Date())),
-        sortWeight: sortWeight,
-      },
-    },
-    signal: abortController?.signal,
-  });
-}
-
-export async function generateVisitQueueNumber(
-  location: string,
-  visitUuid: string,
-  queueUuid: string,
-  visitQueueNumberAttributeUuid: string,
-  abortController?: AbortController,
-) {
-  await openmrsFetch(
-    `${restBaseUrl}/queue-entry-number?location=${location}&queue=${queueUuid}&visit=${visitUuid}&visitAttributeType=${visitQueueNumberAttributeUuid}`,
-    { signal: abortController?.signal },
-  );
-}
-
 export function removeQueuedPatient(
   queueUuid: string,
   queueEntryUuid: string,
diff --git a/packages/esm-patient-chart-app/src/visit/hooks/useUpcomingAppointments.tsx b/packages/esm-patient-chart-app/src/visit/hooks/useUpcomingAppointments.tsx
deleted file mode 100644
index 98553c980b..0000000000
--- a/packages/esm-patient-chart-app/src/visit/hooks/useUpcomingAppointments.tsx
+++ /dev/null
@@ -1,34 +0,0 @@
-import dayjs from 'dayjs';
-import { openmrsFetch, restBaseUrl, type OpenmrsResource, useAbortController } from '@openmrs/esm-framework';
-import { omrsDateFormat } from '../../constants';
-
-export interface AppointmentPayload {
-  patientUuid: string;
-  serviceUuid: string;
-  startDateTime: string;
-  endDateTime: string;
-  appointmentKind: string;
-  providers?: Array<OpenmrsResource>;
-  locationUuid: string;
-  comments?: string;
-  status?: string;
-  appointmentNumber?: string;
-  uuid?: string;
-  providerUuid?: string | OpenmrsResource;
-  dateHonored?: string;
-}
-
-export const updateAppointmentStatus = async (
-  toStatus: string,
-  appointmentUuid: string,
-  abortController?: AbortController,
-) => {
-  const statusChangeTime = dayjs().format(omrsDateFormat);
-  const url = `${restBaseUrl}/appointments/${appointmentUuid}/status-change`;
-  return await openmrsFetch(url, {
-    body: { toStatus, onDate: statusChangeTime },
-    method: 'POST',
-    headers: { 'Content-Type': 'application/json' },
-    signal: abortController?.signal,
-  });
-};
diff --git a/packages/esm-patient-chart-app/src/visit/start-visit-button.component.tsx b/packages/esm-patient-chart-app/src/visit/start-visit-button.component.tsx
index e1cc24e514..6f88435e10 100644
--- a/packages/esm-patient-chart-app/src/visit/start-visit-button.component.tsx
+++ b/packages/esm-patient-chart-app/src/visit/start-visit-button.component.tsx
@@ -1,8 +1,7 @@
-import React, { useCallback } from 'react';
-import { useTranslation } from 'react-i18next';
 import { Button } from '@carbon/react';
 import { launchPatientChartWithWorkspaceOpen } from '@openmrs/esm-patient-common-lib';
-import { navigate } from '@openmrs/esm-framework';
+import React, { useCallback } from 'react';
+import { useTranslation } from 'react-i18next';
 
 const StartVisitButton = ({ patientUuid }) => {
   const { t } = useTranslation();
@@ -11,6 +10,9 @@ const StartVisitButton = ({ patientUuid }) => {
     launchPatientChartWithWorkspaceOpen({
       patientUuid,
       workspaceName: 'start-visit-workspace-form',
+      additionalProps: {
+        openedFrom: 'patient-chart-start-visit'
+      }
     });
   }, [patientUuid]);
 
diff --git a/packages/esm-patient-chart-app/src/visit/visit-action-items/edit-visit-details.component.tsx b/packages/esm-patient-chart-app/src/visit/visit-action-items/edit-visit-details.component.tsx
index 29dce5354a..6d96a877e4 100644
--- a/packages/esm-patient-chart-app/src/visit/visit-action-items/edit-visit-details.component.tsx
+++ b/packages/esm-patient-chart-app/src/visit/visit-action-items/edit-visit-details.component.tsx
@@ -18,6 +18,7 @@ const EditVisitDetailsActionItem: React.FC<EditVisitDetailsActionItemProps> = ({
     launchPatientWorkspace('start-visit-workspace-form', {
       workspaceTitle: t('editVisitDetails', 'Edit visit details'),
       visitToEdit: visit,
+      openedFrom: 'patient-chart-edit-visit'
     });
   };
 
diff --git a/packages/esm-patient-chart-app/src/visit/visit-form/visit-form.component.tsx b/packages/esm-patient-chart-app/src/visit/visit-form/visit-form.component.tsx
index f9be291f36..34b6d25a7d 100644
--- a/packages/esm-patient-chart-app/src/visit/visit-form/visit-form.component.tsx
+++ b/packages/esm-patient-chart-app/src/visit/visit-form/visit-form.component.tsx
@@ -1,7 +1,3 @@
-import React, { useCallback, useEffect, useMemo, useState } from 'react';
-import classNames from 'classnames';
-import dayjs from 'dayjs';
-import isSameOrBefore from 'dayjs/plugin/isSameOrBefore';
 import {
   Button,
   ButtonSet,
@@ -16,18 +12,12 @@ import {
   Stack,
   Switch,
 } from '@carbon/react';
-import { Controller, FormProvider, useForm } from 'react-hook-form';
-import { first } from 'rxjs/operators';
-import { from } from 'rxjs';
-import { useTranslation } from 'react-i18next';
-import { z } from 'zod';
 import { zodResolver } from '@hookform/resolvers/zod';
 import {
+  Extension,
   ExtensionSlot,
   formatDatetime,
   type NewVisitPayload,
-  openmrsFetch,
-  restBaseUrl,
   saveVisit,
   showSnackbar,
   toDateObjectStrict,
@@ -35,13 +25,12 @@ import {
   updateVisit,
   useConfig,
   useConnectivity,
+  useFeatureFlag,
   useLayoutType,
   usePatient,
   useSession,
   useVisit,
-  useVisitTypes,
   type Visit,
-  useFeatureFlag,
 } from '@openmrs/esm-framework';
 import {
   convertTime12to24,
@@ -50,27 +39,45 @@ import {
   time12HourFormatRegex,
   useActivePatientEnrollment,
 } from '@openmrs/esm-patient-common-lib';
+import classNames from 'classnames';
+import dayjs from 'dayjs';
+import isSameOrBefore from 'dayjs/plugin/isSameOrBefore';
+import React, { useCallback, useEffect, useMemo, useState } from 'react';
+import { Controller, FormProvider, useForm } from 'react-hook-form';
+import { useTranslation } from 'react-i18next';
+import { z } from 'zod';
 import { type ChartConfig } from '../../config-schema';
-import { type VisitFormData } from './visit-form.resource';
-import { MemoizedRecommendedVisitType } from './recommended-visit-type.component';
-import { saveQueueEntry } from '../hooks/useServiceQueue';
-import { updateAppointmentStatus } from '../hooks/useUpcomingAppointments';
-import { useMutateAppointments } from '../hooks/useMutateAppointments';
-import { useOfflineVisitType } from '../hooks/useOfflineVisitType';
+
+import { useDefaultVisitLocation } from '../hooks/useDefaultVisitLocation';
+import { useEmrConfiguration } from '../hooks/useEmrConfiguration';
 import { useVisitAttributeTypes } from '../hooks/useVisitAttributeType';
-import { useVisitQueueEntry } from '../queue-entry/queue.resource';
 import { useInfiniteVisits, useVisits } from '../visits-widget/visit.resource';
 import BaseVisitType from './base-visit-type.component';
 import LocationSelector from './location-selector.component';
+import { MemoizedRecommendedVisitType } from './recommended-visit-type.component';
 import VisitAttributeTypeFields from './visit-attribute-type.component';
 import VisitDateTimeField from './visit-date-time.component';
+import {
+  createVisitAttribute,
+  deleteVisitAttribute,
+  type OnVisitCreatedOrUpdatedCallback,
+  updateVisitAttribute,
+  useConditionalVisitTypes,
+  useOnVisitCreatedOrUpdatedCallbacks,
+  type VisitFormData,
+} from './visit-form.resource';
 import styles from './visit-form.scss';
-import { useDefaultVisitLocation } from '../hooks/useDefaultVisitLocation';
-import { useEmrConfiguration } from '../hooks/useEmrConfiguration';
 
 dayjs.extend(isSameOrBefore);
 
 interface StartVisitFormProps extends DefaultPatientWorkspaceProps {
+  /**
+   * A unique string identifying where the visit form is opened from.
+   * This string is passed into various extensions within the form to
+   * affect how / if they should be rendered.
+   */
+  openedFrom: string;
+
   showPatientHeader?: boolean;
   showVisitEndDateTimeFields: boolean;
   visitToEdit?: Visit;
@@ -83,6 +90,7 @@ const StartVisitForm: React.FC<StartVisitFormProps> = ({
   showPatientHeader = false,
   showVisitEndDateTimeFields,
   visitToEdit,
+  openedFrom,
 }) => {
   const { t } = useTranslation();
   const isTablet = useLayoutType() === 'tablet';
@@ -104,28 +112,15 @@ const StartVisitForm: React.FC<StartVisitFormProps> = ({
   const { mutate: mutateCurrentVisit } = useVisit(patientUuid);
   const { mutateVisits } = useVisits(patientUuid);
   const { mutateVisits: mutateInfiniteVisits } = useInfiniteVisits(patientUuid);
-  const { mutateAppointments } = useMutateAppointments();
   const allVisitTypes = useConditionalVisitTypes();
 
-  const { mutate } = useVisit(patientUuid);
   const [errorFetchingResources, setErrorFetchingResources] = useState<{
     blockSavingForm: boolean;
   }>(null);
-  const [upcomingAppointment, setUpcomingAppointment] = useState(null);
-  const upcomingAppointmentState = useMemo(() => ({ patientUuid, setUpcomingAppointment }), [patientUuid]);
-  const visitQueueNumberAttributeUuid = config.visitQueueNumberAttributeUuid;
-  const [visitUuid, setVisitUuid] = useState('');
-  const { mutate: mutateQueueEntry } = useVisitQueueEntry(patientUuid, visitUuid);
   const { visitAttributeTypes } = useVisitAttributeTypes();
   const [extraVisitInfo, setExtraVisitInfo] = useState(null);
-  const [{ service, priority, status, sortWeight, queueLocation }, setVisitFormFields] = useState({
-    service: null,
-    priority: null,
-    status: null,
-    sortWeight: null,
-    queueLocation: null,
-  });
 
+  const [OnVisitCreatedOrUpdatedCallbacks, setOnVisitCreatedOrUpdatedCallbacks] = useOnVisitCreatedOrUpdatedCallbacks();
   const displayVisitStopDateTimeFields = useMemo(
     () => Boolean(visitToEdit?.uuid || showVisitEndDateTimeFields),
     [visitToEdit?.uuid, showVisitEndDateTimeFields],
@@ -358,11 +353,7 @@ const StartVisitForm: React.FC<StartVisitFormProps> = ({
             if (value) {
               // Update attribute with new value
               promises.push(
-                openmrsFetch(`${restBaseUrl}/visit/${visitUuid}/attribute/${attributeToEdit.uuid}`, {
-                  method: 'POST',
-                  headers: { 'Content-type': 'application/json' },
-                  body: { value },
-                }).catch((err) => {
+                updateVisitAttribute(visitUuid, attributeToEdit.uuid, value).catch((err) => {
                   showSnackbar({
                     title: t('errorUpdatingVisitAttribute', 'Error updating the {{attributeName}} visit attribute', {
                       attributeName: attributeToEdit.attributeType.display,
@@ -371,14 +362,13 @@ const StartVisitForm: React.FC<StartVisitFormProps> = ({
                     isLowContrast: false,
                     subtitle: err?.message,
                   });
+                  return Promise.reject(err); // short-circuit promise chain
                 }),
               );
             } else {
               // Delete attribute if no value is provided
               promises.push(
-                openmrsFetch(`${restBaseUrl}/visit/${visitUuid}/attribute/${attributeToEdit.uuid}`, {
-                  method: 'DELETE',
-                }).catch((err) => {
+                deleteVisitAttribute(visitUuid, attributeToEdit.uuid).catch((err) => {
                   showSnackbar({
                     title: t('errorDeletingVisitAttribute', 'Error deleting the {{attributeName}} visit attribute', {
                       attributeName: attributeToEdit.attributeType.display,
@@ -387,6 +377,7 @@ const StartVisitForm: React.FC<StartVisitFormProps> = ({
                     isLowContrast: false,
                     subtitle: err?.message,
                   });
+                  return Promise.reject(err); // short-circuit promise chain
                 }),
               );
             }
@@ -394,11 +385,7 @@ const StartVisitForm: React.FC<StartVisitFormProps> = ({
         } else {
           if (value) {
             promises.push(
-              openmrsFetch(`${restBaseUrl}/visit/${visitUuid}/attribute`, {
-                method: 'POST',
-                headers: { 'Content-type': 'application/json' },
-                body: { attributeType, value },
-              }).catch((err) => {
+              createVisitAttribute(visitUuid, attributeType, value).catch((err) => {
                 showSnackbar({
                   title: t('errorCreatingVisitAttribute', 'Error creating the {{attributeName}} visit attribute', {
                     attributeName: visitAttributeTypes?.find((type) => type.uuid === attributeType)?.display,
@@ -407,6 +394,7 @@ const StartVisitForm: React.FC<StartVisitFormProps> = ({
                   isLowContrast: false,
                   subtitle: err?.message,
                 });
+                return Promise.reject(err); // short-circuit promise chain
               }),
             );
           }
@@ -436,8 +424,6 @@ const StartVisitForm: React.FC<StartVisitFormProps> = ({
         visitStopTimeFormat,
       } = data;
 
-      setIsSubmitting(true);
-
       const [hours, minutes] = convertTime12to24(visitStartTime, visitStartTimeFormat);
 
       let payload: NewVisitPayload = {
@@ -489,115 +475,29 @@ const StartVisitForm: React.FC<StartVisitFormProps> = ({
         handleCreateExtraVisitInfo && handleCreateExtraVisitInfo();
       }
 
+      setIsSubmitting(true);
       if (isOnline) {
-        (visitToEdit?.uuid
+        const visitRequest = visitToEdit?.uuid
           ? updateVisit(visitToEdit?.uuid, payload, abortController)
-          : saveVisit(payload, abortController)
-        )
-          .then((response) => {
-            if (config.showServiceQueueFields && queueLocation && service && priority) {
-              // retrieve values from the queue extension
-              setVisitUuid(response.data.uuid);
-
-              saveQueueEntry(
-                response.data.uuid,
-                service,
-                patientUuid,
-                priority,
-                status,
-                sortWeight,
-                queueLocation,
-                visitQueueNumberAttributeUuid,
-                abortController,
-              ).then(
-                () => {
-                  mutateCurrentVisit();
-                  mutateVisits();
-                  mutateInfiniteVisits();
-                  mutateQueueEntry();
-                  showSnackbar({
-                    kind: 'success',
-                    title: t('visitStarted', 'Visit started'),
-                    subtitle: t('queueAddedSuccessfully', `Patient added to the queue successfully.`),
-                  });
-                },
-                (error) => {
-                  showSnackbar({
-                    title: t('queueEntryError', 'Error adding patient to the queue'),
-                    kind: 'error',
-                    isLowContrast: false,
-                    subtitle: error?.message,
-                  });
-                },
-              );
-
-              if (config.showUpcomingAppointments && upcomingAppointment) {
-                updateAppointmentStatus('CheckedIn', upcomingAppointment.uuid, abortController).then(
-                  () => {
-                    mutateCurrentVisit();
-                    mutateVisits();
-                    mutateInfiniteVisits();
-                    mutateAppointments();
-                    showSnackbar({
-                      isLowContrast: true,
-                      kind: 'success',
-                      subtitle: t('appointmentMarkedChecked', 'Appointment marked as Checked In'),
-                      title: t('appointmentCheckedIn', 'Appointment Checked In'),
-                    });
-                  },
-                  (error) => {
-                    showSnackbar({
-                      title: t('updateError', 'Error updating upcoming appointment'),
-                      kind: 'error',
-                      isLowContrast: false,
-                      subtitle: error?.message,
-                    });
-                  },
-                );
-              }
-            }
+          : saveVisit(payload, abortController);
 
-            // TODO: Refactor this to use Promises
-            from(handleVisitAttributes(visitAttributes, response.data.uuid))
-              .pipe(first())
-              .subscribe({
-                next: (attributesResponses) => {
-                  setIsSubmitting(false);
-                  // Check for no undefined,
-                  // that if there was no failed requests on either creating, updating or deleting an attribute
-                  // then continue and close workspace
-                  if (!attributesResponses.includes(undefined)) {
-                    mutateCurrentVisit();
-                    mutateVisits();
-                    mutateInfiniteVisits();
-                    closeWorkspace({ ignoreChanges: true });
-                    showSnackbar({
-                      isLowContrast: true,
-                      kind: 'success',
-                      subtitle: !visitToEdit
-                        ? t('visitStartedSuccessfully', '{{visit}} started successfully', {
-                            visit: response?.data?.visitType?.display ?? t('visit', 'Visit'),
-                          })
-                        : t('visitDetailsUpdatedSuccessfully', '{{visit}} updated successfully', {
-                            visit: response?.data?.visitType?.display ?? t('pastVisit', 'Past visit'),
-                          }),
-                      title: !visitToEdit
-                        ? t('visitStarted', 'Visit started')
-                        : t('visitDetailsUpdated', 'Visit details updated'),
-                    });
-                  }
-                },
-                error: (error) => {
-                  showSnackbar({
-                    title: !visitToEdit
-                      ? t('startVisitError', 'Error starting visit')
-                      : t('errorUpdatingVisitDetails', 'Error updating visit details'),
-                    kind: 'error',
-                    isLowContrast: false,
-                    subtitle: error?.message,
-                  });
-                },
-              });
+        visitRequest
+          .then((response) => {
+            showSnackbar({
+              isLowContrast: true,
+              kind: 'success',
+              subtitle: !visitToEdit
+                ? t('visitStartedSuccessfully', '{{visit}} started successfully', {
+                    visit: response?.data?.visitType?.display ?? t('visit', 'Visit'),
+                  })
+                : t('visitDetailsUpdatedSuccessfully', '{{visit}} updated successfully', {
+                    visit: response?.data?.visitType?.display ?? t('pastVisit', 'Past visit'),
+                  }),
+              title: !visitToEdit
+                ? t('visitStarted', 'Visit started')
+                : t('visitDetailsUpdated', 'Visit details updated'),
+            });
+            return response;
           })
           .catch((error) => {
             showSnackbar({
@@ -608,6 +508,47 @@ const StartVisitForm: React.FC<StartVisitFormProps> = ({
               isLowContrast: false,
               subtitle: error?.message,
             });
+            return Promise.reject(error); // short-circuit promise chain
+          })
+          .then((response) => {
+            // now that visit is created / updated, we run post-submit actions
+            // to update visit attributes or any other OnVisitCreatedOrUpdated actions
+            const visit = response.data;
+
+            // handleVisitAttributes already has code to show error snackbar when attribute fails to update
+            // no need for catch block here
+            const visitAttributesRequest = handleVisitAttributes(visitAttributes, response.data.uuid).then(
+              (visitAttributesResponses) => {
+                if (visitAttributesResponses.length > 0) {
+                  showSnackbar({
+                    isLowContrast: true,
+                    kind: 'success',
+                    title: t(
+                      'additionalVisitInformationUpdatedSuccessfully',
+                      'Additional visit information updated successfully',
+                    ),
+                  });
+                }
+              },
+            );
+
+            const OnVisitCreatedOrUpdatedRequests = [...OnVisitCreatedOrUpdatedCallbacks.values()].map(
+              (OnVisitCreatedOrUpdated) => OnVisitCreatedOrUpdated(visit, patientUuid),
+            );
+
+            return Promise.all([visitAttributesRequest, ...OnVisitCreatedOrUpdatedRequests]);
+          })
+          .then(() => {
+            closeWorkspace({ ignoreChanges: true });
+          })
+          .catch(() => {
+            // do nothing, this catches any reject promises used for short-circuiting
+          })
+          .finally(() => {
+            setIsSubmitting(false);
+            mutateCurrentVisit();
+            mutateVisits();
+            mutateInfiniteVisits();
           });
       } else {
         createOfflineVisitForPatient(
@@ -615,28 +556,33 @@ const StartVisitForm: React.FC<StartVisitFormProps> = ({
           visitLocation.uuid,
           config.offlineVisitTypeUuid,
           payload.startDatetime,
-        ).then(
-          () => {
-            mutate();
-            closeWorkspace({ ignoreChanges: true });
-            showSnackbar({
-              isLowContrast: true,
-              kind: 'success',
-              subtitle: t('visitStartedSuccessfully', '{{visit}} started successfully', {
-                visit: t('offlineVisit', 'Offline Visit'),
-              }),
-              title: t('visitStarted', 'Visit started'),
-            });
-          },
-          (error: Error) => {
-            showSnackbar({
-              title: t('startVisitError', 'Error starting visit'),
-              kind: 'error',
-              isLowContrast: false,
-              subtitle: error?.message,
-            });
-          },
-        );
+        )
+          .then(
+            () => {
+              mutateCurrentVisit();
+              closeWorkspace({ ignoreChanges: true });
+              showSnackbar({
+                isLowContrast: true,
+                kind: 'success',
+                subtitle: t('visitStartedSuccessfully', '{{visit}} started successfully', {
+                  visit: t('offlineVisit', 'Offline Visit'),
+                }),
+                title: t('visitStarted', 'Visit started'),
+              });
+            },
+            (error: Error) => {
+              showSnackbar({
+                title: t('startVisitError', 'Error starting visit'),
+                kind: 'error',
+                isLowContrast: false,
+                subtitle: error?.message,
+              });
+            },
+          )
+          .finally(() => {
+            setIsSubmitting(false);
+          });
+
         return;
       }
     },
@@ -644,28 +590,17 @@ const StartVisitForm: React.FC<StartVisitFormProps> = ({
       closeWorkspace,
       config.offlineVisitTypeUuid,
       config.showExtraVisitAttributesSlot,
-      config.showServiceQueueFields,
-      config.showUpcomingAppointments,
       displayVisitStopDateTimeFields,
       extraVisitInfo,
       handleVisitAttributes,
       isOnline,
-      mutate,
-      mutateAppointments,
       mutateCurrentVisit,
-      mutateQueueEntry,
       mutateVisits,
       mutateInfiniteVisits,
+      OnVisitCreatedOrUpdatedCallbacks,
       patientUuid,
-      priority,
-      queueLocation,
-      service,
-      sortWeight,
-      status,
       t,
-      upcomingAppointment,
       validateVisitStartStopDatetime,
-      visitQueueNumberAttributeUuid,
       visitToEdit,
     ],
   );
@@ -726,15 +661,18 @@ const StartVisitForm: React.FC<StartVisitFormProps> = ({
               />
             )}
 
-            {/* Upcoming appointments. This get shown when upcoming appointments are configured */}
-            {config.showUpcomingAppointments && (
-              <section>
-                <div className={styles.sectionTitle}></div>
-                <div className={styles.sectionField}>
-                  <ExtensionSlot state={upcomingAppointmentState} name="upcoming-appointment-slot" />
-                </div>
-              </section>
-            )}
+            {/* Upcoming appointments. This get shown when config.showUpcomingAppointments is true. */}
+            <section>
+              <div className={styles.sectionTitle}></div>
+              <div className={styles.sectionField}>
+                <VisitFormExtensionSlot
+                  name="visit-form-top-slot"
+                  patientUuid={patientUuid}
+                  visitFormOpenedFrom={openedFrom}
+                  setOnVisitCreatedOrUpdatedCallbacks={setOnVisitCreatedOrUpdatedCallbacks}
+                />
+              </div>
+            </section>
 
             {/* This field lets the user select a location for the visit. The location is required for the visit to be saved. Defaults to the active session location */}
             <LocationSelector control={control} />
@@ -833,15 +771,19 @@ const StartVisitForm: React.FC<StartVisitFormProps> = ({
               </div>
             </section>
 
-            {/* Queue location and queue fields. These get shown when queue location and queue fields are configured */}
-            {config.showServiceQueueFields && (
-              <section>
-                <div className={styles.sectionTitle}></div>
-                <div className={styles.sectionField}>
-                  <ExtensionSlot name="visit-form-queue-slot" state={{ setFormFields: setVisitFormFields }} />
-                </div>
-              </section>
-            )}
+            {/* Queue location and queue fields. These get shown when config.showServiceQueueFields is true,
+                or when the form is opened from the queues app */}
+            <section>
+              <div className={styles.sectionTitle}></div>
+              <div className={styles.sectionField}>
+                <VisitFormExtensionSlot
+                  name="visit-form-bottom-slot"
+                  patientUuid={patientUuid}
+                  visitFormOpenedFrom={openedFrom}
+                  setOnVisitCreatedOrUpdatedCallbacks={setOnVisitCreatedOrUpdatedCallbacks}
+                />
+              </div>
+            </section>
           </Stack>
         </div>
         <ButtonSet
@@ -878,12 +820,56 @@ const StartVisitForm: React.FC<StartVisitFormProps> = ({
   );
 };
 
-function useConditionalVisitTypes() {
-  const isOnline = useConnectivity();
+interface VisitFormExtensionSlotProps {
+  name: string;
+  patientUuid: string;
+  visitFormOpenedFrom: string;
+  setOnVisitCreatedOrUpdatedCallbacks: React.Dispatch<
+    React.SetStateAction<Map<string, OnVisitCreatedOrUpdatedCallback>>
+  >;
+}
 
-  const visitTypesHook = isOnline ? useVisitTypes : useOfflineVisitType;
+type VisitFormExtensionState = {
+  patientUuid: string;
 
-  return visitTypesHook();
-}
+  /**
+   * This function allows an extension to register a callback to run after a visit has been created.
+   * This callback can be used to make further requests. The callback should handle its own UI notification
+   * on success / failure, and its returned Promise MUST resolve on success and MUST reject on failure.
+   * @param callback
+   * @returns
+   */
+  setOnVisitCreatedOrUpdated: (callback: OnVisitCreatedOrUpdatedCallback) => void;
+
+  visitFormOpenedFrom: string;
+  patientChartConfig: ChartConfig;
+};
+
+const VisitFormExtensionSlot: React.FC<VisitFormExtensionSlotProps> = ({
+  name,
+  patientUuid,
+  visitFormOpenedFrom,
+  setOnVisitCreatedOrUpdatedCallbacks,
+}) => {
+  const config = useConfig<ChartConfig>();
+
+  return (
+    <ExtensionSlot name={name}>
+      {(extension) => {
+        const state: VisitFormExtensionState = {
+          patientUuid,
+          setOnVisitCreatedOrUpdated: (callback) => {
+            setOnVisitCreatedOrUpdatedCallbacks((old) => {
+              return new Map(old).set(extension.id, callback);
+            });
+          },
+          visitFormOpenedFrom,
+          patientChartConfig: config,
+        };
+        return <Extension state={state} />;
+      }}
+    </ExtensionSlot>
+  );
+};
 
 export default StartVisitForm;
diff --git a/packages/esm-patient-chart-app/src/visit/visit-form/visit-form.resource.ts b/packages/esm-patient-chart-app/src/visit/visit-form/visit-form.resource.ts
index d36dff2415..bb22db8f14 100644
--- a/packages/esm-patient-chart-app/src/visit/visit-form/visit-form.resource.ts
+++ b/packages/esm-patient-chart-app/src/visit/visit-form/visit-form.resource.ts
@@ -1,4 +1,7 @@
+import { openmrsFetch, restBaseUrl, useConnectivity, useVisitTypes, type Visit } from '@openmrs/esm-framework';
 import { type amPm } from '@openmrs/esm-patient-common-lib';
+import { useOfflineVisitType } from '../hooks/useOfflineVisitType';
+import { useState } from 'react';
 
 export type VisitFormData = {
   visitStartDate: Date;
@@ -17,3 +20,39 @@ export type VisitFormData = {
     [x: string]: string;
   };
 };
+
+export function useConditionalVisitTypes() {
+  const isOnline = useConnectivity();
+
+  const visitTypesHook = isOnline ? useVisitTypes : useOfflineVisitType;
+
+  return visitTypesHook();
+}
+
+export type OnVisitCreatedOrUpdatedCallback = (visit: Visit, patientUuid: string) => Promise<any>;
+
+export function useOnVisitCreatedOrUpdatedCallbacks() {
+  return useState<Map<string, OnVisitCreatedOrUpdatedCallback>>(new Map());
+}
+
+export function createVisitAttribute(visitUuid: string, attributeType: string, value: string) {
+  return openmrsFetch(`${restBaseUrl}/visit/${visitUuid}/attribute`, {
+    method: 'POST',
+    headers: { 'Content-type': 'application/json' },
+    body: { attributeType, value },
+  });
+}
+
+export function updateVisitAttribute(visitUuid: string, visitAttributeUuid: string, value: string) {
+  return openmrsFetch(`${restBaseUrl}/visit/${visitUuid}/attribute/${visitAttributeUuid}`, {
+    method: 'POST',
+    headers: { 'Content-type': 'application/json' },
+    body: { value },
+  });
+}
+
+export function deleteVisitAttribute(visitUuid: string, visitAttributeUuid: string) {
+  return openmrsFetch(`${restBaseUrl}/visit/${visitUuid}/attribute/${visitAttributeUuid}`, {
+    method: 'DELETE',
+  });
+}
diff --git a/packages/esm-patient-chart-app/src/visit/visit-form/visit-form.test.tsx b/packages/esm-patient-chart-app/src/visit/visit-form/visit-form.test.tsx
index 376f955b9d..da56aa39dc 100644
--- a/packages/esm-patient-chart-app/src/visit/visit-form/visit-form.test.tsx
+++ b/packages/esm-patient-chart-app/src/visit/visit-form/visit-form.test.tsx
@@ -1,12 +1,5 @@
-import React from 'react';
-import dayjs from 'dayjs';
-import { render, screen } from '@testing-library/react';
-import { esmPatientChartSchema, type ChartConfig } from '../../config-schema';
-import userEvent from '@testing-library/user-event';
 import {
   getDefaultsFromConfigSchema,
-  openmrsFetch,
-  restBaseUrl,
   saveVisit,
   showSnackbar,
   updateVisit,
@@ -17,11 +10,22 @@ import {
   type FetchResponse,
   type Visit,
 } from '@openmrs/esm-framework';
-import { mockPatient } from 'tools';
+import { render, screen } from '@testing-library/react';
+import userEvent from '@testing-library/user-event';
 import { mockLocations, mockVisitTypes, mockVisitWithAttributes } from '__mocks__';
+import dayjs from 'dayjs';
+import React from 'react';
+import { mockPatient } from 'tools';
+import { esmPatientChartSchema, type ChartConfig } from '../../config-schema';
 import { useEmrConfiguration } from '../hooks/useEmrConfiguration';
 import { useVisitAttributeType } from '../hooks/useVisitAttributeType';
 import StartVisitForm from './visit-form.component';
+import {
+  createVisitAttribute,
+  deleteVisitAttribute,
+  updateVisitAttribute,
+  useOnVisitCreatedOrUpdatedCallbacks,
+} from './visit-form.resource';
 
 const visitUuid = 'test_visit_uuid';
 const visitAttributes = {
@@ -52,6 +56,7 @@ const mockPromptBeforeClosing = jest.fn();
 const mockSetTitle = jest.fn();
 
 const testProps = {
+  openedFrom: 'test',
   patientUuid: mockPatient.id,
   closeWorkspace: mockCloseWorkspace,
   closeWorkspaceWithSavedChanges: mockCloseWorkspace,
@@ -62,7 +67,6 @@ const testProps = {
 
 const mockSaveVisit = jest.mocked(saveVisit);
 const mockUpdateVisit = jest.mocked(updateVisit);
-const mockOpenmrsFetch = jest.mocked(openmrsFetch);
 const mockUseConfig = jest.mocked(useConfig<ChartConfig>);
 const mockUseVisitAttributeType = jest.mocked(useVisitAttributeType);
 const mockUseVisitTypes = jest.mocked(useVisitTypes);
@@ -70,6 +74,16 @@ const mockUsePatient = jest.mocked(usePatient);
 const mockUseLocations = jest.mocked(useLocations);
 const mockUseEmrConfiguration = jest.mocked(useEmrConfiguration);
 
+// from ./visit-form.resource
+const mockOnVisitCreatedOrUpdatedCallback = jest.fn();
+jest.mocked(useOnVisitCreatedOrUpdatedCallbacks).mockReturnValue([
+  new Map([['test-extension-id', mockOnVisitCreatedOrUpdatedCallback]]), // OnVisitCreatedOrUpdatedCallbacks
+  jest.fn(), // setOnVisitCreatedOrUpdatedCallbacks
+]);
+const mockCreateVisitAttribute = jest.mocked(createVisitAttribute).mockResolvedValue({} as unknown as FetchResponse);
+const mockUpdateVisitAttribute = jest.mocked(updateVisitAttribute).mockResolvedValue({} as unknown as FetchResponse);
+const mockDeleteVisitAttribute = jest.mocked(deleteVisitAttribute).mockResolvedValue({} as unknown as FetchResponse);
+
 jest.mock('@openmrs/esm-patient-common-lib', () => ({
   ...jest.requireActual('@openmrs/esm-patient-common-lib'),
   useActivePatientEnrollment: jest.fn().mockReturnValue({
@@ -98,7 +112,7 @@ jest.mock('../hooks/useVisitAttributeType', () => ({
   useVisitAttributeTypes: jest.fn(() => ({
     isLoading: false,
     error: null,
-    data: [visitAttributes.punctuality, visitAttributes.insurancePolicyNumber],
+    visitAttributeTypes: [visitAttributes.punctuality, visitAttributes.insurancePolicyNumber],
   })),
   useConceptAnswersForVisitAttributeType: jest.fn(() => ({
     isLoading: false,
@@ -146,6 +160,27 @@ jest.mock('../hooks/useDefaultFacilityLocation', () => {
   };
 });
 
+jest.mock('./visit-form.resource', () => {
+  const requireActual = jest.requireActual('./visit-form.resource');
+  return {
+    ...requireActual,
+    useOnVisitCreatedOrUpdatedCallbacks: jest.fn(),
+    createVisitAttribute: jest.fn(),
+    updateVisitAttribute: jest.fn(),
+    deleteVisitAttribute: jest.fn(),
+  };
+});
+
+mockSaveVisit.mockResolvedValue({
+  status: 201,
+  data: {
+    uuid: visitUuid,
+    visitType: {
+      display: 'Facility Visit',
+    },
+  },
+} as unknown as FetchResponse<Visit>);
+
 describe('Visit form', () => {
   beforeEach(() => {
     mockUseConfig.mockReturnValue({
@@ -275,15 +310,6 @@ describe('Visit form', () => {
   it('starts a new visit upon successful submission of the form', async () => {
     const user = userEvent.setup();
 
-    mockSaveVisit.mockResolvedValue({
-      status: 201,
-      data: {
-        visitType: {
-          display: 'Facility Visit',
-        },
-      },
-    } as unknown as FetchResponse<Visit>);
-
     renderVisitForm();
 
     const saveButton = screen.getByRole('button', { name: /Start visit/i });
@@ -320,8 +346,6 @@ describe('Visit form', () => {
   it('starts a new visit with attributes upon successful submission of the form', async () => {
     const user = userEvent.setup();
 
-    mockOpenmrsFetch.mockResolvedValue({} as unknown as FetchResponse);
-
     renderVisitForm();
 
     const saveButton = screen.getByRole('button', { name: /Start visit/i });
@@ -341,16 +365,6 @@ describe('Visit form', () => {
     await user.clear(insuranceNumberInput);
     await user.type(insuranceNumberInput, '183299');
 
-    mockSaveVisit.mockResolvedValue({
-      status: 201,
-      data: {
-        uuid: visitUuid,
-        visitType: {
-          display: 'Facility Visit',
-        },
-      },
-    } as unknown as FetchResponse<Visit>);
-
     await user.click(saveButton);
 
     expect(mockSaveVisit).toHaveBeenCalledTimes(1);
@@ -363,33 +377,39 @@ describe('Visit form', () => {
       expect.any(Object),
     );
 
-    expect(mockOpenmrsFetch).toHaveBeenCalledWith(`${restBaseUrl}/visit/${visitUuid}/attribute`, {
-      method: 'POST',
-      headers: { 'Content-type': 'application/json' },
-      body: { attributeType: visitAttributes.punctuality.uuid, value: '66cdc0a1-aa19-4676-af51-80f66d78d9eb' },
-    });
+    expect(mockCreateVisitAttribute).toHaveBeenCalledTimes(2);
+    expect(mockCreateVisitAttribute).toHaveBeenCalledWith(
+      visitUuid,
+      visitAttributes.punctuality.uuid,
+      '66cdc0a1-aa19-4676-af51-80f66d78d9eb',
+    );
+    expect(mockCreateVisitAttribute).toHaveBeenCalledWith(
+      visitUuid,
+      visitAttributes.insurancePolicyNumber.uuid,
+      '183299',
+    );
 
-    expect(mockOpenmrsFetch).toHaveBeenCalledWith(`${restBaseUrl}/visit/${visitUuid}/attribute`, {
-      method: 'POST',
-      headers: { 'Content-type': 'application/json' },
-      body: { attributeType: visitAttributes.insurancePolicyNumber.uuid, value: '183299' },
-    });
+    expect(mockOnVisitCreatedOrUpdatedCallback).toHaveBeenCalled();
 
     expect(mockCloseWorkspace).toHaveBeenCalled();
 
+    expect(showSnackbar).toHaveBeenCalledTimes(2);
     expect(showSnackbar).toHaveBeenCalledWith({
       isLowContrast: true,
       subtitle: expect.stringContaining('started successfully'),
       kind: 'success',
       title: 'Visit started',
     });
+    expect(showSnackbar).toHaveBeenCalledWith({
+      isLowContrast: true,
+      title: expect.stringContaining('Additional visit information updated successfully'),
+      kind: 'success',
+    });
   });
 
   it('updates visit attributes when editing an existing visit', async () => {
     const user = userEvent.setup();
 
-    mockOpenmrsFetch.mockResolvedValue({} as unknown as FetchResponse);
-
     renderVisitForm(mockVisitWithAttributes);
 
     const saveButton = screen.getByRole('button', { name: /Update visit/i });
@@ -430,23 +450,13 @@ describe('Visit form', () => {
       expect.any(Object),
     );
 
-    expect(mockOpenmrsFetch).toHaveBeenCalledWith(
-      `${restBaseUrl}/visit/${visitUuid}/attribute/c98e66d7-7db5-47ae-b46f-91a0f3b6dda1`,
-      {
-        method: 'POST',
-        headers: { 'Content-type': 'application/json' },
-        body: { value: '66cdc0a1-aa19-4676-af51-80f66d78d9ec' },
-      },
-    );
-
-    expect(mockOpenmrsFetch).toHaveBeenCalledWith(
-      `${restBaseUrl}/visit/${visitUuid}/attribute/d6d7d26a-5975-4f03-8abb-db073c948897`,
-      {
-        method: 'POST',
-        headers: { 'Content-type': 'application/json' },
-        body: { value: '1873290' },
-      },
+    expect(mockUpdateVisitAttribute).toHaveBeenCalledTimes(2);
+    expect(mockUpdateVisitAttribute).toHaveBeenCalledWith(
+      visitUuid,
+      'c98e66d7-7db5-47ae-b46f-91a0f3b6dda1',
+      '66cdc0a1-aa19-4676-af51-80f66d78d9ec',
     );
+    expect(mockUpdateVisitAttribute).toHaveBeenCalledWith(visitUuid, 'd6d7d26a-5975-4f03-8abb-db073c948897', '1873290');
 
     expect(mockCloseWorkspace).toHaveBeenCalled();
     expect(showSnackbar).toHaveBeenCalledWith({
@@ -460,8 +470,6 @@ describe('Visit form', () => {
   it('deletes visit attributes if the value of the field is cleared when editing an existing visit', async () => {
     const user = userEvent.setup();
 
-    mockOpenmrsFetch.mockResolvedValue({} as FetchResponse);
-
     renderVisitForm(mockVisitWithAttributes);
 
     const saveButton = screen.getByRole('button', { name: /Update visit/i });
@@ -501,15 +509,9 @@ describe('Visit form', () => {
       expect.any(Object),
     );
 
-    expect(mockOpenmrsFetch).toHaveBeenCalledWith(
-      `${restBaseUrl}/visit/${visitUuid}/attribute/c98e66d7-7db5-47ae-b46f-91a0f3b6dda1`,
-      { method: 'DELETE' },
-    );
-
-    expect(mockOpenmrsFetch).toHaveBeenCalledWith(
-      `${restBaseUrl}/visit/${visitUuid}/attribute/d6d7d26a-5975-4f03-8abb-db073c948897`,
-      { method: 'DELETE' },
-    );
+    expect(mockDeleteVisitAttribute).toHaveBeenCalledTimes(2);
+    expect(mockDeleteVisitAttribute).toHaveBeenCalledWith(visitUuid, 'c98e66d7-7db5-47ae-b46f-91a0f3b6dda1');
+    expect(mockDeleteVisitAttribute).toHaveBeenCalledWith(visitUuid, 'd6d7d26a-5975-4f03-8abb-db073c948897');
 
     expect(mockCloseWorkspace).toHaveBeenCalled();
 
@@ -524,7 +526,7 @@ describe('Visit form', () => {
   it('renders an error message if there was a problem starting a new visit', async () => {
     const user = userEvent.setup();
 
-    mockSaveVisit.mockRejectedValue({ status: 500, statusText: 'Internal server error' });
+    mockSaveVisit.mockRejectedValueOnce({ status: 500, statusText: 'Internal server error' });
 
     renderVisitForm();
 
@@ -533,7 +535,7 @@ describe('Visit form', () => {
     const saveButton = screen.getByRole('button', { name: /Start Visit/i });
     const locationPicker = screen.getByRole('combobox', { name: /Select a location/i });
     await user.click(locationPicker);
-    await user.click(screen.getByText('Inpatient Ward'));
+    await user.click(screen.getByText(/Inpatient Ward/i));
 
     await user.click(saveButton);
 
@@ -544,6 +546,56 @@ describe('Visit form', () => {
         title: 'Error starting visit',
       }),
     );
+
+    expect(mockOnVisitCreatedOrUpdatedCallback).not.toHaveBeenCalled();
+    expect(mockCloseWorkspace).not.toHaveBeenCalled();
+  });
+
+  it('renders an error message if there was a problem updating visit attributes after starting a new visit', async () => {
+    const user = userEvent.setup();
+
+    mockCreateVisitAttribute.mockRejectedValue({ status: 500, statusText: 'Internal server error' });
+
+    renderVisitForm();
+
+    await user.click(screen.getByLabelText(/Outpatient visit/i));
+
+    const saveButton = screen.getByRole('button', { name: /Start Visit/i });
+    const locationPicker = screen.getByRole('combobox', { name: /Select a location/i });
+    await user.click(locationPicker);
+    await user.click(screen.getByText(/Inpatient Ward/i));
+
+    const punctualityPicker = screen.getByRole('combobox', { name: 'Punctuality (optional)' });
+    await user.selectOptions(punctualityPicker, 'On time');
+
+    const insuranceNumberInput = screen.getByRole('textbox', { name: 'Insurance Policy Number (optional)' });
+    await user.clear(insuranceNumberInput);
+    await user.type(insuranceNumberInput, '183299');
+
+    await user.click(saveButton);
+
+    expect(showSnackbar).toHaveBeenCalledTimes(3);
+    expect(showSnackbar).toHaveBeenCalledWith({
+      isLowContrast: true,
+      subtitle: expect.stringContaining('started successfully'),
+      kind: 'success',
+      title: 'Visit started',
+    });
+    expect(showSnackbar).toHaveBeenCalledWith({
+      isLowContrast: false,
+      subtitle: undefined,
+      kind: 'error',
+      title: 'Error creating the Punctuality visit attribute',
+    });
+    expect(showSnackbar).toHaveBeenCalledWith({
+      isLowContrast: false,
+      subtitle: undefined,
+      kind: 'error',
+      title: 'Error creating the Insurance Policy Number visit attribute',
+    });
+
+    expect(mockOnVisitCreatedOrUpdatedCallback).toHaveBeenCalled();
+    expect(mockCloseWorkspace).not.toHaveBeenCalled();
   });
 
   it('displays a warning modal if the user attempts to discard the visit form with unsaved changes', async () => {
@@ -588,15 +640,6 @@ describe('Visit form', () => {
       ],
     });
 
-    mockSaveVisit.mockResolvedValue({
-      status: 201,
-      data: {
-        visitType: {
-          display: 'Facility Visit',
-        },
-      },
-    } as unknown as FetchResponse<Visit>);
-
     renderVisitForm();
 
     const saveButton = screen.getByRole('button', { name: /Start visit/i });
diff --git a/packages/esm-patient-chart-app/src/visit/visit-prompt/start-visit-dialog.component.tsx b/packages/esm-patient-chart-app/src/visit/visit-prompt/start-visit-dialog.component.tsx
index 9ecfb9ea92..561be2cbe0 100644
--- a/packages/esm-patient-chart-app/src/visit/visit-prompt/start-visit-dialog.component.tsx
+++ b/packages/esm-patient-chart-app/src/visit/visit-prompt/start-visit-dialog.component.tsx
@@ -38,9 +38,10 @@ const StartVisitDialog: React.FC<StartVisitDialogProps> = ({
       launchPatientChartWithWorkspaceOpen({
         patientUuid,
         workspaceName: 'start-visit-workspace-form',
+        additionalProps: {openedFrom: 'patient-chart-start-visit'}
       });
     } else {
-      launchPatientWorkspace('start-visit-workspace-form');
+      launchPatientWorkspace('start-visit-workspace-form', {openedFrom: 'patient-chart-start-visit'});
     }
 
     closeModal();
diff --git a/packages/esm-patient-chart-app/src/visit/visit-prompt/start-visit-dialog.test.tsx b/packages/esm-patient-chart-app/src/visit/visit-prompt/start-visit-dialog.test.tsx
index d9a9475fcb..567c7294f7 100644
--- a/packages/esm-patient-chart-app/src/visit/visit-prompt/start-visit-dialog.test.tsx
+++ b/packages/esm-patient-chart-app/src/visit/visit-prompt/start-visit-dialog.test.tsx
@@ -35,7 +35,9 @@ describe('StartVisit', () => {
 
     await user.click(startNewVisitButton);
 
-    expect(launchPatientWorkspace).toHaveBeenCalledWith('start-visit-workspace-form');
+    expect(launchPatientWorkspace).toHaveBeenCalledWith('start-visit-workspace-form', {
+      openedFrom: 'patient-chart-start-visit',
+    });
   });
 
   test('should launch edit past visit form', async () => {
diff --git a/packages/esm-patient-chart-app/src/visit/visits-widget/current-visit-summary.component.tsx b/packages/esm-patient-chart-app/src/visit/visits-widget/current-visit-summary.component.tsx
index 782594c4e1..aa473fd442 100644
--- a/packages/esm-patient-chart-app/src/visit/visits-widget/current-visit-summary.component.tsx
+++ b/packages/esm-patient-chart-app/src/visit/visits-widget/current-visit-summary.component.tsx
@@ -33,7 +33,7 @@ const CurrentVisitSummary: React.FC<CurrentVisitSummaryProps> = ({ patientUuid }
       <EmptyState
         headerTitle={t('currentVisit', 'Current visit')}
         displayText={t('noActiveVisitMessage', 'active visit')}
-        launchForm={() => launchPatientWorkspace('start-visit-workspace-form')}
+        launchForm={() => launchPatientWorkspace('start-visit-workspace-form', {openedFrom: 'patient-chart-current-visit-summary'})}
       />
     );
   }
diff --git a/packages/esm-patient-chart-app/translations/en.json b/packages/esm-patient-chart-app/translations/en.json
index bef2c0bf30..aaf1e2776a 100644
--- a/packages/esm-patient-chart-app/translations/en.json
+++ b/packages/esm-patient-chart-app/translations/en.json
@@ -1,11 +1,10 @@
 {
   "addAPastVisit": "Add a past visit",
+  "additionalVisitInformationUpdatedSuccessfully": "Additional visit information updated successfully",
   "addPastVisit": "Add past visit",
   "addPastVisitText": "You can add a new past visit or update an old one. Choose from one of the options below to continue.",
   "all": "All",
   "allEncounters": "All encounters",
-  "appointmentCheckedIn": "Appointment checked in",
-  "appointmentMarkedChecked": "Appointment marked as Checked In",
   "cancel": "Cancel",
   "cancelActiveVisitConfirmation": "Are you sure you want to cancel this active visit?",
   "cancellingVisit": "Cancelling visit",
@@ -122,8 +121,6 @@
   "program": "Program",
   "provider": "Provider",
   "quantity": "Quantity",
-  "queueAddedSuccessfully": "Patient has been added to the queue successfully.",
-  "queueEntryError": "Error adding patient to the queue",
   "recommended": "Recommended",
   "record": "Record",
   "refills": "Refills",
@@ -153,7 +150,6 @@
   "timeFormat ": "Time Format",
   "type": "Type",
   "undo": "Undo",
-  "updateError": "Error updating upcoming appointment",
   "updateVisit": "Update visit",
   "updatingVisit": "Updating visit",
   "visit": "Visit",