From 89af0648fc16d8b307b0b3699a0bdecc5399e4b6 Mon Sep 17 00:00:00 2001
From: Carlos Valente <carlosvalente@pm.me>
Date: Sat, 11 Jan 2025 16:06:43 +0100
Subject: [PATCH] refactor: remove legacy service

---
 apps/cli/main.js                              |   5 +-
 apps/client/src/common/models/Info.ts         |   3 -
 apps/client/src/common/models/OscSettings.ts  |  10 -
 .../src/features/app-settings/AppSettings.tsx |   2 -
 .../integrations-panel/HttpIntegrations.tsx   | 189 -----------
 .../IntegrationsPanel.module.css              |  16 -
 .../integrations-panel/IntegrationsPanel.tsx  |  42 ---
 .../integrations-panel/OscIntegrations.tsx    | 310 ------------------
 .../integrations-panel/integrationUtils.ts    |  19 --
 .../app-settings/useAppSettingsMenu.tsx       |   8 -
 apps/electron/src/main.js                     |   5 +-
 .../api-data/automation/automation.parser.ts  |  25 ++
 .../src/api-data/http/http.controller.ts      |  31 --
 apps/server/src/api-data/http/http.router.ts  |   9 -
 .../src/api-data/http/http.validation.ts      |  21 --
 apps/server/src/api-data/index.ts             |   4 -
 .../server/src/api-data/osc/osc.controller.ts |  32 --
 apps/server/src/api-data/osc/osc.router.ts    |   8 -
 .../server/src/api-data/osc/osc.validation.ts |  25 --
 .../src/api-data/session/session.service.ts   |   2 -
 apps/server/src/app.ts                        |  44 +--
 apps/server/src/index.ts                      |   6 +-
 apps/server/src/models/dataModel.ts           |  12 -
 .../integration-service/HttpIntegration.ts    |  80 -----
 .../integration-service/IIntegration.ts       |  11 -
 .../integration-service/IntegrationService.ts |  37 ---
 .../integration-service/OscIntegration.ts     | 147 ---------
 .../integrationUtils.test.ts                  | 169 ----------
 .../integration-service/integrationUtils.ts   |  73 -----
 .../project-service/ProjectService.ts         |  14 +-
 .../runtime-service/RuntimeService.ts         |   1 -
 .../server/src/utils/__tests__/parser.test.ts |   4 +-
 .../utils/__tests__/parserFunctions.test.ts   | 143 --------
 apps/server/src/utils/parser.ts               |  12 +-
 apps/server/src/utils/parserFunctions.ts      | 103 +-----
 .../ontime-controller/BackendResponse.type.ts |   2 -
 .../types/src/definitions/DataModel.type.ts   |   4 -
 .../src/definitions/core/HttpSettings.type.ts |   8 -
 .../src/definitions/core/OscSettings.type.ts  |  18 -
 packages/types/src/index.ts                   |   4 -
 40 files changed, 35 insertions(+), 1623 deletions(-)
 delete mode 100644 apps/client/src/common/models/OscSettings.ts
 delete mode 100644 apps/client/src/features/app-settings/panel/integrations-panel/HttpIntegrations.tsx
 delete mode 100644 apps/client/src/features/app-settings/panel/integrations-panel/IntegrationsPanel.module.css
 delete mode 100644 apps/client/src/features/app-settings/panel/integrations-panel/IntegrationsPanel.tsx
 delete mode 100644 apps/client/src/features/app-settings/panel/integrations-panel/OscIntegrations.tsx
 delete mode 100644 apps/client/src/features/app-settings/panel/integrations-panel/integrationUtils.ts
 delete mode 100644 apps/server/src/api-data/http/http.controller.ts
 delete mode 100644 apps/server/src/api-data/http/http.router.ts
 delete mode 100644 apps/server/src/api-data/http/http.validation.ts
 delete mode 100644 apps/server/src/api-data/osc/osc.controller.ts
 delete mode 100644 apps/server/src/api-data/osc/osc.router.ts
 delete mode 100644 apps/server/src/api-data/osc/osc.validation.ts
 delete mode 100644 apps/server/src/services/integration-service/HttpIntegration.ts
 delete mode 100644 apps/server/src/services/integration-service/IIntegration.ts
 delete mode 100644 apps/server/src/services/integration-service/IntegrationService.ts
 delete mode 100644 apps/server/src/services/integration-service/OscIntegration.ts
 delete mode 100644 apps/server/src/services/integration-service/integrationUtils.test.ts
 delete mode 100644 apps/server/src/services/integration-service/integrationUtils.ts
 delete mode 100644 packages/types/src/definitions/core/HttpSettings.type.ts
 delete mode 100644 packages/types/src/definitions/core/OscSettings.type.ts

diff --git a/apps/cli/main.js b/apps/cli/main.js
index 73f5260ba5..a2354a407d 100644
--- a/apps/cli/main.js
+++ b/apps/cli/main.js
@@ -3,14 +3,11 @@
 // NOTE: for now the following needs to be in place: ./server/index.cjs, ./client, ./external
 
 const ontimeServer = require('./server/index.cjs');
-const { initAssets, startServer, startIntegrations, shutdown } = ontimeServer;
+const { initAssets, startServer, shutdown } = ontimeServer;
 
 async function startOntime() {
   await initAssets();
-
   await startServer();
-
-  await startIntegrations();
 }
 
 startOntime();
diff --git a/apps/client/src/common/models/Info.ts b/apps/client/src/common/models/Info.ts
index 1cec492a80..d05acdd2b0 100644
--- a/apps/client/src/common/models/Info.ts
+++ b/apps/client/src/common/models/Info.ts
@@ -1,11 +1,8 @@
 import { GetInfo } from 'ontime-types';
 
-import { oscPlaceholderSettings } from './OscSettings';
-
 export const ontimePlaceholderInfo: GetInfo = {
   networkInterfaces: [],
   version: '2.0.0',
   serverPort: 4001,
-  osc: oscPlaceholderSettings,
   publicDir: '',
 };
diff --git a/apps/client/src/common/models/OscSettings.ts b/apps/client/src/common/models/OscSettings.ts
deleted file mode 100644
index 365b9ae8c1..0000000000
--- a/apps/client/src/common/models/OscSettings.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import { OSCSettings } from 'ontime-types';
-
-export const oscPlaceholderSettings: OSCSettings = {
-  portIn: 8888,
-  portOut: 9999,
-  targetIP: '127.0.0.1',
-  enabledIn: false,
-  enabledOut: false,
-  subscriptions: [],
-};
diff --git a/apps/client/src/features/app-settings/AppSettings.tsx b/apps/client/src/features/app-settings/AppSettings.tsx
index a4ceb8cc6e..3644c3d068 100644
--- a/apps/client/src/features/app-settings/AppSettings.tsx
+++ b/apps/client/src/features/app-settings/AppSettings.tsx
@@ -7,7 +7,6 @@ import AutomationPanel from './panel/automations-panel/AutomationPanel';
 import ClientControlPanel from './panel/client-control-panel/ClientControlPanel';
 import FeatureSettingsPanel from './panel/feature-settings-panel/FeatureSettingsPanel';
 import GeneralPanel from './panel/general-panel/GeneralPanel';
-import IntegrationsPanel from './panel/integrations-panel/IntegrationsPanel';
 import NetworkLogPanel from './panel/network-panel/NetworkLogPanel';
 import ProjectPanel from './panel/project-panel/ProjectPanel';
 import ShutdownPanel from './panel/shutdown-panel/ShutdownPanel';
@@ -31,7 +30,6 @@ export default function AppSettings() {
           {panel === 'general' && <GeneralPanel location={location} />}
           {panel === 'feature_settings' && <FeatureSettingsPanel location={location} />}
           {panel === 'sources' && <SourcesPanel />}
-          {panel === 'integrations' && <IntegrationsPanel location={location} />}
           {panel === 'automation' && <AutomationPanel location={location} />}
           {panel === 'client_control' && <ClientControlPanel />}
           {panel === 'about' && <AboutPanel />}
diff --git a/apps/client/src/features/app-settings/panel/integrations-panel/HttpIntegrations.tsx b/apps/client/src/features/app-settings/panel/integrations-panel/HttpIntegrations.tsx
deleted file mode 100644
index 7e28fe8732..0000000000
--- a/apps/client/src/features/app-settings/panel/integrations-panel/HttpIntegrations.tsx
+++ /dev/null
@@ -1,189 +0,0 @@
-import { Controller, useFieldArray, useForm } from 'react-hook-form';
-import { Button, IconButton, Input, Select, Switch } from '@chakra-ui/react';
-import { IoAdd } from '@react-icons/all-files/io5/IoAdd';
-import { IoTrash } from '@react-icons/all-files/io5/IoTrash';
-import { HttpSettings } from 'ontime-types';
-import { generateId } from 'ontime-utils';
-
-import { maybeAxiosError } from '../../../../common/api/utils';
-import { useHttpSettings, usePostHttpSettings } from '../../../../common/hooks-query/useHttpSettings';
-import { isKeyEscape } from '../../../../common/utils/keyEvent';
-import { startsWithHttp } from '../../../../common/utils/regex';
-import * as Panel from '../../panel-utils/PanelUtils';
-
-import { cycles } from './integrationUtils';
-
-import style from './IntegrationsPanel.module.css';
-
-export default function HttpIntegrations() {
-  const { data, status } = useHttpSettings();
-  const { mutateAsync } = usePostHttpSettings();
-
-  const {
-    control,
-    handleSubmit,
-    reset,
-    register,
-    setError,
-    formState: { errors, isSubmitting, isDirty, isValid },
-  } = useForm<HttpSettings>({
-    mode: 'onChange',
-    defaultValues: data,
-    values: data,
-    resetOptions: {
-      keepDirtyValues: true,
-    },
-  });
-
-  const { fields, prepend, remove } = useFieldArray({
-    name: 'subscriptions',
-    control,
-  });
-
-  const onSubmit = async (values: HttpSettings) => {
-    try {
-      await mutateAsync(values);
-    } catch (error) {
-      setError('root', { message: maybeAxiosError(error) });
-    }
-  };
-
-  const preventEscape = (event: React.KeyboardEvent) => {
-    if (isKeyEscape(event)) {
-      event.preventDefault();
-      event.stopPropagation();
-    }
-  };
-
-  const handleAddNewSubscription = () => {
-    prepend({
-      id: generateId(),
-      cycle: 'onLoad',
-      message: '',
-      enabled: true,
-    });
-  };
-
-  const handleDeleteSubscription = (index: number) => {
-    remove(index);
-  };
-
-  const canSubmit = !isSubmitting && isDirty && isValid;
-  const isLoading = status === 'pending';
-
-  return (
-    <Panel.Section>
-      <Panel.Card>
-        <Panel.SubHeader>
-          HTTP settings
-          <div className={style.flex}>
-            <Button variant='ontime-ghosted' size='sm' onClick={() => reset()} isDisabled={!canSubmit}>
-              Revert to saved
-            </Button>
-            <Button
-              variant='ontime-filled'
-              size='sm'
-              type='submit'
-              form='http-form'
-              isDisabled={!canSubmit}
-              isLoading={isSubmitting}
-            >
-              Save
-            </Button>
-          </div>
-        </Panel.SubHeader>
-        <Panel.Divider />
-        <Panel.Section as='form' id='http-form' onSubmit={handleSubmit(onSubmit)} onKeyDown={preventEscape}>
-          <Panel.Loader isLoading={isLoading} />
-          {errors?.root && <Panel.Error>{errors.root.message}</Panel.Error>}
-          <Panel.ListGroup>
-            <Panel.ListItem>
-              <Panel.Field title='HTTP Output' description='Provide feedback from Ontime through HTTP' />
-              <Controller
-                control={control}
-                name='enabledOut'
-                render={({ field: { onChange, value, ref } }) => (
-                  <Switch variant='ontime' size='lg' isChecked={value} onChange={onChange} ref={ref} />
-                )}
-              />
-            </Panel.ListItem>
-          </Panel.ListGroup>
-
-          <Panel.Divider />
-
-          <Panel.Title>
-            HTTP Integration
-            <Button variant='ontime-subtle' size='sm' rightIcon={<IoAdd />} onClick={handleAddNewSubscription}>
-              New
-            </Button>
-          </Panel.Title>
-          {fields.length > 0 && (
-            <Panel.Table>
-              <thead>
-                <tr>
-                  <th>Enabled</th>
-                  <th>Cycle</th>
-                  <th className={style.fullWidth}>Message</th>
-                  <th />
-                </tr>
-              </thead>
-              <tbody>
-                {fields.map((integration, index) => {
-                  // @ts-expect-error -- not sure why it is not finding the type, it is ok
-                  const maybeError = errors.subscriptions?.[index]?.message?.message;
-                  return (
-                    <tr key={integration.id}>
-                      <td>
-                        <Switch variant='ontime' {...register(`subscriptions.${index}.enabled`)} />
-                      </td>
-                      <td className={style.autoWidth}>
-                        <Select
-                          size='sm'
-                          variant='ontime'
-                          className={style.fitContents}
-                          {...register(`subscriptions.${index}.cycle`)}
-                        >
-                          {cycles.map((cycle) => (
-                            <option key={cycle.id} value={cycle.value}>
-                              {cycle.label}
-                            </option>
-                          ))}
-                        </Select>
-                      </td>
-                      <td className={style.fullWidth}>
-                        <Input
-                          size='sm'
-                          variant='ontime-filled'
-                          autoComplete='off'
-                          placeholder='http://third-party/vt1/{{timer.current}}'
-                          {...register(`subscriptions.${index}.message`, {
-                            required: { value: true, message: 'Required field' },
-                            pattern: {
-                              value: startsWithHttp,
-                              message: 'HTTP messages should start with http://',
-                            },
-                          })}
-                        />
-                        {maybeError && <Panel.Error>{maybeError}</Panel.Error>}
-                      </td>
-                      <td>
-                        <IconButton
-                          size='sm'
-                          variant='ontime-ghosted'
-                          color='#FA5656' // $red-500
-                          icon={<IoTrash />}
-                          aria-label='Delete entry'
-                          onClick={() => handleDeleteSubscription(index)}
-                        />
-                      </td>
-                    </tr>
-                  );
-                })}
-              </tbody>
-            </Panel.Table>
-          )}
-        </Panel.Section>
-      </Panel.Card>
-    </Panel.Section>
-  );
-}
diff --git a/apps/client/src/features/app-settings/panel/integrations-panel/IntegrationsPanel.module.css b/apps/client/src/features/app-settings/panel/integrations-panel/IntegrationsPanel.module.css
deleted file mode 100644
index 606f7f934d..0000000000
--- a/apps/client/src/features/app-settings/panel/integrations-panel/IntegrationsPanel.module.css
+++ /dev/null
@@ -1,16 +0,0 @@
-.fullWidth {
-  width: 100%;
-}
-
-.halfWidth {
-  width: 50%;
-}
-
-.fitContents.fitContents {
-  width: max-content; /* override chakra */
-}
-
-.flex {
-  display: flex;
-  gap: 1rem;
-}
diff --git a/apps/client/src/features/app-settings/panel/integrations-panel/IntegrationsPanel.tsx b/apps/client/src/features/app-settings/panel/integrations-panel/IntegrationsPanel.tsx
deleted file mode 100644
index ac25cd7aae..0000000000
--- a/apps/client/src/features/app-settings/panel/integrations-panel/IntegrationsPanel.tsx
+++ /dev/null
@@ -1,42 +0,0 @@
-import { Alert, AlertDescription, AlertIcon } from '@chakra-ui/react';
-
-import ExternalLink from '../../../../common/components/external-link/ExternalLink';
-import useScrollIntoView from '../../../../common/hooks/useScrollIntoView';
-import type { PanelBaseProps } from '../../panel-list/PanelList';
-import * as Panel from '../../panel-utils/PanelUtils';
-
-import HttpIntegrations from './HttpIntegrations';
-import OscIntegrations from './OscIntegrations';
-
-const integrationDocsUrl = 'https://docs.getontime.no/api/integrations/';
-
-export default function IntegrationsPanel({ location }: PanelBaseProps) {
-  const oscRef = useScrollIntoView<HTMLDivElement>('osc', location);
-  const httpRef = useScrollIntoView<HTMLDivElement>('http', location);
-
-  return (
-    <>
-      <Panel.Header>Integration settings</Panel.Header>
-      <Panel.Section>
-        <Alert status='info' variant='ontime-on-dark-info'>
-          <AlertIcon />
-          <AlertDescription>
-            Integrations allow Ontime to receive commands or send its data to other systems in your workflow. <br />
-            <br />
-            Currently supported protocols are OSC (Open Sound Control), HTTP and Websockets. <br />
-            WebSockets are used for Ontime and cannot be configured independently. <br />
-            <ExternalLink href={integrationDocsUrl}>See the docs</ExternalLink>
-          </AlertDescription>
-        </Alert>
-      </Panel.Section>
-      <Panel.Section>
-        <div ref={oscRef}>
-          <OscIntegrations />
-        </div>
-        <div ref={httpRef}>
-          <HttpIntegrations />
-        </div>
-      </Panel.Section>
-    </>
-  );
-}
diff --git a/apps/client/src/features/app-settings/panel/integrations-panel/OscIntegrations.tsx b/apps/client/src/features/app-settings/panel/integrations-panel/OscIntegrations.tsx
deleted file mode 100644
index b235836859..0000000000
--- a/apps/client/src/features/app-settings/panel/integrations-panel/OscIntegrations.tsx
+++ /dev/null
@@ -1,310 +0,0 @@
-import { useEffect } from 'react';
-import { Controller, useFieldArray, useForm } from 'react-hook-form';
-import { Button, IconButton, Input, Select, Switch } from '@chakra-ui/react';
-import { IoAdd } from '@react-icons/all-files/io5/IoAdd';
-import { IoTrash } from '@react-icons/all-files/io5/IoTrash';
-import { OSCSettings } from 'ontime-types';
-import { generateId } from 'ontime-utils';
-
-import { maybeAxiosError } from '../../../../common/api/utils';
-import useOscSettings, { useOscSettingsMutation } from '../../../../common/hooks-query/useOscSettings';
-import { preventEscape } from '../../../../common/utils/keyEvent';
-import { isASCII, isASCIIorEmpty, isIPAddress, isOnlyNumbers, startsWithSlash } from '../../../../common/utils/regex';
-import { isOntimeCloud } from '../../../../externals';
-import * as Panel from '../../panel-utils/PanelUtils';
-
-import { cycles } from './integrationUtils';
-
-import style from './IntegrationsPanel.module.css';
-
-export default function OscIntegrations() {
-  const { data, status } = useOscSettings();
-  const { mutateAsync } = useOscSettingsMutation();
-
-  const {
-    control,
-    handleSubmit,
-    reset,
-    register,
-    setError,
-    formState: { errors, isSubmitting, isDirty, isValid },
-  } = useForm<OSCSettings>({
-    mode: 'onChange',
-    defaultValues: data,
-    values: data,
-    resetOptions: {
-      keepDirtyValues: true,
-    },
-  });
-
-  const { fields, prepend, remove } = useFieldArray({
-    name: 'subscriptions',
-    control,
-  });
-
-  // update form if we get new data from server
-  useEffect(() => {
-    if (data) {
-      reset(data);
-    }
-  }, [data, reset]);
-
-  const onSubmit = async (values: OSCSettings) => {
-    if (values.portIn === values.portOut) {
-      setError('portIn', { message: 'OSC IN and OUT Ports cant be the same' });
-      return;
-    }
-
-    const parsedValues = { ...values, portIn: Number(values.portIn), portOut: Number(values.portOut) };
-    try {
-      await mutateAsync(parsedValues);
-    } catch (error) {
-      setError('root', { message: maybeAxiosError(error) });
-    }
-  };
-
-  const handleAddNewSubscription = () => {
-    prepend({
-      id: generateId(),
-      cycle: 'onLoad',
-      address: '',
-      payload: '',
-      enabled: true,
-    });
-  };
-
-  const handleDeleteSubscription = (index: number) => {
-    remove(index);
-  };
-
-  const canSubmit = !isSubmitting && isDirty && isValid;
-  const isLoading = status === 'pending';
-
-  return (
-    <Panel.Card>
-      <Panel.SubHeader>
-        OSC settings
-        <div className={style.flex}>
-          <Button variant='ontime-ghosted' size='sm' onClick={() => reset()} isDisabled={!canSubmit}>
-            Revert to saved
-          </Button>
-          <Button
-            variant='ontime-filled'
-            size='sm'
-            type='submit'
-            form='osc-form'
-            isDisabled={!canSubmit}
-            isLoading={isSubmitting}
-          >
-            Save
-          </Button>
-        </div>
-      </Panel.SubHeader>
-      {isOntimeCloud && (
-        <Panel.Highlight>For security reasons OSC integrations are not available in the cloud service.</Panel.Highlight>
-      )}
-
-      <Panel.Divider />
-
-      <Panel.Section as='form' id='osc-form' onSubmit={handleSubmit(onSubmit)} onKeyDown={preventEscape}>
-        <Panel.Loader isLoading={isLoading} />
-        <Panel.Title>General OSC settings</Panel.Title>
-        {errors?.root && <Panel.Error>{errors.root.message}</Panel.Error>}
-        <Panel.ListGroup>
-          <Panel.ListItem>
-            <Panel.Field title='OSC input' description='Allow control of Ontime through OSC' />
-            <Controller
-              control={control}
-              name='enabledIn'
-              render={({ field: { onChange, value, ref } }) => (
-                <Switch variant='ontime' size='lg' isChecked={value} onChange={onChange} ref={ref} />
-              )}
-            />
-          </Panel.ListItem>
-          <Panel.ListItem>
-            <Panel.Field
-              title='Listen on port'
-              description='Port for incoming OSC. Default: 8888'
-              error={errors.portIn?.message}
-            />
-            <Input
-              id='portIn'
-              placeholder='8888'
-              width='5rem'
-              maxLength={5}
-              size='sm'
-              textAlign='right'
-              variant='ontime-filled'
-              type='number'
-              autoComplete='off'
-              {...register('portIn', {
-                required: { value: true, message: 'Required field' },
-                max: { value: 65535, message: 'Port must be within range 1024 - 65535' },
-                min: { value: 1024, message: 'Port must be within range 1024 - 65535' },
-                pattern: {
-                  value: isOnlyNumbers,
-                  message: 'Value should be numeric',
-                },
-              })}
-            />
-          </Panel.ListItem>
-        </Panel.ListGroup>
-        <Panel.ListGroup>
-          <Panel.ListItem>
-            <Panel.Field title='OSC output' description='Provide feedback from Ontime with OSC' />
-            <Controller
-              control={control}
-              name='enabledOut'
-              render={({ field: { onChange, value, ref } }) => (
-                <Switch variant='ontime' size='lg' isChecked={value} onChange={onChange} ref={ref} />
-              )}
-            />
-          </Panel.ListItem>
-          <Panel.ListItem>
-            <Panel.Field
-              title='OSC target IP'
-              description='IP address Ontime will send OSC messages to'
-              error={errors.targetIP?.message}
-            />
-            <Input
-              id='targetIP'
-              placeholder='127.0.0.1'
-              width='9rem'
-              size='sm'
-              textAlign='right'
-              variant='ontime-filled'
-              autoComplete='off'
-              {...register('targetIP', {
-                required: { value: true, message: 'Required field' },
-                pattern: {
-                  value: isIPAddress,
-                  message: 'Invalid IP address',
-                },
-              })}
-            />
-          </Panel.ListItem>
-          <Panel.ListItem>
-            <Panel.Field
-              title='OSC target port'
-              description='Port number Ontime will send OSC messages to'
-              error={errors.portOut?.message}
-            />
-            <Input
-              id='portOut'
-              placeholder='8888'
-              width='75px'
-              size='sm'
-              textAlign='right'
-              variant='ontime-filled'
-              autoComplete='off'
-              {...register('portOut', {
-                required: { value: true, message: 'Required field' },
-                max: { value: 65535, message: 'Port must be within range 1024 - 65535' },
-                min: { value: 1024, message: 'Port must be within range 1024 - 65535' },
-                pattern: {
-                  value: isOnlyNumbers,
-                  message: 'Value should be numeric',
-                },
-              })}
-            />
-          </Panel.ListItem>
-        </Panel.ListGroup>
-
-        <Panel.Divider />
-
-        <Panel.Title>
-          OSC integrations
-          <Button variant='ontime-subtle' size='sm' rightIcon={<IoAdd />} onClick={handleAddNewSubscription}>
-            Add
-          </Button>
-        </Panel.Title>
-
-        {fields.length > 0 && (
-          <Panel.Table>
-            <thead>
-              <tr>
-                <th>Enabled</th>
-                <th>Cycle</th>
-                <th className={style.halfWidth}>Address</th>
-                <th className={style.halfWidth}>Arguments</th>
-                <th />
-              </tr>
-            </thead>
-            <tbody>
-              {fields.map((field, index) => {
-                const maybeAddressError = errors.subscriptions?.[index]?.address?.message;
-                const maybePayloadError = errors.subscriptions?.[index]?.payload?.message;
-                return (
-                  <tr key={field.id}>
-                    <td>
-                      <Switch variant='ontime' {...register(`subscriptions.${index}.enabled`)} />
-                    </td>
-                    <td className={style.autoWidth}>
-                      <Select
-                        size='sm'
-                        variant='ontime'
-                        className={style.fitContents}
-                        {...register(`subscriptions.${index}.cycle`)}
-                      >
-                        {cycles.map((cycle) => (
-                          <option key={cycle.id} value={cycle.value}>
-                            {cycle.label}
-                          </option>
-                        ))}
-                      </Select>
-                    </td>
-                    <td className={style.halfWidth}>
-                      <Input
-                        key={field.id}
-                        size='sm'
-                        variant='ontime-filled'
-                        autoComplete='off'
-                        placeholder='/from-ontime/'
-                        {...register(`subscriptions.${index}.address`, {
-                          required: { value: true, message: 'Required field' },
-                          validate: {
-                            oscStartsWithSlash: (value) =>
-                              startsWithSlash.test(value) || 'OSC address should start with a forward slash',
-                            oscStringIsAscii: (value) =>
-                              isASCII.test(value) || 'OSC address only allow ASCII characters',
-                          },
-                        })}
-                      />
-                      {maybeAddressError && <Panel.Error>{maybeAddressError}</Panel.Error>}
-                    </td>
-                    <td className={style.halfWidth}>
-                      <Input
-                        key={field.id}
-                        size='sm'
-                        variant='ontime-filled'
-                        autoComplete='off'
-                        placeholder='{{timer.current}}'
-                        {...register(`subscriptions.${index}.payload`, {
-                          validate: {
-                            oscStringIsAscii: (value) =>
-                              isASCIIorEmpty.test(value) || 'OSC arguments only allow ASCII characters',
-                          },
-                        })}
-                      />
-                      {maybePayloadError && <Panel.Error>{maybePayloadError}</Panel.Error>}
-                    </td>
-                    <td>
-                      <IconButton
-                        size='sm'
-                        variant='ontime-ghosted'
-                        color='#FA5656' // $red-500
-                        icon={<IoTrash />}
-                        aria-label='Delete entry'
-                        onClick={() => handleDeleteSubscription(index)}
-                      />
-                    </td>
-                  </tr>
-                );
-              })}
-            </tbody>
-          </Panel.Table>
-        )}
-      </Panel.Section>
-    </Panel.Card>
-  );
-}
diff --git a/apps/client/src/features/app-settings/panel/integrations-panel/integrationUtils.ts b/apps/client/src/features/app-settings/panel/integrations-panel/integrationUtils.ts
deleted file mode 100644
index 1f0456cfa8..0000000000
--- a/apps/client/src/features/app-settings/panel/integrations-panel/integrationUtils.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import { TimerLifeCycle } from 'ontime-types';
-
-type CycleLabel = {
-  id: number;
-  label: string;
-  value: keyof typeof TimerLifeCycle;
-};
-
-export const cycles: CycleLabel[] = [
-  { id: 1, label: 'On Load', value: 'onLoad' },
-  { id: 2, label: 'On Start', value: 'onStart' },
-  { id: 3, label: 'On Pause', value: 'onPause' },
-  { id: 4, label: 'On Stop', value: 'onStop' },
-  { id: 5, label: 'Every second', value: 'onClock' },
-  { id: 5, label: 'On Timer Update', value: 'onUpdate' },
-  { id: 6, label: 'On Finish', value: 'onFinish' },
-  { id: 7, label: 'On Warning', value: 'onWarning' },
-  { id: 8, label: 'On Danger', value: 'onDanger' },
-];
diff --git a/apps/client/src/features/app-settings/useAppSettingsMenu.tsx b/apps/client/src/features/app-settings/useAppSettingsMenu.tsx
index 5faebdbae9..75350d65ff 100644
--- a/apps/client/src/features/app-settings/useAppSettingsMenu.tsx
+++ b/apps/client/src/features/app-settings/useAppSettingsMenu.tsx
@@ -46,14 +46,6 @@ const staticOptions = [
     ],
     split: true,
   },
-  {
-    id: 'integrations',
-    label: 'Integrations',
-    secondary: [
-      { id: 'integrations__osc', label: 'OSC settings' },
-      { id: 'integrations__http', label: 'HTTP settings' },
-    ],
-  },
   {
     id: 'automation',
     label: 'Automation',
diff --git a/apps/electron/src/main.js b/apps/electron/src/main.js
index f200ac7e33..ae6a0e1de8 100644
--- a/apps/electron/src/main.js
+++ b/apps/electron/src/main.js
@@ -47,15 +47,12 @@ async function startBackend() {
   }
 
   const ontimeServer = require(nodePath);
-  const { initAssets, startServer, startIntegrations } = ontimeServer;
+  const { initAssets, startServer } = ontimeServer;
 
   await initAssets();
 
   const result = await startServer(escalateError);
   loaded = result.message;
-
-  await startIntegrations();
-
   return result.serverPort;
 }
 
diff --git a/apps/server/src/api-data/automation/automation.parser.ts b/apps/server/src/api-data/automation/automation.parser.ts
index c3d007da92..54e881f18c 100644
--- a/apps/server/src/api-data/automation/automation.parser.ts
+++ b/apps/server/src/api-data/automation/automation.parser.ts
@@ -4,10 +4,35 @@ import { dbModel } from '../../models/dataModel.js';
 import type { ErrorEmitter } from '../../utils/parser.js';
 
 export function parseAutomationSettings(data: Partial<DatabaseModel>, emitError?: ErrorEmitter): AutomationSettings {
+  /**
+   * Leaving a path for migrating users to the new automations
+   * This should be removed after a few releases
+   */
+  // @ts-expect-error -- these are legacy keys that may exist in a file <= 3.9.5
+  if (data.http || data.osc) {
+    emitError?.('Found legacy integrations');
+    console.log('Found legacy integrations...');
+    // @ts-expect-error -- these are legacy keys that may exist in a file <= 3.9.5
+    if (data.osc) {
+      return {
+        enabledAutomations: dbModel.automation.enabledAutomations,
+        // @ts-expect-error -- these are legacy keys that may exist in a file <= 3.9.5
+        enabledOscIn: data.osc?.enabledIn ?? dbModel.automation.enabledOscIn,
+        // @ts-expect-error -- these are legacy keys that may exist in a file <= 3.9.5
+        oscPortIn: data.osc?.portIn ?? dbModel.automation.oscPortIn,
+        automations: [],
+        blueprints: {},
+      };
+    } else {
+      return { ...dbModel.automation };
+    }
+  }
+
   if (!data.automation) {
     emitError?.('No data found to import');
     return { ...dbModel.automation };
   }
+  console.log('Found Automation settings, importing...');
 
   return {
     enabledAutomations: data.automation.enabledAutomations ?? dbModel.automation.enabledAutomations,
diff --git a/apps/server/src/api-data/http/http.controller.ts b/apps/server/src/api-data/http/http.controller.ts
deleted file mode 100644
index 5812743122..0000000000
--- a/apps/server/src/api-data/http/http.controller.ts
+++ /dev/null
@@ -1,31 +0,0 @@
-import type { ErrorResponse, HttpSettings } from 'ontime-types';
-import { getErrorMessage } from 'ontime-utils';
-
-import type { Request, Response } from 'express';
-
-import { failEmptyObjects } from '../../utils/routerUtils.js';
-import { httpIntegration } from '../../services/integration-service/HttpIntegration.js';
-import { getDataProvider } from '../../classes/data-provider/DataProvider.js';
-
-export async function getHTTP(_req: Request, res: Response<HttpSettings>) {
-  const http = getDataProvider().getHttp();
-  res.status(200).send(http);
-}
-
-export async function postHTTP(req: Request, res: Response<HttpSettings | ErrorResponse>) {
-  if (failEmptyObjects(req.body, res)) {
-    return;
-  }
-
-  try {
-    const httpSettings = req.body;
-
-    httpIntegration.init(httpSettings);
-    // we persist the data after init to avoid persisting invalid data
-    const result = await getDataProvider().setHttp(httpSettings);
-    res.send(result).status(200);
-  } catch (error) {
-    const message = getErrorMessage(error);
-    res.status(400).send({ message });
-  }
-}
diff --git a/apps/server/src/api-data/http/http.router.ts b/apps/server/src/api-data/http/http.router.ts
deleted file mode 100644
index 8e9fb645ad..0000000000
--- a/apps/server/src/api-data/http/http.router.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import express from 'express';
-
-import { validateHTTP } from './http.validation.js';
-import { getHTTP, postHTTP } from './http.controller.js';
-
-export const router = express.Router();
-
-router.get('/', getHTTP);
-router.post('/', validateHTTP, postHTTP);
diff --git a/apps/server/src/api-data/http/http.validation.ts b/apps/server/src/api-data/http/http.validation.ts
deleted file mode 100644
index 0acd9b4340..0000000000
--- a/apps/server/src/api-data/http/http.validation.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import { body, validationResult } from 'express-validator';
-import { Request, Response, NextFunction } from 'express';
-
-import { sanitiseHttpSubscriptions } from '../../utils/parserFunctions.js';
-
-/**
- * @description Validates object for POST /ontime/http
- */
-export const validateHTTP = [
-  body('enabledOut').exists().isBoolean(),
-  body('subscriptions')
-    .exists()
-    .isArray()
-    .custom((value) => sanitiseHttpSubscriptions(value)),
-
-  (req: Request, res: Response, next: NextFunction) => {
-    const errors = validationResult(req);
-    if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });
-    next();
-  },
-];
diff --git a/apps/server/src/api-data/index.ts b/apps/server/src/api-data/index.ts
index 9024aaff5e..d7211b9096 100644
--- a/apps/server/src/api-data/index.ts
+++ b/apps/server/src/api-data/index.ts
@@ -4,8 +4,6 @@ import { router as automationsRouter } from './automation/automation.router.js';
 import { router as urlPresetsRouter } from './url-presets/urlPresets.router.js';
 import { router as customFieldsRouter } from './custom-fields/customFields.router.js';
 import { router as dbRouter } from './db/db.router.js';
-import { router as httpRouter } from './http/http.router.js';
-import { router as oscRouter } from './osc/osc.router.js';
 import { router as projectRouter } from './project/project.router.js';
 import { router as rundownRouter } from './rundown/rundown.router.js';
 import { router as settingsRouter } from './settings/settings.router.js';
@@ -19,8 +17,6 @@ export const appRouter = express.Router();
 appRouter.use('/automations', automationsRouter);
 appRouter.use('/custom-fields', customFieldsRouter);
 appRouter.use('/db', dbRouter);
-appRouter.use('/http', httpRouter);
-appRouter.use('/osc', oscRouter);
 appRouter.use('/project', projectRouter);
 appRouter.use('/rundown', rundownRouter);
 appRouter.use('/settings', settingsRouter);
diff --git a/apps/server/src/api-data/osc/osc.controller.ts b/apps/server/src/api-data/osc/osc.controller.ts
deleted file mode 100644
index 9c1a23139d..0000000000
--- a/apps/server/src/api-data/osc/osc.controller.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-import type { ErrorResponse, OSCSettings } from 'ontime-types';
-import { getErrorMessage } from 'ontime-utils';
-
-import type { Request, Response } from 'express';
-
-import { failEmptyObjects } from '../../utils/routerUtils.js';
-import { oscIntegration } from '../../services/integration-service/OscIntegration.js';
-import { getDataProvider } from '../../classes/data-provider/DataProvider.js';
-
-export async function getOSC(_req: Request, res: Response<OSCSettings>) {
-  const osc = getDataProvider().getOsc();
-  res.status(200).send(osc);
-}
-
-export async function postOSC(req: Request, res: Response<OSCSettings | ErrorResponse>) {
-  if (failEmptyObjects(req.body, res)) {
-    return;
-  }
-
-  try {
-    const oscSettings = req.body;
-
-    oscIntegration.init(oscSettings);
-    // we persist the data after init to avoid persisting invalid data
-    const result = await getDataProvider().setOsc(oscSettings);
-
-    res.send(result).status(200);
-  } catch (error) {
-    const message = getErrorMessage(error);
-    res.status(400).send({ message });
-  }
-}
diff --git a/apps/server/src/api-data/osc/osc.router.ts b/apps/server/src/api-data/osc/osc.router.ts
deleted file mode 100644
index 7ff46413b6..0000000000
--- a/apps/server/src/api-data/osc/osc.router.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import express from 'express';
-import { getOSC, postOSC } from './osc.controller.js';
-import { validateOSC } from './osc.validation.js';
-
-export const router = express.Router();
-
-router.get('/', getOSC);
-router.post('/', validateOSC, postOSC);
diff --git a/apps/server/src/api-data/osc/osc.validation.ts b/apps/server/src/api-data/osc/osc.validation.ts
deleted file mode 100644
index 72ebdc973d..0000000000
--- a/apps/server/src/api-data/osc/osc.validation.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-import { body, validationResult } from 'express-validator';
-import { Request, Response, NextFunction } from 'express';
-
-import { sanitiseOscSubscriptions } from '../../utils/parserFunctions.js';
-
-/**
- * @description Validates object for POST /ontime/osc
- */
-export const validateOSC = [
-  body('portIn').exists().isPort(),
-  body('portOut').exists().isPort(),
-  body('targetIP').exists().isIP(),
-  body('enabledIn').exists().isBoolean(),
-  body('enabledOut').exists().isBoolean(),
-  body('subscriptions')
-    .exists()
-    .isArray()
-    .custom((value) => sanitiseOscSubscriptions(value)),
-
-  (req: Request, res: Response, next: NextFunction) => {
-    const errors = validationResult(req);
-    if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });
-    next();
-  },
-];
diff --git a/apps/server/src/api-data/session/session.service.ts b/apps/server/src/api-data/session/session.service.ts
index 7fbee53c35..75af229a67 100644
--- a/apps/server/src/api-data/session/session.service.ts
+++ b/apps/server/src/api-data/session/session.service.ts
@@ -33,7 +33,6 @@ export async function getSessionStats(): Promise<SessionStats> {
  */
 export async function getInfo(): Promise<GetInfo> {
   const { version, serverPort } = getDataProvider().getSettings();
-  const osc = getDataProvider().getOsc();
 
   // get nif and inject localhost
   const ni = getNetworkInterfaces();
@@ -43,7 +42,6 @@ export async function getInfo(): Promise<GetInfo> {
     networkInterfaces: ni,
     version,
     serverPort,
-    osc,
     publicDir: publicDir.root,
   };
 }
diff --git a/apps/server/src/app.ts b/apps/server/src/app.ts
index 233e2f5471..957f1488b8 100644
--- a/apps/server/src/app.ts
+++ b/apps/server/src/app.ts
@@ -10,7 +10,7 @@ import { extname } from 'node:path';
 
 // import utils
 import { publicDir, srcDir, srcFiles } from './setup/index.js';
-import { environment, isOntimeCloud, isProduction, updateRouterPrefix } from './externals.js';
+import { environment, isProduction, updateRouterPrefix } from './externals.js';
 import { ONTIME_VERSION } from './ONTIME_VERSION.js';
 import { consoleSuccess, consoleHighlight, consoleError } from './utils/console.js';
 
@@ -23,10 +23,7 @@ import { socket } from './adapters/WebsocketAdapter.js';
 import { getDataProvider } from './classes/data-provider/DataProvider.js';
 
 // Services
-import { integrationService } from './services/integration-service/IntegrationService.js';
 import { logger } from './classes/Logger.js';
-import { oscIntegration } from './services/integration-service/OscIntegration.js';
-import { httpIntegration } from './services/integration-service/HttpIntegration.js';
 import { populateStyles } from './setup/loadStyles.js';
 import { eventStore } from './stores/EventStore.js';
 import { runtimeService } from './services/runtime-service/RuntimeService.js';
@@ -146,7 +143,6 @@ enum OntimeStartOrder {
   Error,
   InitAssets,
   InitServer,
-  InitIO,
 }
 
 let step = OntimeStartOrder.InitAssets;
@@ -155,7 +151,7 @@ let expressServer: Server | null = null;
 const checkStart = (currentState: OntimeStartOrder) => {
   if (step !== currentState) {
     step = OntimeStartOrder.Error;
-    throw new Error('Init order error: initAssets > startServer > startOsc > startIntegrations');
+    throw new Error('Init order error: initAssets > startServer');
   } else {
     if (step === 1 || step === 2) {
       step = step + 1;
@@ -249,41 +245,6 @@ export const startServer = async (
   };
 };
 
-/**
- * starts integrations
- */
-export const startIntegrations = async () => {
-  checkStart(OntimeStartOrder.InitIO);
-
-  // if a config is not provided, we use the persisted one
-  const { osc, http } = getDataProvider().getData();
-
-  if (http) {
-    logger.info(LogOrigin.Tx, 'Initialising HTTP Integration...');
-    try {
-      httpIntegration.init(http);
-      integrationService.register(httpIntegration);
-    } catch (error) {
-      logger.error(LogOrigin.Tx, `HTTP Integration initialisation failed: ${error}`);
-    }
-  }
-
-  if (isOntimeCloud) {
-    logger.info(LogOrigin.Tx, 'Skipping OSC in Cloud environment...');
-    return;
-  }
-
-  if (osc) {
-    logger.info(LogOrigin.Tx, 'Initialising OSC Integration...');
-    try {
-      oscIntegration.init(osc);
-      integrationService.register(oscIntegration);
-    } catch (error) {
-      logger.error(LogOrigin.Tx, 'OSC Integration initialisation failed');
-    }
-  }
-};
-
 /**
  * @description clean shutdown app services
  * @param {number} exitCode
@@ -303,7 +264,6 @@ export const shutdown = async (exitCode = 0) => {
 
   expressServer?.close();
   runtimeService.shutdown();
-  integrationService.shutdown();
   logger.shutdown();
   socket.shutdown();
   process.exit(exitCode);
diff --git a/apps/server/src/index.ts b/apps/server/src/index.ts
index fcb9eb8a25..b4170864ae 100644
--- a/apps/server/src/index.ts
+++ b/apps/server/src/index.ts
@@ -1,6 +1,6 @@
 /* eslint-disable no-console */
 import { consoleHighlight, consoleError } from './utils/console.js';
-import { initAssets, startIntegrations, startServer } from './app.js';
+import { initAssets, startServer } from './app.js';
 
 async function startOntime() {
   try {
@@ -11,10 +11,6 @@ async function startOntime() {
     console.log('\n');
     consoleHighlight('Request: Start server...');
     await startServer();
-
-    console.log('\n');
-    consoleHighlight('Request: Start integrations...');
-    await startIntegrations();
   } catch (error) {
     consoleError(`Request failed: ${error}`);
   }
diff --git a/apps/server/src/models/dataModel.ts b/apps/server/src/models/dataModel.ts
index cdf19ada3b..ccd6fb03e6 100644
--- a/apps/server/src/models/dataModel.ts
+++ b/apps/server/src/models/dataModel.ts
@@ -31,18 +31,6 @@ export const dbModel: DatabaseModel = {
   },
   urlPresets: [],
   customFields: {},
-  osc: {
-    portIn: 8888,
-    portOut: 9999,
-    targetIP: '127.0.0.1',
-    enabledIn: false,
-    enabledOut: false,
-    subscriptions: [],
-  },
-  http: {
-    enabledOut: false,
-    subscriptions: [],
-  },
   automation: {
     enabledAutomations: true,
     enabledOscIn: true,
diff --git a/apps/server/src/services/integration-service/HttpIntegration.ts b/apps/server/src/services/integration-service/HttpIntegration.ts
deleted file mode 100644
index 5b7c83a313..0000000000
--- a/apps/server/src/services/integration-service/HttpIntegration.ts
+++ /dev/null
@@ -1,80 +0,0 @@
-import got from 'got';
-
-import { HttpSettings, HttpSubscription, LogOrigin } from 'ontime-types';
-
-import IIntegration, { TimerLifeCycleKey } from './IIntegration.js';
-import { parseTemplateNested } from './integrationUtils.js';
-import { logger } from '../../classes/Logger.js';
-
-/**
- * @description Class contains logic towards outgoing HTTP communications
- * @class
- */
-export class HttpIntegration implements IIntegration<HttpSubscription, HttpSettings> {
-  subscriptions: HttpSubscription[];
-  enabled: boolean;
-
-  constructor() {
-    this.subscriptions = [];
-    this.enabled = false;
-  }
-
-  /**
-   * Initializes httpClient
-   */
-  init(config: HttpSettings) {
-    const { subscriptions, enabledOut } = config;
-    this.initSubscriptions(subscriptions);
-    this.enabled = enabledOut;
-  }
-
-  initSubscriptions(subscriptions: HttpSubscription[]) {
-    this.subscriptions = subscriptions;
-  }
-
-  dispatch(action: TimerLifeCycleKey, state?: object) {
-    // noop
-    if (!this.enabled) {
-      return;
-    }
-
-    for (let i = 0; i < this.subscriptions.length; i++) {
-      const { cycle, message, enabled } = this.subscriptions[i];
-      if (cycle !== action || !enabled || !message) {
-        continue;
-      }
-
-      const parsedMessage = parseTemplateNested(message, state || {});
-      this.emit(parsedMessage);
-    }
-  }
-
-  emit(path: string) {
-    got.get(path, { retry: { limit: 0 } }).catch((err) => {
-      logger.warning(LogOrigin.Tx, `HTTP Integration: ${err.message}`);
-
-      if (err.code === 'ECONNREFUSED') {
-        logger.warning(LogOrigin.Tx, `HTTP Integration: '${err.code}' The server refused the connection`);
-        return;
-      }
-
-      if (err.code === 'ENOTFOUND') {
-        logger.warning(LogOrigin.Tx, `HTTP Integration: '${err.code}' DNS lookup failed`);
-        return;
-      }
-
-      if (err.code === 'ETIMEDOUT') {
-        logger.warning(LogOrigin.Tx, `HTTP Integration: '${err.code}' The connection timed out`);
-        return;
-      }
-
-      logger.warning(LogOrigin.Tx, `HTTP Integration: ${err.code}`);
-    });
-  }
-
-  shutdown() {
-    /** shutdown is a no-op here*/
-  }
-}
-
-export const httpIntegration = new HttpIntegration();
diff --git a/apps/server/src/services/integration-service/IIntegration.ts b/apps/server/src/services/integration-service/IIntegration.ts
deleted file mode 100644
index 9a5ea24da3..0000000000
--- a/apps/server/src/services/integration-service/IIntegration.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import { TimerLifeCycle } from 'ontime-types';
-
-export type TimerLifeCycleKey = keyof typeof TimerLifeCycle;
-
-export default interface IIntegration<T, C> {
-  subscriptions: T[];
-  init: (config: C) => void;
-  dispatch: (action: TimerLifeCycleKey, state?: object) => void;
-  emit: (...args: never[]) => unknown;
-  shutdown: () => void;
-}
diff --git a/apps/server/src/services/integration-service/IntegrationService.ts b/apps/server/src/services/integration-service/IntegrationService.ts
deleted file mode 100644
index 4c8e59086b..0000000000
--- a/apps/server/src/services/integration-service/IntegrationService.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-import { LogOrigin } from 'ontime-types';
-
-import IIntegration, { TimerLifeCycleKey } from './IIntegration.js';
-import { eventStore } from '../../stores/EventStore.js';
-import { logger } from '../../classes/Logger.js';
-
-class IntegrationService {
-  private integrations: IIntegration<unknown, unknown>[];
-
-  constructor() {
-    this.integrations = [];
-  }
-
-  register(integrationService: IIntegration<unknown, unknown>) {
-    this.integrations.push(integrationService);
-  }
-
-  unregister(integrationService: IIntegration<unknown, unknown>) {
-    this.integrations = this.integrations.filter((int) => int !== integrationService);
-  }
-
-  dispatch(action: TimerLifeCycleKey) {
-    const state = eventStore.poll();
-    this.integrations.forEach((integration) => {
-      integration.dispatch(action, state);
-    });
-  }
-
-  shutdown() {
-    logger.info(LogOrigin.Tx, 'Shutdown Integrations');
-    this.integrations.forEach((integration) => {
-      integration.shutdown();
-    });
-  }
-}
-
-export const integrationService = new IntegrationService();
diff --git a/apps/server/src/services/integration-service/OscIntegration.ts b/apps/server/src/services/integration-service/OscIntegration.ts
deleted file mode 100644
index 8e5ae5c674..0000000000
--- a/apps/server/src/services/integration-service/OscIntegration.ts
+++ /dev/null
@@ -1,147 +0,0 @@
-import { ArgumentType, Client, Message } from 'node-osc';
-import { LogOrigin, MaybeNumber, MaybeString, OSCSettings, OscSubscription } from 'ontime-types';
-
-import IIntegration, { TimerLifeCycleKey } from './IIntegration.js';
-import { parseTemplateNested } from './integrationUtils.js';
-import { logger } from '../../classes/Logger.js';
-import { OscServer } from '../../adapters/OscAdapter.js';
-import { stringToOSCArgs } from '../../utils/oscArgParser.js';
-
-/**
- * @description Class contains logic towards outgoing OSC communications
- * @class
- */
-export class OscIntegration implements IIntegration<OscSubscription, OSCSettings> {
-  protected oscClient: null | Client;
-  protected oscServer: OscServer | null = null;
-
-  subscriptions: OscSubscription[];
-  targetIP: MaybeString;
-  portOut: MaybeNumber;
-  portIn: MaybeNumber;
-  enabledOut: boolean;
-  enabledIn: boolean;
-
-  constructor() {
-    this.oscClient = null;
-    this.subscriptions = [];
-    this.targetIP = null;
-    this.portOut = null;
-    this.portIn = null;
-    this.enabledOut = false;
-    this.enabledIn = false;
-  }
-
-  /**
-   * Initializes oscClient
-   */
-  init(config: OSCSettings) {
-    const { targetIP, portOut, subscriptions, enabledOut, enabledIn, portIn } = config;
-
-    this.initTX(enabledOut, targetIP, portOut, subscriptions);
-    this.initRX(enabledIn, portIn);
-    // return `OSC integration client connected to ${targetIP}:${portOut}`;
-  }
-
-  private initSubscriptions(subscriptions: OscSubscription[]) {
-    this.subscriptions = subscriptions;
-  }
-
-  dispatch(action: TimerLifeCycleKey, state?: object) {
-    // noop
-    if (!this.oscClient || !this.enabledOut) {
-      return;
-    }
-
-    for (let i = 0; i < this.subscriptions.length; i++) {
-      const { cycle, address, payload, enabled } = this.subscriptions[i];
-      if (cycle !== action || !enabled || !address) {
-        continue;
-      }
-      const parsedAddress = parseTemplateNested(address, state || {});
-      const parsedPayload = payload ? parseTemplateNested(payload, state || {}) : undefined;
-      const parsedArguments = stringToOSCArgs(parsedPayload);
-
-      try {
-        this.emit(parsedAddress, parsedArguments);
-      } catch (error) {
-        logger.error(LogOrigin.Tx, `OSC Integration: ${error}`);
-      }
-    }
-  }
-
-  emit(address: string, args: ArgumentType[]) {
-    if (!this.oscClient) {
-      return;
-    }
-
-    //TODO: Look into using bundles
-    const message = new Message(address);
-    message.append(args);
-
-    this.oscClient.send(message);
-  }
-
-  private initTX(enabledOut: boolean, targetIP: string, portOut: number, subscriptions: OscSubscription[]) {
-    this.initSubscriptions(subscriptions);
-
-    if (!enabledOut) {
-      this.targetIP = targetIP;
-      this.portOut = portOut;
-      this.enabledOut = enabledOut;
-      this.shutdownTX();
-      return;
-    }
-
-    if (this.oscClient && targetIP === this.targetIP && portOut === this.portOut) {
-      // nothing changed that would mean we need a new client
-      return;
-    }
-
-    this.targetIP = targetIP;
-    this.portOut = portOut;
-    this.enabledOut = enabledOut;
-
-    try {
-      this.oscClient = new Client(targetIP, portOut);
-      logger.info(LogOrigin.Tx, `Starting OSC Clint on port: ${portOut}`);
-    } catch (error) {
-      this.oscClient = null;
-      throw new Error(`Failed initialising OSC client: ${error}`);
-    }
-  }
-
-  private initRX(enabledIn: boolean, portIn: number) {
-    if (!enabledIn) {
-      this.shutdownRX();
-      return;
-    }
-
-    // Start OSC Server
-    logger.info(LogOrigin.Rx, `Starting OSC Server on port: ${portIn}`);
-    this.oscServer = new OscServer(portIn);
-  }
-
-  shutdown() {
-    this.shutdownTX();
-    this.shutdownRX();
-  }
-
-  private shutdownTX() {
-    if (this.oscClient) {
-      logger.info(LogOrigin.Tx, 'Shutting down OSC integration');
-      this.oscClient?.close();
-      this.oscClient = null;
-    }
-  }
-
-  private shutdownRX() {
-    if (this.oscServer) {
-      logger.info(LogOrigin.Rx, 'Shutting down OSC integration');
-      this.oscServer?.shutdown();
-      this.oscServer = null;
-    }
-  }
-}
-
-export const oscIntegration = new OscIntegration();
diff --git a/apps/server/src/services/integration-service/integrationUtils.test.ts b/apps/server/src/services/integration-service/integrationUtils.test.ts
deleted file mode 100644
index 3203a53490..0000000000
--- a/apps/server/src/services/integration-service/integrationUtils.test.ts
+++ /dev/null
@@ -1,169 +0,0 @@
-import { stringToOSCArgs } from '../../utils/oscArgParser.js';
-import { parseTemplateNested } from './integrationUtils.js';
-
-describe('parseTemplateNested()', () => {
-  it('parses string with a single-level variable name', () => {
-    const store = { timer: 10 };
-    const templateString = '/test/{{timer}}';
-    const result = parseTemplateNested(templateString, store);
-    expect(result).toEqual('/test/10');
-  });
-
-  it('parses string with a nested variable name', () => {
-    const store = { timer: { clock: 10 } };
-    const templateString = '/timer/{{timer.clock}}';
-    const result = parseTemplateNested(templateString, store);
-    expect(result).toEqual('/timer/10');
-  });
-
-  it('parses string with multiple variables', () => {
-    const mockState = { test1: 'that', test2: 'this' };
-    const testString = '{{test1}} should replace {{test2}}';
-    const expected = `${mockState.test1} should replace ${mockState.test2}`;
-
-    const result = parseTemplateNested(testString, mockState);
-    expect(result).toStrictEqual(expected);
-  });
-
-  it('correctly parses a string without templates', () => {
-    const testString = 'That should replace {test}';
-
-    const result = parseTemplateNested(testString, {});
-    expect(result).toStrictEqual(testString);
-  });
-
-  it('handles scenarios with missing variables', () => {
-    // by failing to provide a value, we give visibility to
-    // potential issues in the given string
-    const mockState = { test1: 'that', test2: 'this' };
-    const testString = '{{test1}} should replace {{test2}}, but not {{test3}}';
-    const expected = `${mockState.test1} should replace ${mockState.test2}, but not {{test3}}`;
-
-    const result = parseTemplateNested(testString, mockState);
-    expect(result).toStrictEqual(expected);
-  });
-});
-
-describe('parseNestedTemplate() -> resolveAliasData()', () => {
-  it('resolves data through callback', () => {
-    const data = {
-      not: {
-        so: {
-          easy: '3',
-        },
-      },
-    };
-    const aliases = {
-      easy: { key: 'not.so.easy', cb: (value: string) => `testing-${value}` },
-    };
-
-    const easyParse = parseTemplateNested('{{human.easy}}', data, aliases);
-    expect(easyParse).toBe('testing-3');
-  });
-  it('handles a mixed operation', () => {
-    const data = {
-      not: {
-        so: {
-          easy: '3',
-        },
-      },
-      other: {
-        value: 42,
-      },
-    };
-    const aliases = {
-      easy: { key: 'not.so.easy', cb: (value: string) => `testing-${value}` },
-    };
-
-    const easyParse = parseTemplateNested('{{other.value}} to {{human.easy}}', data, aliases);
-    expect(easyParse).toBe('42 to testing-3');
-  });
-  it('returns given key when not found', () => {
-    const data = {
-      not: {
-        so: {
-          easy: '3',
-        },
-      },
-      other: {
-        value: 5,
-      },
-    };
-    const aliases = {
-      easy: { key: 'not.so.easy', cb: (value: string) => `testing-${value}` },
-    };
-
-    const easyParse = parseTemplateNested('{{other.value}} to {{human.easy}} {{human.not.found}}', data, aliases);
-    expect(easyParse).toBe('5 to testing-3 {{human.not.found}}');
-  });
-});
-
-describe('parseNestedTemplate() -> stringToOSCArgs()', () => {
-  it('specific osc requirements', () => {
-    const data = {
-      not: {
-        so: {
-          easy: 'data with space',
-          empty: '',
-          number: 1234,
-          stringNumber: '1234',
-        },
-      },
-    };
-
-    const payloads = [
-      {
-        test: '"string with space and {{not.so.easy}}"',
-        expect: [{ type: 'string', value: 'string with space and data with space' }],
-      },
-      {
-        test: '',
-        expect: [],
-      },
-      {
-        test: ' ',
-        expect: [],
-      },
-      {
-        test: '""',
-        expect: [{ type: 'string', value: '' }],
-      },
-      {
-        test: '"string with space and {{not.so.empty}}"',
-        expect: [{ type: 'string', value: 'string with space and ' }],
-      },
-      {
-        test: '"string with space and {{not.so.number}}"',
-        expect: [{ type: 'string', value: 'string with space and 1234' }],
-      },
-      {
-        test: '"string with space and {{not.so.stringNumber}}"',
-        expect: [{ type: 'string', value: 'string with space and 1234' }],
-      },
-      {
-        test: '"{{not.so.easy}}" 1',
-        expect: [
-          { type: 'string', value: 'data with space' },
-          { type: 'integer', value: 1 },
-        ],
-      },
-      {
-        test: '"{{not.so.empty}}" 1',
-        expect: [
-          { type: 'string', value: '' },
-          { type: 'integer', value: 1 },
-        ],
-      },
-      {
-        test: '',
-        expect: [],
-      },
-    ];
-
-    payloads.forEach((payload) => {
-      const parsedPayload = parseTemplateNested(payload.test, data);
-      const parsedArguments = stringToOSCArgs(parsedPayload);
-      expect(parsedArguments).toStrictEqual(payload.expect);
-    });
-  });
-});
diff --git a/apps/server/src/services/integration-service/integrationUtils.ts b/apps/server/src/services/integration-service/integrationUtils.ts
deleted file mode 100644
index eee5c44ba9..0000000000
--- a/apps/server/src/services/integration-service/integrationUtils.ts
+++ /dev/null
@@ -1,73 +0,0 @@
-import { MaybeNumber } from 'ontime-types';
-import { millisToString, removeLeadingZero } from 'ontime-utils';
-
-// any value inside double curly braces {{val}}
-const placeholderRegex = /{{(.*?)}}/g;
-
-function formatDisplayFromString(value: string, hideZero = false): string {
-  let valueInNumber: MaybeNumber = null;
-
-  if (value !== 'null') {
-    const parsedValue = Number(value);
-    if (!Number.isNaN(parsedValue)) {
-      valueInNumber = parsedValue;
-    }
-  }
-  let formatted = millisToString(valueInNumber, { fallback: hideZero ? '00:00' : '00:00:00' });
-  if (hideZero) {
-    formatted = removeLeadingZero(formatted);
-  }
-  return formatted;
-}
-
-type AliasesDefinition = Record<string, { key: string; cb: (value: string) => string }>;
-const quickAliases: AliasesDefinition = {
-  clock: { key: 'clock', cb: (value: string) => formatDisplayFromString(value) },
-  duration: { key: 'timer.duration', cb: (value: string) => formatDisplayFromString(value, true) },
-  expectedEnd: {
-    key: 'timer.expectedFinish',
-    cb: (value: string) => formatDisplayFromString(value),
-  },
-  runningTimer: {
-    key: 'timer.current',
-    cb: (value: string) => formatDisplayFromString(value, true),
-  },
-  elapsedTime: {
-    key: 'timer.elapsed',
-    cb: (value: string) => formatDisplayFromString(value, true),
-  },
-  startedAt: { key: 'timer.startedAt', cb: (value: string) => formatDisplayFromString(value) },
-};
-
-/**
- * Parses a templated string to values in a nested object
- */
-export function parseTemplateNested(template: string, state: object, humanReadable = quickAliases): string {
-  let parsedTemplate = template;
-  const matches = Array.from(parsedTemplate.matchAll(placeholderRegex));
-
-  for (const match of matches) {
-    const variableName = match[1];
-    const variableParts = variableName.split('.');
-    let value: string | undefined = undefined;
-
-    if (variableParts[0] === 'human') {
-      const lookupKey = variableParts[1];
-      if (lookupKey in humanReadable) {
-        const newTemplate = `{{${humanReadable[lookupKey].key}}}`;
-        const parsed = parseTemplateNested(newTemplate, state, humanReadable);
-        value = humanReadable[lookupKey].cb(parsed);
-      } else {
-        value = undefined;
-      }
-    } else {
-      // iterate through variable parts, and look for the property in the state object
-      value = variableParts.reduce((obj, key) => obj?.[key], state);
-    }
-    if (value !== undefined) {
-      parsedTemplate = parsedTemplate.replace(match[0], value);
-    }
-  }
-
-  return parsedTemplate;
-}
diff --git a/apps/server/src/services/project-service/ProjectService.ts b/apps/server/src/services/project-service/ProjectService.ts
index 6cc13d9474..6df369401d 100644
--- a/apps/server/src/services/project-service/ProjectService.ts
+++ b/apps/server/src/services/project-service/ProjectService.ts
@@ -28,8 +28,6 @@ import {
   setLastLoadedProject,
 } from '../app-state-service/AppStateService.js';
 import { runtimeService } from '../runtime-service/RuntimeService.js';
-import { oscIntegration } from '../integration-service/OscIntegration.js';
-import { httpIntegration } from '../integration-service/HttpIntegration.js';
 
 import {
   copyCorruptFile,
@@ -176,14 +174,10 @@ export async function loadProjectFile(name: string) {
   // apply data model
   runtimeService.stop();
 
-  const { rundown, customFields, osc, http } = result.data;
+  const { rundown, customFields } = result.data;
 
   // apply the rundown
   await initRundown(rundown, customFields);
-
-  // apply integrations
-  oscIntegration.init(osc);
-  httpIntegration.init(http);
 }
 
 /**
@@ -250,14 +244,10 @@ export async function renameProjectFile(originalFile: string, newFilename: strin
     // apply data model
     runtimeService.stop();
 
-    const { rundown, customFields, osc, http } = result.data;
+    const { rundown, customFields } = result.data;
 
     // apply the rundown
     await initRundown(rundown, customFields);
-
-    // apply integrations
-    oscIntegration.init(osc);
-    httpIntegration.init(http);
   }
 }
 
diff --git a/apps/server/src/services/runtime-service/RuntimeService.ts b/apps/server/src/services/runtime-service/RuntimeService.ts
index 7674e82d31..c4422b54e4 100644
--- a/apps/server/src/services/runtime-service/RuntimeService.ts
+++ b/apps/server/src/services/runtime-service/RuntimeService.ts
@@ -32,7 +32,6 @@ import {
   getRundown,
   getTimedEvents,
 } from '../rundown-service/rundownUtils.js';
-import { integrationService } from '../integration-service/IntegrationService.js';
 
 import { getForceUpdate, getShouldClockUpdate, getShouldTimerUpdate } from './rundownService.utils.js';
 import { skippedOutOfEvent } from '../timerUtils.js';
diff --git a/apps/server/src/utils/__tests__/parser.test.ts b/apps/server/src/utils/__tests__/parser.test.ts
index 779d9e400d..5a13b0646c 100644
--- a/apps/server/src/utils/__tests__/parser.test.ts
+++ b/apps/server/src/utils/__tests__/parser.test.ts
@@ -314,7 +314,7 @@ describe('test parser edge cases', () => {
     //@ts-expect-error -- we know this is wrong, testing imports outside domain
     const { data, errors } = parseDatabaseModel(testData);
     expect(data.rundown.length).toBe(1);
-    expect(errors.length).toBe(7);
+    expect(errors.length).toBe(5);
   });
 
   it('handles incomplete datasets', () => {
@@ -724,8 +724,6 @@ describe('test import of v2 datamodel', () => {
     );
     // @ts-expect-error -- checking if the field is removed
     expect(parsed?.userFields).toBeUndefined();
-    expect(parsed.osc).toMatchObject({ subscriptions: [] });
-    expect(parsed.http).toMatchObject({ enabledOut: false, subscriptions: [] });
   });
 });
 
diff --git a/apps/server/src/utils/__tests__/parserFunctions.test.ts b/apps/server/src/utils/__tests__/parserFunctions.test.ts
index 12d69454e5..eface0ea1a 100644
--- a/apps/server/src/utils/__tests__/parserFunctions.test.ts
+++ b/apps/server/src/utils/__tests__/parserFunctions.test.ts
@@ -2,12 +2,8 @@ import {
   CustomFields,
   DatabaseModel,
   EndAction,
-  HttpSettings,
-  HttpSubscription,
-  OSCSettings,
   OntimeEvent,
   OntimeRundown,
-  OscSubscription,
   Settings,
   SupportedEvent,
   TimeStrategy,
@@ -17,16 +13,12 @@ import {
 
 import {
   parseCustomFields,
-  parseHttp,
-  parseOsc,
   parseProject,
   parseRundown,
   parseSettings,
   parseUrlPresets,
   parseViewSettings,
   sanitiseCustomFields,
-  sanitiseHttpSubscriptions,
-  sanitiseOscSubscriptions,
 } from '../parserFunctions.js';
 
 describe('parseRundown()', () => {
@@ -111,66 +103,6 @@ describe('parseViewSettings()', () => {
   });
 });
 
-describe('parseOsc()', () => {
-  it('returns an a base model if nothing is given', () => {
-    const errorEmitter = vi.fn();
-    const result = parseOsc({}, errorEmitter);
-    expect(result).toBeTypeOf('object');
-    expect(errorEmitter).toHaveBeenCalledOnce();
-  });
-
-  it('parses data, skipping invalid results', () => {
-    const errorEmitter = vi.fn();
-    const osc = {
-      subscriptions: [
-        { id: '1', cycle: 'onLoad', address: '/test', payload: 'test', enabled: true }, // OK
-        {}, // no data
-        { id: '2', cycle: 'onStart', payload: 'test', enabled: true }, // no address
-      ],
-    } as OSCSettings;
-    const result = parseOsc({ osc }, errorEmitter);
-    expect(result.subscriptions.length).toEqual(1);
-    expect(result.subscriptions.at(0)).toMatchObject({
-      id: '1',
-      cycle: 'onLoad',
-      address: '/test',
-      payload: 'test',
-      enabled: true,
-    });
-    expect(errorEmitter).toHaveBeenCalled();
-  });
-});
-
-describe('parseHttp()', () => {
-  it('returns an a base model if nothing is given', () => {
-    const errorEmitter = vi.fn();
-    const result = parseHttp({}, errorEmitter);
-    expect(result).toBeTypeOf('object');
-    expect(errorEmitter).toHaveBeenCalledOnce();
-  });
-
-  it('parses data, skipping invalid results', () => {
-    const errorEmitter = vi.fn();
-    const http = {
-      subscriptions: [
-        { id: '1', cycle: 'onLoad', message: 'http://', enabled: true }, // OK
-        {}, // no data
-        { id: '2', cycle: 'onStart', enabled: true }, // no message
-        { id: '3', cycle: 'onLoad', message: '/test', enabled: true }, // doesnt start with http
-      ],
-    } as HttpSettings;
-    const result = parseHttp({ http }, errorEmitter);
-    expect(result.subscriptions.length).toEqual(1);
-    expect(result.subscriptions.at(0)).toMatchObject({
-      id: '1',
-      cycle: 'onLoad',
-      message: 'http://',
-      enabled: true,
-    });
-    expect(errorEmitter).toHaveBeenCalled();
-  });
-});
-
 describe('parseUrlPresets()', () => {
   it('returns an a base model if nothing is given', () => {
     const errorEmitter = vi.fn();
@@ -223,81 +155,6 @@ describe('parseCustomFields()', () => {
   });
 });
 
-describe('sanitiseOscSubscriptions()', () => {
-  it('throws if not an array an empty array if not an array', () => {
-    expect(() => sanitiseOscSubscriptions(undefined)).toThrow();
-    // @ts-expect-error -- data is external, we check bad types
-    expect(() => sanitiseOscSubscriptions({})).toThrow();
-    expect(() => sanitiseOscSubscriptions(null)).toThrow();
-  });
-
-  it('returns an array of valid entries', () => {
-    const oscSubscriptions: OscSubscription[] = [
-      { id: '1', cycle: 'onLoad', address: '/test', payload: 'test', enabled: true },
-      { id: '2', cycle: 'onStart', address: '/test', payload: 'test', enabled: false },
-      { id: '3', cycle: 'onPause', address: '/test', payload: 'test', enabled: true },
-      { id: '4', cycle: 'onStop', address: '/test', payload: 'test', enabled: false },
-      { id: '5', cycle: 'onUpdate', address: '/test', payload: 'test', enabled: true },
-      { id: '6', cycle: 'onFinish', address: '/test', payload: 'test', enabled: false },
-      { id: '7', cycle: 'onWarning', address: '/test', payload: 'test', enabled: false },
-      { id: '8', cycle: 'onDanger', address: '/test', payload: 'test', enabled: false },
-    ];
-    const sanitationResult = sanitiseOscSubscriptions(oscSubscriptions);
-    expect(sanitationResult).toStrictEqual(oscSubscriptions);
-  });
-
-  it('filters invalid entries', () => {
-    const oscSubscriptions = [
-      { id: '1', cycle: 'onLoad', address: 4, payload: 'test', enabled: true },
-      { cycle: 'onLoad', payload: 'test', enabled: true },
-      { id: '2', cycle: 'unknown', payload: 'test', enabled: false },
-      { id: '3', payload: 'test', enabled: true },
-      { id: '4', cycle: 'onStop', enabled: false },
-      { id: '5', cycle: 'onUpdate', payload: 'test' },
-      { id: '6', cycle: 'onFinish', payload: 'test', enabled: 'true' },
-    ] as OscSubscription[];
-    const sanitationResult = sanitiseOscSubscriptions(oscSubscriptions);
-    expect(sanitationResult.length).toBe(0);
-  });
-});
-
-describe('sanitiseHttpSubscriptions()', () => {
-  it('throws if the data is unexpected', () => {
-    expect(() => sanitiseHttpSubscriptions(undefined)).toThrow();
-    // @ts-expect-error -- data is external, we check bad types
-    expect(() => sanitiseHttpSubscriptions({})).toThrow();
-    expect(() => sanitiseHttpSubscriptions(null)).toThrow();
-  });
-
-  it('returns an array of valid entries', () => {
-    const httpSubscription: HttpSubscription[] = [
-      { id: '1', cycle: 'onLoad', message: 'http://test', enabled: true },
-      { id: '2', cycle: 'onStart', message: 'http://test', enabled: false },
-      { id: '3', cycle: 'onPause', message: 'http://test', enabled: true },
-      { id: '4', cycle: 'onStop', message: 'http://test', enabled: false },
-      { id: '5', cycle: 'onUpdate', message: 'http://test', enabled: true },
-      { id: '6', cycle: 'onFinish', message: 'http://test', enabled: false },
-      { id: '7', cycle: 'onWarning', message: 'http://test', enabled: false },
-      { id: '8', cycle: 'onDanger', message: 'http://test', enabled: false },
-    ];
-    const sanitationResult = sanitiseHttpSubscriptions(httpSubscription);
-    expect(sanitationResult).toStrictEqual(httpSubscription);
-  });
-
-  it('filters invalid entries', () => {
-    const httpSubscription = [
-      { cycle: 'onLoad', message: 'http://test', enabled: true },
-      { id: '2', cycle: 'unknown', message: 'http://test', enabled: false },
-      { id: '3', message: 'http://test', enabled: true },
-      { id: '4', cycle: 'onStop', enabled: false },
-      { id: '5', cycle: 'onUpdate', message: 'http://test' },
-      { id: '6', cycle: 'onFinish', message: 'ftp://test', enabled: 'true' },
-    ];
-    const sanitationResult = sanitiseHttpSubscriptions(httpSubscription as HttpSubscription[]);
-    expect(sanitationResult.length).toBe(0);
-  });
-});
-
 describe('sanitiseCustomFields()', () => {
   it('returns an empty array if not an array', () => {
     expect(sanitiseCustomFields({})).toEqual({});
diff --git a/apps/server/src/utils/parser.ts b/apps/server/src/utils/parser.ts
index 53a4729fb3..55f97aeb49 100644
--- a/apps/server/src/utils/parser.ts
+++ b/apps/server/src/utils/parser.ts
@@ -27,15 +27,7 @@ import { logger } from '../classes/Logger.js';
 import { event as eventDef } from '../models/eventsDefinition.js';
 
 import { makeString } from './parserUtils.js';
-import {
-  parseHttp,
-  parseOsc,
-  parseProject,
-  parseRundown,
-  parseSettings,
-  parseUrlPresets,
-  parseViewSettings,
-} from './parserFunctions.js';
+import { parseProject, parseRundown, parseSettings, parseUrlPresets, parseViewSettings } from './parserFunctions.js';
 import { parseExcelDate } from './time.js';
 
 export type ErrorEmitter = (message: string) => void;
@@ -334,8 +326,6 @@ export function parseDatabaseModel(jsonData: Partial<DatabaseModel>): { data: Da
     viewSettings: parseViewSettings(jsonData, makeEmitError('View Settings')),
     urlPresets: parseUrlPresets(jsonData, makeEmitError('URL Presets')),
     customFields,
-    osc: parseOsc(jsonData, makeEmitError('OSC')),
-    http: parseHttp(jsonData, makeEmitError('HTTP')),
     automation: parseAutomationSettings(jsonData),
   };
 
diff --git a/apps/server/src/utils/parserFunctions.ts b/apps/server/src/utils/parserFunctions.ts
index 0dcbab54da..34253e9b4f 100644
--- a/apps/server/src/utils/parserFunctions.ts
+++ b/apps/server/src/utils/parserFunctions.ts
@@ -2,25 +2,20 @@ import {
   CustomField,
   CustomFields,
   DatabaseModel,
-  HttpSettings,
-  HttpSubscription,
-  OSCSettings,
   OntimeBlock,
   OntimeDelay,
   OntimeEvent,
   OntimeRundown,
-  OscSubscription,
   ProjectData,
   Settings,
   TimerType,
   URLPreset,
   ViewSettings,
   isOntimeBlock,
-  isOntimeCycle,
   isOntimeDelay,
   isOntimeEvent,
 } from 'ontime-types';
-import { customFieldLabelToKey, generateId, getErrorMessage, isAlphanumericWithSpace } from 'ontime-utils';
+import { customFieldLabelToKey, generateId, isAlphanumericWithSpace } from 'ontime-utils';
 
 import { dbModel } from '../models/dataModel.js';
 import { block as blockDef, delay as delayDef } from '../models/eventsDefinition.js';
@@ -165,102 +160,6 @@ export function parseViewSettings(data: Partial<DatabaseModel>, emitError?: Erro
   };
 }
 
-/**
- * Sanitises an OSC Subscriptions array
- */
-export function sanitiseOscSubscriptions(subscriptions?: OscSubscription[]): OscSubscription[] {
-  if (!Array.isArray(subscriptions)) {
-    throw new Error('ERROR: invalid OSC subscriptions');
-  }
-
-  return subscriptions.filter(
-    ({ id, cycle, address, payload, enabled }) =>
-      typeof id === 'string' &&
-      isOntimeCycle(cycle) &&
-      typeof address === 'string' &&
-      typeof payload === 'string' &&
-      typeof enabled === 'boolean',
-  );
-}
-
-/**
- * Parse osc portion of an entry
- */
-export function parseOsc(data: Partial<DatabaseModel>, emitError?: ErrorEmitter): OSCSettings {
-  if (!data.osc) {
-    emitError?.('No data found to import');
-    return { ...dbModel.osc };
-  }
-
-  console.log('Found OSC settings, importing...');
-
-  let newSubscriptions: OscSubscription[] = [];
-  try {
-    newSubscriptions = sanitiseOscSubscriptions(data.osc.subscriptions);
-  } catch (error) {
-    emitError?.(getErrorMessage(error));
-  }
-
-  if (newSubscriptions.length !== data.osc.subscriptions.length) {
-    emitError?.('Skipped invalid subscriptions');
-  }
-
-  return {
-    portIn: data.osc.portIn ?? dbModel.osc.portIn,
-    portOut: data.osc.portOut ?? dbModel.osc.portOut,
-    targetIP: data.osc.targetIP ?? dbModel.osc.targetIP,
-    enabledIn: data.osc.enabledIn ?? dbModel.osc.enabledIn,
-    enabledOut: data.osc.enabledOut ?? dbModel.osc.enabledOut,
-    subscriptions: newSubscriptions,
-  };
-}
-
-/**
- * Sanitises an HTTP Subscriptions array
- */
-export function sanitiseHttpSubscriptions(subscriptions?: HttpSubscription[]): HttpSubscription[] {
-  if (!Array.isArray(subscriptions)) {
-    throw new Error('ERROR: invalid HTTP subscriptions');
-  }
-
-  return subscriptions.filter(
-    ({ id, cycle, message, enabled }) =>
-      typeof id === 'string' &&
-      isOntimeCycle(cycle) &&
-      typeof message === 'string' &&
-      message.startsWith('http://') &&
-      typeof enabled === 'boolean',
-  );
-}
-
-/**
- * Parse Http portion of an entry
- */
-export function parseHttp(data: Partial<DatabaseModel>, emitError?: ErrorEmitter): HttpSettings {
-  if (!data.http) {
-    emitError?.('No data found to import');
-    return { ...dbModel.http };
-  }
-
-  console.log('Found HTTP settings, importing...');
-
-  let newSubscriptions: HttpSubscription[] = [];
-  try {
-    newSubscriptions = sanitiseHttpSubscriptions(data.http.subscriptions);
-  } catch (error) {
-    emitError?.(getErrorMessage(error));
-  }
-
-  if (newSubscriptions.length !== data.http?.subscriptions.length) {
-    emitError?.('Skipped invalid subscriptions');
-  }
-
-  return {
-    enabledOut: data.http.enabledOut ?? dbModel.http.enabledOut,
-    subscriptions: newSubscriptions,
-  };
-}
-
 /**
  * Parse URL preset portion of an entry
  */
diff --git a/packages/types/src/api/ontime-controller/BackendResponse.type.ts b/packages/types/src/api/ontime-controller/BackendResponse.type.ts
index d81dd8827d..961a09b06e 100644
--- a/packages/types/src/api/ontime-controller/BackendResponse.type.ts
+++ b/packages/types/src/api/ontime-controller/BackendResponse.type.ts
@@ -1,4 +1,3 @@
-import type { OSCSettings } from '../../definitions/core/OscSettings.type.js';
 import type { OntimeRundown } from '../../definitions/core/Rundown.type.js';
 import type { Playback } from '../../definitions/runtime/Playback.type.js';
 import type { MaybeString } from '../../utils/utils.type.js';
@@ -22,7 +21,6 @@ export interface GetInfo {
   networkInterfaces: NetworkInterface[];
   version: string;
   serverPort: number;
-  osc: OSCSettings;
   publicDir: string;
 }
 
diff --git a/packages/types/src/definitions/DataModel.type.ts b/packages/types/src/definitions/DataModel.type.ts
index 63ecbc98e8..0f8d318789 100644
--- a/packages/types/src/definitions/DataModel.type.ts
+++ b/packages/types/src/definitions/DataModel.type.ts
@@ -1,9 +1,7 @@
 import type {
   AutomationSettings,
   CustomFields,
-  HttpSettings,
   OntimeRundown,
-  OSCSettings,
   ProjectData,
   Settings,
   URLPreset,
@@ -17,7 +15,5 @@ export type DatabaseModel = {
   viewSettings: ViewSettings;
   urlPresets: URLPreset[];
   customFields: CustomFields;
-  osc: OSCSettings;
-  http: HttpSettings;
   automation: AutomationSettings;
 };
diff --git a/packages/types/src/definitions/core/HttpSettings.type.ts b/packages/types/src/definitions/core/HttpSettings.type.ts
deleted file mode 100644
index 0c3dfc92db..0000000000
--- a/packages/types/src/definitions/core/HttpSettings.type.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import type { TimerLifeCycleKey } from './TimerLifecycle.type.js';
-
-export type HttpSubscription = { id: string; cycle: TimerLifeCycleKey; message: string; enabled: boolean };
-
-export interface HttpSettings {
-  enabledOut: boolean;
-  subscriptions: HttpSubscription[];
-}
diff --git a/packages/types/src/definitions/core/OscSettings.type.ts b/packages/types/src/definitions/core/OscSettings.type.ts
deleted file mode 100644
index c006d65f1e..0000000000
--- a/packages/types/src/definitions/core/OscSettings.type.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import type { TimerLifeCycleKey } from './TimerLifecycle.type.js';
-
-export type OscSubscription = {
-  id: string;
-  cycle: TimerLifeCycleKey;
-  address: string;
-  payload: string; // TODO: we should be using arguments to keep in line with protocol language
-  enabled: boolean;
-};
-
-export interface OSCSettings {
-  portIn: number;
-  portOut: number;
-  targetIP: string;
-  enabledIn: boolean;
-  enabledOut: boolean;
-  subscriptions: OscSubscription[];
-}
diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts
index 0c1237114c..b84273b9e5 100644
--- a/packages/types/src/index.ts
+++ b/packages/types/src/index.ts
@@ -52,10 +52,6 @@ export type {
   EventCustomFields,
 } from './definitions/core/CustomFields.type.js';
 
-// ---> Integration, Subscription
-export type { OSCSettings, OscSubscription } from './definitions/core/OscSettings.type.js';
-export type { HttpSettings, HttpSubscription } from './definitions/core/HttpSettings.type.js';
-
 // SERVER RESPONSES
 export type {
   AuthenticationStatus,