diff --git a/src/Pages/ShowEpisodeDetails.vue b/src/Pages/ShowEpisodeDetails.vue
index 376ad295f710e250eed18256b5294430344f98ab..7c13a6b271071fe1772ec9d6a8224ae0671ffa16 100644
--- a/src/Pages/ShowEpisodeDetails.vue
+++ b/src/Pages/ShowEpisodeDetails.vue
@@ -1,6 +1,23 @@
 <template>
   <div>
-    <PageHeader :lead="show.name" :title="title" :editing-metadata="episode" />
+    <PageHeader :lead="show.name" :title="title" :editing-metadata="episode">
+      <APermissionGuard show-permissions="program.delete_episode">
+        <ConfirmEpisodeDelete v-slot="{ resolve }">
+          <AConfirmDialog
+            :title="t('episode.deletion.title')"
+            :confirm-label="t('episode.deletion.confirmLabel')"
+            @confirm="resolve(true)"
+            @cancel="resolve(false)"
+          >
+            <p>{{ t('episode.deletion.description') }}</p>
+          </AConfirmDialog>
+        </ConfirmEpisodeDelete>
+
+        <button type="button" class="btn btn-danger" @click="deleteEpisode">
+          {{ t('episode.deletion.title') }}
+        </button>
+      </APermissionGuard>
+    </PageHeader>
 
     <div
       class="tw-grid tw-grid-cols-1 lg:tw-grid-cols-2 xl:tw-grid-cols-10 tw-items-start tw-gap-6 tw-max-w-[1200px]"
@@ -82,8 +99,9 @@ import { ensureDate, useObjectListFromStore } from '@/util'
 import ASpinnerLabel from '@/components/generic/ASpinnerLabel.vue'
 import { useMediaFactory } from '@/stores/media-manager'
 import FormGroup from '@/components/generic/FormGroup.vue'
-import { useTextareaAutosize } from '@vueuse/core'
+import { createTemplatePromise, useTextareaAutosize } from '@vueuse/core'
 import { useAPIObjectFieldCopy } from '@/form'
+import AConfirmDialog from '@/components/generic/AConfirmDialog.vue'
 
 const props = defineProps<{
   show: Show
@@ -115,6 +133,13 @@ const timeslotData = computed(() => {
   })
 })
 
+const ConfirmEpisodeDelete = createTemplatePromise<boolean>()
+
+async function deleteEpisode() {
+  if (!(await ConfirmEpisodeDelete.start())) return
+  await episodeStore.remove(episode.value.id)
+}
+
 const mediaDescription = useAPIObjectFieldCopy(episodeStore, episode, 'mediaDescription', {
   debounce: 2,
 })
diff --git a/src/i18n/de.js b/src/i18n/de.js
index e29354f2032666022a5fa8c00a41942855abfa97..37a580099aea077942e85db96cda7decd19175f6 100644
--- a/src/i18n/de.js
+++ b/src/i18n/de.js
@@ -93,6 +93,11 @@ export default {
       createNew: 'Neue Sendung anlegen',
       perPage: 'Sendungen pro Seite',
     },
+    deletion: {
+      title: 'Sendung löschen',
+      description: 'Bist du sicher, dass du diese Sendung löschen willst?',
+      confirmLabel: 'Ja, Sendung löschen',
+    },
     assignment: {
       clear: 'Zuweisung aufheben',
       clearDescription:
diff --git a/src/i18n/en.js b/src/i18n/en.js
index 74b48a5757c9c19a6d27c3eeac0e72d58ca360b6..c1515a39b26f50375bf14a536cafcebdd8cbf57a 100644
--- a/src/i18n/en.js
+++ b/src/i18n/en.js
@@ -92,6 +92,11 @@ export default {
       createNew: 'Create new episode',
       perPage: 'Episodes per page',
     },
+    deletion: {
+      title: 'Delete episode',
+      description: 'Are you sure you want to delete this episode?',
+      confirmLabel: 'Yes, delete episode',
+    },
     assignment: {
       clear: 'Clear assignment',
       clearDescription: