diff --git a/src-ui/messages.xlf b/src-ui/messages.xlf
index fe15461a7..6b908d900 100644
--- a/src-ui/messages.xlf
+++ b/src-ui/messages.xlf
@@ -1736,7 +1736,7 @@
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
-          <context context-type="linenumber">83</context>
+          <context context-type="linenumber">87</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
@@ -3543,7 +3543,7 @@
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
-          <context context-type="linenumber">79</context>
+          <context context-type="linenumber">83</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
@@ -4101,15 +4101,15 @@
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/system-status-dialog/system-status-dialog.component.html</context>
-          <context context-type="linenumber">165</context>
+          <context context-type="linenumber">175</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/system-status-dialog/system-status-dialog.component.html</context>
-          <context context-type="linenumber">189</context>
+          <context context-type="linenumber">209</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/system-status-dialog/system-status-dialog.component.html</context>
-          <context context-type="linenumber">213</context>
+          <context context-type="linenumber">243</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/toast/toast.component.html</context>
@@ -4396,7 +4396,7 @@
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
-          <context context-type="linenumber">125</context>
+          <context context-type="linenumber">129</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/profile-edit-dialog/profile-edit-dialog.component.html</context>
@@ -4992,11 +4992,18 @@
           <context context-type="linenumber">72</context>
         </context-group>
       </trans-unit>
+      <trans-unit id="235571817610183244" datatype="html">
+        <source>Web UI</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
+          <context context-type="linenumber">76</context>
+        </context-group>
+      </trans-unit>
       <trans-unit id="3553216189604488439" datatype="html">
         <source>Modified</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
-          <context context-type="linenumber">87</context>
+          <context context-type="linenumber">91</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/data/document.ts</context>
@@ -5007,70 +5014,70 @@
         <source>Custom Field</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
-          <context context-type="linenumber">91</context>
+          <context context-type="linenumber">95</context>
         </context-group>
       </trans-unit>
       <trans-unit id="8696908693776094667" datatype="html">
         <source>Consumption Started</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
-          <context context-type="linenumber">98</context>
+          <context context-type="linenumber">102</context>
         </context-group>
       </trans-unit>
       <trans-unit id="7858311467093621703" datatype="html">
         <source>Document Added</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
-          <context context-type="linenumber">102</context>
+          <context context-type="linenumber">106</context>
         </context-group>
       </trans-unit>
       <trans-unit id="7955486237346046731" datatype="html">
         <source>Document Updated</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
-          <context context-type="linenumber">106</context>
+          <context context-type="linenumber">110</context>
         </context-group>
       </trans-unit>
       <trans-unit id="9172233176401579786" datatype="html">
         <source>Scheduled</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
-          <context context-type="linenumber">110</context>
+          <context context-type="linenumber">114</context>
         </context-group>
       </trans-unit>
       <trans-unit id="5502398334173581061" datatype="html">
         <source>Assignment</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
-          <context context-type="linenumber">117</context>
+          <context context-type="linenumber">121</context>
         </context-group>
       </trans-unit>
       <trans-unit id="6234812824772766804" datatype="html">
         <source>Removal</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
-          <context context-type="linenumber">121</context>
+          <context context-type="linenumber">125</context>
         </context-group>
       </trans-unit>
       <trans-unit id="4206419737792796794" datatype="html">
         <source>Webhook</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
-          <context context-type="linenumber">129</context>
+          <context context-type="linenumber">133</context>
         </context-group>
       </trans-unit>
       <trans-unit id="3138206142174978019" datatype="html">
         <source>Create new workflow</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
-          <context context-type="linenumber">225</context>
+          <context context-type="linenumber">229</context>
         </context-group>
       </trans-unit>
       <trans-unit id="5996779210524133604" datatype="html">
         <source>Edit workflow</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
-          <context context-type="linenumber">229</context>
+          <context context-type="linenumber">233</context>
         </context-group>
       </trans-unit>
       <trans-unit id="6381578200008167206" datatype="html">
@@ -5560,7 +5567,7 @@
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/system-status-dialog/system-status-dialog.component.html</context>
-          <context context-type="linenumber">231</context>
+          <context context-type="linenumber">261</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/manage/mail/mail.component.html</context>
@@ -6014,39 +6021,54 @@
           <context context-type="linenumber">146</context>
         </context-group>
       </trans-unit>
+      <trans-unit id="9127131074422113272" datatype="html">
+        <source>Run Task</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/components/common/system-status-dialog/system-status-dialog.component.html</context>
+          <context context-type="linenumber">166</context>
+        </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/components/common/system-status-dialog/system-status-dialog.component.html</context>
+          <context context-type="linenumber">200</context>
+        </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/components/common/system-status-dialog/system-status-dialog.component.html</context>
+          <context context-type="linenumber">234</context>
+        </context-group>
+      </trans-unit>
       <trans-unit id="4089509911694721896" datatype="html">
         <source>Last Updated</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/system-status-dialog/system-status-dialog.component.html</context>
-          <context context-type="linenumber">163</context>
+          <context context-type="linenumber">173</context>
         </context-group>
       </trans-unit>
       <trans-unit id="46628344485199198" datatype="html">
         <source>Classifier</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/system-status-dialog/system-status-dialog.component.html</context>
-          <context context-type="linenumber">168</context>
+          <context context-type="linenumber">178</context>
         </context-group>
       </trans-unit>
       <trans-unit id="6096684179126491743" datatype="html">
         <source>Last Trained</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/system-status-dialog/system-status-dialog.component.html</context>
-          <context context-type="linenumber">187</context>
+          <context context-type="linenumber">207</context>
         </context-group>
       </trans-unit>
       <trans-unit id="6427836860962380759" datatype="html">
         <source>Sanity Checker</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/system-status-dialog/system-status-dialog.component.html</context>
-          <context context-type="linenumber">192</context>
+          <context context-type="linenumber">212</context>
         </context-group>
       </trans-unit>
       <trans-unit id="6578747070254776938" datatype="html">
         <source>Last Run</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/system-status-dialog/system-status-dialog.component.html</context>
-          <context context-type="linenumber">211</context>
+          <context context-type="linenumber">241</context>
         </context-group>
       </trans-unit>
       <trans-unit id="6732151329960766506" datatype="html">
@@ -9692,28 +9714,28 @@
         <source>Connecting...</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/services/upload-documents.service.ts</context>
-          <context context-type="linenumber">42</context>
+          <context context-type="linenumber">43</context>
         </context-group>
       </trans-unit>
       <trans-unit id="1245343823699368872" datatype="html">
         <source>Uploading...</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/services/upload-documents.service.ts</context>
-          <context context-type="linenumber">54</context>
+          <context context-type="linenumber">55</context>
         </context-group>
       </trans-unit>
       <trans-unit id="7446520539098045935" datatype="html">
         <source>Upload complete, waiting...</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/services/upload-documents.service.ts</context>
-          <context context-type="linenumber">57</context>
+          <context context-type="linenumber">58</context>
         </context-group>
       </trans-unit>
       <trans-unit id="1405142710727603568" datatype="html">
         <source>HTTP error: <x id="PH" equiv-text="error.status"/> <x id="PH_1" equiv-text="error.statusText"/></source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/services/upload-documents.service.ts</context>
-          <context context-type="linenumber">70</context>
+          <context context-type="linenumber">71</context>
         </context-group>
       </trans-unit>
       <trans-unit id="2119857572761283468" datatype="html">
diff --git a/src-ui/src/app/components/common/system-status-dialog/system-status-dialog.component.html b/src-ui/src/app/components/common/system-status-dialog/system-status-dialog.component.html
index c87f80f43..df3b6940d 100644
--- a/src-ui/src/app/components/common/system-status-dialog/system-status-dialog.component.html
+++ b/src-ui/src/app/components/common/system-status-dialog/system-status-dialog.component.html
@@ -144,7 +144,7 @@
           <div class="card-body">
             <dl class="card-text">
               <dt i18n>Search Index</dt>
-              <dd>
+              <dd class="d-flex align-items-center">
                 <div class="badge text-uppercase bg-info text-dark" [ngbPopover]="indexStatus" triggers="mouseenter:mouseleave">
                   {{status.tasks.index_status}}
                   @if (status.tasks.index_status === 'OK') {
@@ -157,6 +157,16 @@
                     <i-bs name="exclamation-triangle-fill" class="text-danger ms-2 lh-1"></i-bs>
                   }
                 </div>
+                @if (currentUserIsSuperUser) {
+                  @if (isRunning(PaperlessTaskName.IndexOptimize)) {
+                    <div class="spinner-border spinner-border-sm ms-2" role="status"></div>
+                  } @else {
+                    <div class="badge cursor-pointer bg-info btn-outline-secondary ms-2" (click)="runTask(PaperlessTaskName.IndexOptimize)">
+                      <i-bs name="play-fill"></i-bs>&nbsp;
+                      <ng-container i18n>Run Task</ng-container>
+                    </div>
+                  }
+                }
               </dd>
               <ng-template #indexStatus>
                 @if (status.tasks.index_status === 'OK') {
@@ -166,7 +176,7 @@
                 }
               </ng-template>
               <dt i18n>Classifier</dt>
-              <dd>
+              <dd class="d-flex align-items-center">
                 <div class="badge text-uppercase bg-info text-dark" [ngbPopover]="classifierStatus" triggers="mouseenter:mouseleave">
                   {{status.tasks.classifier_status}}
                   @if (status.tasks.classifier_status === 'OK') {
@@ -181,6 +191,16 @@
                     [class.text-warning]="status.tasks.classifier_status === SystemStatusItemStatus.WARNING"></i-bs>
                   }
                 </div>
+                @if (currentUserIsSuperUser) {
+                  @if (isRunning(PaperlessTaskName.TrainClassifier)) {
+                    <div class="spinner-border spinner-border-sm ms-2" role="status"></div>
+                  } @else {
+                    <div class="badge cursor-pointer bg-info btn-outline-secondary ms-2" (click)="runTask(PaperlessTaskName.TrainClassifier)">
+                      <i-bs name="play-fill"></i-bs>&nbsp;
+                      <ng-container i18n>Run Task</ng-container>
+                    </div>
+                  }
+                }
               </dd>
               <ng-template #classifierStatus>
                 @if (status.tasks.classifier_status === 'OK') {
@@ -190,7 +210,7 @@
                 }
               </ng-template>
               <dt i18n>Sanity Checker</dt>
-              <dd>
+              <dd class="d-flex align-items-center">
                 <div class="badge text-uppercase bg-info text-dark" [ngbPopover]="sanityCheckerStatus" triggers="mouseenter:mouseleave">
                   {{status.tasks.sanity_check_status}}
                   @if (status.tasks.sanity_check_status === 'OK') {
@@ -205,6 +225,16 @@
                     [class.text-warning]="status.tasks.sanity_check_status === SystemStatusItemStatus.WARNING"></i-bs>
                   }
                 </div>
+                @if (currentUserIsSuperUser) {
+                  @if (isRunning(PaperlessTaskName.SanityCheck)) {
+                    <div class="spinner-border spinner-border-sm ms-2" role="status"></div>
+                  } @else {
+                    <div class="badge cursor-pointer bg-info btn-outline-secondary ms-2" (click)="runTask(PaperlessTaskName.SanityCheck)">
+                      <i-bs name="play-fill"></i-bs>&nbsp;
+                      <ng-container i18n>Run Task</ng-container>
+                    </div>
+                  }
+                }
               </dd>
               <ng-template #sanityCheckerStatus>
                 @if (status.tasks.sanity_check_status === 'OK') {
diff --git a/src-ui/src/app/components/common/system-status-dialog/system-status-dialog.component.ts b/src-ui/src/app/components/common/system-status-dialog/system-status-dialog.component.ts
index 710d01dcf..d1e1e5745 100644
--- a/src-ui/src/app/components/common/system-status-dialog/system-status-dialog.component.ts
+++ b/src-ui/src/app/components/common/system-status-dialog/system-status-dialog.component.ts
@@ -7,12 +7,17 @@ import {
   NgbProgressbarModule,
 } from '@ng-bootstrap/ng-bootstrap'
 import { NgxBootstrapIconsModule } from 'ngx-bootstrap-icons'
+import { PaperlessTaskName } from 'src/app/data/paperless-task'
 import {
   SystemStatus,
   SystemStatusItemStatus,
 } from 'src/app/data/system-status'
 import { CustomDatePipe } from 'src/app/pipes/custom-date.pipe'
 import { FileSizePipe } from 'src/app/pipes/file-size.pipe'
+import { PermissionsService } from 'src/app/services/permissions.service'
+import { SystemStatusService } from 'src/app/services/system-status.service'
+import { TasksService } from 'src/app/services/tasks.service'
+import { ToastService } from 'src/app/services/toast.service'
 
 @Component({
   selector: 'pngx-system-status-dialog',
@@ -30,13 +35,24 @@ import { FileSizePipe } from 'src/app/pipes/file-size.pipe'
 })
 export class SystemStatusDialogComponent {
   public SystemStatusItemStatus = SystemStatusItemStatus
+  public PaperlessTaskName = PaperlessTaskName
   public status: SystemStatus
 
   public copied: boolean = false
 
+  private runningTasks: Set<PaperlessTaskName> = new Set()
+
+  get currentUserIsSuperUser(): boolean {
+    return this.permissionsService.isSuperUser()
+  }
+
   constructor(
     public activeModal: NgbActiveModal,
-    private clipboard: Clipboard
+    private clipboard: Clipboard,
+    private statusService: SystemStatusService,
+    private tasksService: TasksService,
+    private toastService: ToastService,
+    private permissionsService: PermissionsService
   ) {}
 
   public close() {
@@ -56,4 +72,30 @@ export class SystemStatusDialogComponent {
     const now = new Date()
     return now.getTime() - date.getTime() > hours * 60 * 60 * 1000
   }
+
+  public isRunning(taskName: PaperlessTaskName): boolean {
+    return this.runningTasks.has(taskName)
+  }
+
+  public runTask(taskName: PaperlessTaskName) {
+    this.runningTasks.add(taskName)
+    this.toastService.showInfo(`Task ${taskName} started`)
+    this.tasksService.run(taskName).subscribe({
+      next: () => {
+        this.runningTasks.delete(taskName)
+        this.statusService.get().subscribe({
+          next: (status) => {
+            this.status = status
+          },
+        })
+      },
+      error: (err) => {
+        this.runningTasks.delete(taskName)
+        this.toastService.showError(
+          `Failed to start task ${taskName}, see the logs for more details`,
+          err
+        )
+      },
+    })
+  }
 }
diff --git a/src-ui/src/app/data/paperless-task.ts b/src-ui/src/app/data/paperless-task.ts
index d788dcbd4..1bec277eb 100644
--- a/src-ui/src/app/data/paperless-task.ts
+++ b/src-ui/src/app/data/paperless-task.ts
@@ -10,6 +10,7 @@ export enum PaperlessTaskName {
   ConsumeFile = 'consume_file',
   TrainClassifier = 'train_classifier',
   SanityCheck = 'check_sanity',
+  IndexOptimize = 'index_optimize',
 }
 
 export enum PaperlessTaskStatus {
diff --git a/src-ui/src/app/services/tasks.service.spec.ts b/src-ui/src/app/services/tasks.service.spec.ts
index 940690453..0d4c8ee01 100644
--- a/src-ui/src/app/services/tasks.service.spec.ts
+++ b/src-ui/src/app/services/tasks.service.spec.ts
@@ -132,4 +132,19 @@ describe('TasksService', () => {
     expect(tasksService.queuedFileTasks).toHaveLength(1)
     expect(tasksService.startedFileTasks).toHaveLength(1)
   })
+
+  it('supports running tasks', () => {
+    tasksService.run(PaperlessTaskName.SanityCheck).subscribe((res) => {
+      expect(res).toEqual({
+        result: 'success',
+      })
+    })
+    const req = httpTestingController.expectOne(
+      `${environment.apiBaseUrl}tasks/run/`
+    )
+    expect(req.request.method).toEqual('POST')
+    req.flush({
+      result: 'success',
+    })
+  })
 })
diff --git a/src-ui/src/app/services/tasks.service.ts b/src-ui/src/app/services/tasks.service.ts
index 967d4e8ff..3ecfffe38 100644
--- a/src-ui/src/app/services/tasks.service.ts
+++ b/src-ui/src/app/services/tasks.service.ts
@@ -1,6 +1,6 @@
 import { HttpClient } from '@angular/common/http'
 import { Injectable } from '@angular/core'
-import { Subject } from 'rxjs'
+import { Observable, Subject } from 'rxjs'
 import { first, takeUntil } from 'rxjs/operators'
 import {
   PaperlessTask,
@@ -14,6 +14,7 @@ import { environment } from 'src/environments/environment'
 })
 export class TasksService {
   private baseUrl: string = environment.apiBaseUrl
+  private endpoint: string = 'tasks'
 
   public loading: boolean
 
@@ -55,7 +56,7 @@ export class TasksService {
 
     this.http
       .get<PaperlessTask[]>(
-        `${this.baseUrl}tasks/?task_name=consume_file&acknowledged=false`
+        `${this.baseUrl}${this.endpoint}/?task_name=consume_file&acknowledged=false`
       )
       .pipe(takeUntil(this.unsubscribeNotifer), first())
       .subscribe((r) => {
@@ -80,4 +81,13 @@ export class TasksService {
   public cancelPending(): void {
     this.unsubscribeNotifer.next(true)
   }
+
+  public run(taskName: PaperlessTaskName): Observable<any> {
+    return this.http.post<any>(
+      `${environment.apiBaseUrl}${this.endpoint}/run/`,
+      {
+        task_name: taskName,
+      }
+    )
+  }
 }
diff --git a/src-ui/src/main.ts b/src-ui/src/main.ts
index a9d446891..612e883d8 100644
--- a/src-ui/src/main.ts
+++ b/src-ui/src/main.ts
@@ -107,6 +107,7 @@ import {
   personFillLock,
   personLock,
   personSquare,
+  playFill,
   plus,
   plusCircle,
   questionCircle,
@@ -311,6 +312,7 @@ const icons = {
   personFillLock,
   personLock,
   personSquare,
+  playFill,
   plus,
   plusCircle,
   questionCircle,
diff --git a/src/documents/migrations/1063_paperlesstask_type_alter_paperlesstask_task_name_and_more.py b/src/documents/migrations/1063_paperlesstask_type_alter_paperlesstask_task_name_and_more.py
index 506817ead..aeedbd6a0 100644
--- a/src/documents/migrations/1063_paperlesstask_type_alter_paperlesstask_task_name_and_more.py
+++ b/src/documents/migrations/1063_paperlesstask_type_alter_paperlesstask_task_name_and_more.py
@@ -50,6 +50,7 @@ class Migration(migrations.Migration):
                     ("consume_file", "Consume File"),
                     ("train_classifier", "Train Classifier"),
                     ("check_sanity", "Check Sanity"),
+                    ("index_optimize", "Index Optimize"),
                 ],
                 help_text="Name of the task that was run",
                 max_length=255,
diff --git a/src/documents/models.py b/src/documents/models.py
index 3f7d459a9..42e473438 100644
--- a/src/documents/models.py
+++ b/src/documents/models.py
@@ -659,6 +659,7 @@ class PaperlessTask(ModelWithOwner):
         CONSUME_FILE = ("consume_file", _("Consume File"))
         TRAIN_CLASSIFIER = ("train_classifier", _("Train Classifier"))
         CHECK_SANITY = ("check_sanity", _("Check Sanity"))
+        INDEX_OPTIMIZE = ("index_optimize", _("Index Optimize"))
 
     task_id = models.CharField(
         max_length=255,
diff --git a/src/documents/serialisers.py b/src/documents/serialisers.py
index 251eb8797..e94f4234a 100644
--- a/src/documents/serialisers.py
+++ b/src/documents/serialisers.py
@@ -1742,6 +1742,14 @@ class TasksViewSerializer(OwnedObjectSerializer):
         return result
 
 
+class RunTaskViewSerializer(serializers.Serializer):
+    task_name = serializers.ChoiceField(
+        choices=PaperlessTask.TaskName.choices,
+        label="Task Name",
+        write_only=True,
+    )
+
+
 class AcknowledgeTasksViewSerializer(serializers.Serializer):
     tasks = serializers.ListField(
         required=True,
diff --git a/src/documents/tasks.py b/src/documents/tasks.py
index e3c579743..8a504d28d 100644
--- a/src/documents/tasks.py
+++ b/src/documents/tasks.py
@@ -201,13 +201,16 @@ def consume_file(
 
 
 @shared_task
-def sanity_check():
-    messages = sanity_checker.check_sanity()
+def sanity_check(*, scheduled=True, raise_on_error=True):
+    messages = sanity_checker.check_sanity(scheduled=scheduled)
 
     messages.log_messages()
 
     if messages.has_error:
-        raise SanityCheckFailedException("Sanity check failed with errors. See log.")
+        message = "Sanity check exited with errors. See log."
+        if raise_on_error:
+            raise SanityCheckFailedException(message)
+        return message
     elif messages.has_warning:
         return "Sanity check exited with warnings. See log."
     elif len(messages) > 0:
diff --git a/src/documents/tests/test_api_tasks.py b/src/documents/tests/test_api_tasks.py
index 3d4839ff5..57b56a2ef 100644
--- a/src/documents/tests/test_api_tasks.py
+++ b/src/documents/tests/test_api_tasks.py
@@ -1,4 +1,5 @@
 import uuid
+from unittest import mock
 
 import celery
 from django.contrib.auth.models import Permission
@@ -309,3 +310,57 @@ class TestTasks(DirectoriesMixin, APITestCase):
         returned_data = response.data[0]
 
         self.assertEqual(returned_data["related_document"], "1234")
+
+    @mock.patch("documents.tasks.train_classifier")
+    def test_run_train_classifier_task(self, mock_train_classifier):
+        """
+        GIVEN:
+            - A superuser
+        WHEN:
+            - API call is made to run the train classifier task
+        THEN:
+            - The task is run
+        """
+        mock_train_classifier.return_value = "Task started"
+        response = self.client.post(
+            self.ENDPOINT + "run/",
+            {"task_name": PaperlessTask.TaskName.TRAIN_CLASSIFIER},
+        )
+
+        self.assertEqual(response.status_code, status.HTTP_200_OK)
+        self.assertEqual(response.data, {"result": "Task started"})
+        mock_train_classifier.assert_called_once_with(scheduled=False)
+
+        # mock error
+        mock_train_classifier.reset_mock()
+        mock_train_classifier.side_effect = Exception("Error")
+        response = self.client.post(
+            self.ENDPOINT + "run/",
+            {"task_name": PaperlessTask.TaskName.TRAIN_CLASSIFIER},
+        )
+
+        self.assertEqual(response.status_code, status.HTTP_500_INTERNAL_SERVER_ERROR)
+        mock_train_classifier.assert_called_once_with(scheduled=False)
+
+    @mock.patch("documents.tasks.sanity_check")
+    def test_run_task_requires_superuser(self, mock_check_sanity):
+        """
+        GIVEN:
+            - A regular user
+        WHEN:
+            - API call is made to run a task
+        THEN:
+            - The task is not run
+        """
+        regular_user = User.objects.create_user(username="test")
+        regular_user.user_permissions.add(*Permission.objects.all())
+        self.client.logout()
+        self.client.force_authenticate(user=regular_user)
+
+        response = self.client.post(
+            self.ENDPOINT + "run/",
+            {"task_name": PaperlessTask.TaskName.CHECK_SANITY},
+        )
+
+        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
+        mock_check_sanity.assert_not_called()
diff --git a/src/documents/views.py b/src/documents/views.py
index 92aea1fe4..99cb9d76e 100644
--- a/src/documents/views.py
+++ b/src/documents/views.py
@@ -38,6 +38,7 @@ from django.http import HttpResponse
 from django.http import HttpResponseBadRequest
 from django.http import HttpResponseForbidden
 from django.http import HttpResponseRedirect
+from django.http import HttpResponseServerError
 from django.shortcuts import get_object_or_404
 from django.utils import timezone
 from django.utils.decorators import method_decorator
@@ -145,6 +146,7 @@ from documents.serialisers import DocumentListSerializer
 from documents.serialisers import DocumentSerializer
 from documents.serialisers import DocumentTypeSerializer
 from documents.serialisers import PostDocumentSerializer
+from documents.serialisers import RunTaskViewSerializer
 from documents.serialisers import SavedViewSerializer
 from documents.serialisers import SearchResultSerializer
 from documents.serialisers import ShareLinkSerializer
@@ -161,6 +163,9 @@ from documents.serialisers import WorkflowTriggerSerializer
 from documents.signals import document_updated
 from documents.tasks import consume_file
 from documents.tasks import empty_trash
+from documents.tasks import index_optimize
+from documents.tasks import sanity_check
+from documents.tasks import train_classifier
 from documents.templating.filepath import validate_filepath_template_and_render
 from paperless import version
 from paperless.celery import app as celery_app
@@ -2233,6 +2238,18 @@ class TasksViewSet(ReadOnlyModelViewSet):
     )
     filterset_class = PaperlessTaskFilterSet
 
+    TASK_AND_ARGS_BY_NAME = {
+        PaperlessTask.TaskName.INDEX_OPTIMIZE: (index_optimize, {}),
+        PaperlessTask.TaskName.TRAIN_CLASSIFIER: (
+            train_classifier,
+            {"scheduled": False},
+        ),
+        PaperlessTask.TaskName.CHECK_SANITY: (
+            sanity_check,
+            {"scheduled": False, "raise_on_error": False},
+        ),
+    }
+
     def get_queryset(self):
         queryset = PaperlessTask.objects.all().order_by("-date_created")
         task_id = self.request.query_params.get("task_id")
@@ -2257,6 +2274,25 @@ class TasksViewSet(ReadOnlyModelViewSet):
         except Exception:
             return HttpResponseBadRequest()
 
+    @action(methods=["post"], detail=False)
+    def run(self, request):
+        serializer = RunTaskViewSerializer(data=request.data)
+        serializer.is_valid(raise_exception=True)
+        task_name = serializer.validated_data.get("task_name")
+
+        if not request.user.is_superuser:
+            return HttpResponseForbidden("Insufficient permissions")
+
+        try:
+            task_func, task_args = self.TASK_AND_ARGS_BY_NAME[task_name]
+            result = task_func(**task_args)
+            return Response({"result": result})
+        except Exception as e:
+            logger.warning(f"An error occurred running task: {e!s}")
+            return HttpResponseServerError(
+                "Error running task, check logs for more detail.",
+            )
+
 
 class ShareLinkViewSet(ModelViewSet, PassUserMixin):
     model = ShareLink
diff --git a/src/locale/en_US/LC_MESSAGES/django.po b/src/locale/en_US/LC_MESSAGES/django.po
index 3ac865367..5dad5273b 100644
--- a/src/locale/en_US/LC_MESSAGES/django.po
+++ b/src/locale/en_US/LC_MESSAGES/django.po
@@ -2,7 +2,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: paperless-ngx\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2025-02-14 15:45-0800\n"
+"POT-Creation-Date: 2025-02-25 11:07-0800\n"
 "PO-Revision-Date: 2022-02-17 04:17\n"
 "Last-Translator: \n"
 "Language-Team: English\n"
@@ -57,31 +57,31 @@ msgstr ""
 msgid "Custom field not found"
 msgstr ""
 
-#: documents/models.py:41 documents/models.py:829
+#: documents/models.py:41 documents/models.py:830
 msgid "owner"
 msgstr ""
 
-#: documents/models.py:58 documents/models.py:1040
+#: documents/models.py:58 documents/models.py:1041
 msgid "None"
 msgstr ""
 
-#: documents/models.py:59 documents/models.py:1041
+#: documents/models.py:59 documents/models.py:1042
 msgid "Any word"
 msgstr ""
 
-#: documents/models.py:60 documents/models.py:1042
+#: documents/models.py:60 documents/models.py:1043
 msgid "All words"
 msgstr ""
 
-#: documents/models.py:61 documents/models.py:1043
+#: documents/models.py:61 documents/models.py:1044
 msgid "Exact match"
 msgstr ""
 
-#: documents/models.py:62 documents/models.py:1044
+#: documents/models.py:62 documents/models.py:1045
 msgid "Regular expression"
 msgstr ""
 
-#: documents/models.py:63 documents/models.py:1045
+#: documents/models.py:63 documents/models.py:1046
 msgid "Fuzzy word"
 msgstr ""
 
@@ -89,20 +89,20 @@ msgstr ""
 msgid "Automatic"
 msgstr ""
 
-#: documents/models.py:67 documents/models.py:433 documents/models.py:1521
+#: documents/models.py:67 documents/models.py:433 documents/models.py:1526
 #: paperless_mail/models.py:23 paperless_mail/models.py:143
 msgid "name"
 msgstr ""
 
-#: documents/models.py:69 documents/models.py:1108
+#: documents/models.py:69 documents/models.py:1110
 msgid "match"
 msgstr ""
 
-#: documents/models.py:72 documents/models.py:1111
+#: documents/models.py:72 documents/models.py:1113
 msgid "matching algorithm"
 msgstr ""
 
-#: documents/models.py:77 documents/models.py:1116
+#: documents/models.py:77 documents/models.py:1118
 msgid "is insensitive"
 msgstr ""
 
@@ -168,7 +168,7 @@ msgstr ""
 msgid "title"
 msgstr ""
 
-#: documents/models.py:175 documents/models.py:743
+#: documents/models.py:175 documents/models.py:744
 msgid "content"
 msgstr ""
 
@@ -206,8 +206,8 @@ msgstr ""
 msgid "The number of pages of the document."
 msgstr ""
 
-#: documents/models.py:221 documents/models.py:401 documents/models.py:749
-#: documents/models.py:787 documents/models.py:858 documents/models.py:916
+#: documents/models.py:221 documents/models.py:401 documents/models.py:750
+#: documents/models.py:788 documents/models.py:859 documents/models.py:917
 msgid "created"
 msgstr ""
 
@@ -255,8 +255,8 @@ msgstr ""
 msgid "The position of this document in your physical document archive."
 msgstr ""
 
-#: documents/models.py:295 documents/models.py:760 documents/models.py:814
-#: documents/models.py:1564
+#: documents/models.py:295 documents/models.py:761 documents/models.py:815
+#: documents/models.py:1569
 msgid "document"
 msgstr ""
 
@@ -320,11 +320,11 @@ msgstr ""
 msgid "Title"
 msgstr ""
 
-#: documents/models.py:420 documents/models.py:1060
+#: documents/models.py:420 documents/models.py:1062
 msgid "Created"
 msgstr ""
 
-#: documents/models.py:421 documents/models.py:1059
+#: documents/models.py:421 documents/models.py:1061
 msgid "Added"
 msgstr ""
 
@@ -632,589 +632,597 @@ msgstr ""
 msgid "Check Sanity"
 msgstr ""
 
-#: documents/models.py:666
-msgid "Task ID"
+#: documents/models.py:662
+msgid "Index Optimize"
 msgstr ""
 
 #: documents/models.py:667
+msgid "Task ID"
+msgstr ""
+
+#: documents/models.py:668
 msgid "Celery ID for the Task that was run"
 msgstr ""
 
-#: documents/models.py:672
+#: documents/models.py:673
 msgid "Acknowledged"
 msgstr ""
 
-#: documents/models.py:673
+#: documents/models.py:674
 msgid "If the task is acknowledged via the frontend or API"
 msgstr ""
 
-#: documents/models.py:679
+#: documents/models.py:680
 msgid "Task Filename"
 msgstr ""
 
-#: documents/models.py:680
+#: documents/models.py:681
 msgid "Name of the file which the Task was run for"
 msgstr ""
 
-#: documents/models.py:687
+#: documents/models.py:688
 msgid "Task Name"
 msgstr ""
 
-#: documents/models.py:688
+#: documents/models.py:689
 msgid "Name of the task that was run"
 msgstr ""
 
-#: documents/models.py:695
+#: documents/models.py:696
 msgid "Task State"
 msgstr ""
 
-#: documents/models.py:696
+#: documents/models.py:697
 msgid "Current state of the task being run"
 msgstr ""
 
-#: documents/models.py:702
+#: documents/models.py:703
 msgid "Created DateTime"
 msgstr ""
 
-#: documents/models.py:703
+#: documents/models.py:704
 msgid "Datetime field when the task result was created in UTC"
 msgstr ""
 
-#: documents/models.py:709
+#: documents/models.py:710
 msgid "Started DateTime"
 msgstr ""
 
-#: documents/models.py:710
+#: documents/models.py:711
 msgid "Datetime field when the task was started in UTC"
 msgstr ""
 
-#: documents/models.py:716
+#: documents/models.py:717
 msgid "Completed DateTime"
 msgstr ""
 
-#: documents/models.py:717
+#: documents/models.py:718
 msgid "Datetime field when the task was completed in UTC"
 msgstr ""
 
-#: documents/models.py:723
+#: documents/models.py:724
 msgid "Result Data"
 msgstr ""
 
-#: documents/models.py:725
+#: documents/models.py:726
 msgid "The data returned by the task"
 msgstr ""
 
-#: documents/models.py:733
+#: documents/models.py:734
 msgid "Task Type"
 msgstr ""
 
-#: documents/models.py:734
+#: documents/models.py:735
 msgid "The type of task that was run"
 msgstr ""
 
-#: documents/models.py:745
+#: documents/models.py:746
 msgid "Note for the document"
 msgstr ""
 
-#: documents/models.py:769
+#: documents/models.py:770
 msgid "user"
 msgstr ""
 
-#: documents/models.py:774
+#: documents/models.py:775
 msgid "note"
 msgstr ""
 
-#: documents/models.py:775
+#: documents/models.py:776
 msgid "notes"
 msgstr ""
 
-#: documents/models.py:783
+#: documents/models.py:784
 msgid "Archive"
 msgstr ""
 
-#: documents/models.py:784
+#: documents/models.py:785
 msgid "Original"
 msgstr ""
 
-#: documents/models.py:795 paperless_mail/models.py:75
+#: documents/models.py:796 paperless_mail/models.py:75
 msgid "expiration"
 msgstr ""
 
-#: documents/models.py:802
+#: documents/models.py:803
 msgid "slug"
 msgstr ""
 
-#: documents/models.py:834
+#: documents/models.py:835
 msgid "share link"
 msgstr ""
 
-#: documents/models.py:835
+#: documents/models.py:836
 msgid "share links"
 msgstr ""
 
-#: documents/models.py:847
+#: documents/models.py:848
 msgid "String"
 msgstr ""
 
-#: documents/models.py:848
+#: documents/models.py:849
 msgid "URL"
 msgstr ""
 
-#: documents/models.py:849
+#: documents/models.py:850
 msgid "Date"
 msgstr ""
 
-#: documents/models.py:850
+#: documents/models.py:851
 msgid "Boolean"
 msgstr ""
 
-#: documents/models.py:851
+#: documents/models.py:852
 msgid "Integer"
 msgstr ""
 
-#: documents/models.py:852
+#: documents/models.py:853
 msgid "Float"
 msgstr ""
 
-#: documents/models.py:853
+#: documents/models.py:854
 msgid "Monetary"
 msgstr ""
 
-#: documents/models.py:854
+#: documents/models.py:855
 msgid "Document Link"
 msgstr ""
 
-#: documents/models.py:855
+#: documents/models.py:856
 msgid "Select"
 msgstr ""
 
-#: documents/models.py:867
+#: documents/models.py:868
 msgid "data type"
 msgstr ""
 
-#: documents/models.py:874
+#: documents/models.py:875
 msgid "extra data"
 msgstr ""
 
-#: documents/models.py:878
+#: documents/models.py:879
 msgid "Extra data for the custom field, such as select options"
 msgstr ""
 
-#: documents/models.py:884
+#: documents/models.py:885
 msgid "custom field"
 msgstr ""
 
-#: documents/models.py:885
+#: documents/models.py:886
 msgid "custom fields"
 msgstr ""
 
-#: documents/models.py:982
+#: documents/models.py:983
 msgid "custom field instance"
 msgstr ""
 
-#: documents/models.py:983
+#: documents/models.py:984
 msgid "custom field instances"
 msgstr ""
 
-#: documents/models.py:1048
+#: documents/models.py:1049
 msgid "Consumption Started"
 msgstr ""
 
-#: documents/models.py:1049
+#: documents/models.py:1050
 msgid "Document Added"
 msgstr ""
 
-#: documents/models.py:1050
+#: documents/models.py:1051
 msgid "Document Updated"
 msgstr ""
 
-#: documents/models.py:1051
+#: documents/models.py:1052
 msgid "Scheduled"
 msgstr ""
 
-#: documents/models.py:1054
+#: documents/models.py:1055
 msgid "Consume Folder"
 msgstr ""
 
-#: documents/models.py:1055
+#: documents/models.py:1056
 msgid "Api Upload"
 msgstr ""
 
-#: documents/models.py:1056
+#: documents/models.py:1057
 msgid "Mail Fetch"
 msgstr ""
 
-#: documents/models.py:1061
+#: documents/models.py:1058
+msgid "Web UI"
+msgstr ""
+
+#: documents/models.py:1063
 msgid "Modified"
 msgstr ""
 
-#: documents/models.py:1062
+#: documents/models.py:1064
 msgid "Custom Field"
 msgstr ""
 
-#: documents/models.py:1065
+#: documents/models.py:1067
 msgid "Workflow Trigger Type"
 msgstr ""
 
-#: documents/models.py:1077
+#: documents/models.py:1079
 msgid "filter path"
 msgstr ""
 
-#: documents/models.py:1082
+#: documents/models.py:1084
 msgid ""
 "Only consume documents with a path that matches this if specified. Wildcards "
 "specified as * are allowed. Case insensitive."
 msgstr ""
 
-#: documents/models.py:1089
+#: documents/models.py:1091
 msgid "filter filename"
 msgstr ""
 
-#: documents/models.py:1094 paperless_mail/models.py:200
+#: documents/models.py:1096 paperless_mail/models.py:200
 msgid ""
 "Only consume documents which entirely match this filename if specified. "
 "Wildcards such as *.pdf or *invoice* are allowed. Case insensitive."
 msgstr ""
 
-#: documents/models.py:1105
+#: documents/models.py:1107
 msgid "filter documents from this mail rule"
 msgstr ""
 
-#: documents/models.py:1121
+#: documents/models.py:1123
 msgid "has these tag(s)"
 msgstr ""
 
-#: documents/models.py:1129
+#: documents/models.py:1131
 msgid "has this document type"
 msgstr ""
 
-#: documents/models.py:1137
+#: documents/models.py:1139
 msgid "has this correspondent"
 msgstr ""
 
-#: documents/models.py:1141
+#: documents/models.py:1143
 msgid "schedule offset days"
 msgstr ""
 
-#: documents/models.py:1144
+#: documents/models.py:1146
 msgid "The number of days to offset the schedule trigger by."
 msgstr ""
 
-#: documents/models.py:1149
+#: documents/models.py:1151
 msgid "schedule is recurring"
 msgstr ""
 
-#: documents/models.py:1152
+#: documents/models.py:1154
 msgid "If the schedule should be recurring."
 msgstr ""
 
-#: documents/models.py:1157
+#: documents/models.py:1159
 msgid "schedule recurring delay in days"
 msgstr ""
 
-#: documents/models.py:1161
+#: documents/models.py:1163
 msgid "The number of days between recurring schedule triggers."
 msgstr ""
 
-#: documents/models.py:1166
+#: documents/models.py:1168
 msgid "schedule date field"
 msgstr ""
 
-#: documents/models.py:1171
+#: documents/models.py:1173
 msgid "The field to check for a schedule trigger."
 msgstr ""
 
-#: documents/models.py:1180
+#: documents/models.py:1182
 msgid "schedule date custom field"
 msgstr ""
 
-#: documents/models.py:1184
+#: documents/models.py:1186
 msgid "workflow trigger"
 msgstr ""
 
-#: documents/models.py:1185
+#: documents/models.py:1187
 msgid "workflow triggers"
 msgstr ""
 
-#: documents/models.py:1193
+#: documents/models.py:1195
 msgid "email subject"
 msgstr ""
 
-#: documents/models.py:1197
+#: documents/models.py:1199
 msgid ""
 "The subject of the email, can include some placeholders, see documentation."
 msgstr ""
 
-#: documents/models.py:1203
+#: documents/models.py:1205
 msgid "email body"
 msgstr ""
 
-#: documents/models.py:1206
+#: documents/models.py:1208
 msgid ""
 "The body (message) of the email, can include some placeholders, see "
 "documentation."
 msgstr ""
 
-#: documents/models.py:1212
+#: documents/models.py:1214
 msgid "emails to"
 msgstr ""
 
-#: documents/models.py:1215
+#: documents/models.py:1217
 msgid "The destination email addresses, comma separated."
 msgstr ""
 
-#: documents/models.py:1221
+#: documents/models.py:1223
 msgid "include document in email"
 msgstr ""
 
-#: documents/models.py:1230
+#: documents/models.py:1234
 msgid "webhook url"
 msgstr ""
 
-#: documents/models.py:1232
+#: documents/models.py:1237
 msgid "The destination URL for the notification."
 msgstr ""
 
-#: documents/models.py:1237
+#: documents/models.py:1242
 msgid "use parameters"
 msgstr ""
 
-#: documents/models.py:1242
+#: documents/models.py:1247
 msgid "send as JSON"
 msgstr ""
 
-#: documents/models.py:1246
+#: documents/models.py:1251
 msgid "webhook parameters"
 msgstr ""
 
-#: documents/models.py:1249
+#: documents/models.py:1254
 msgid "The parameters to send with the webhook URL if body not used."
 msgstr ""
 
-#: documents/models.py:1253
+#: documents/models.py:1258
 msgid "webhook body"
 msgstr ""
 
-#: documents/models.py:1256
+#: documents/models.py:1261
 msgid "The body to send with the webhook URL if parameters not used."
 msgstr ""
 
-#: documents/models.py:1260
+#: documents/models.py:1265
 msgid "webhook headers"
 msgstr ""
 
-#: documents/models.py:1263
+#: documents/models.py:1268
 msgid "The headers to send with the webhook URL."
 msgstr ""
 
-#: documents/models.py:1268
+#: documents/models.py:1273
 msgid "include document in webhook"
 msgstr ""
 
-#: documents/models.py:1279
+#: documents/models.py:1284
 msgid "Assignment"
 msgstr ""
 
-#: documents/models.py:1283
+#: documents/models.py:1288
 msgid "Removal"
 msgstr ""
 
-#: documents/models.py:1287 documents/templates/account/password_reset.html:15
+#: documents/models.py:1292 documents/templates/account/password_reset.html:15
 msgid "Email"
 msgstr ""
 
-#: documents/models.py:1291
+#: documents/models.py:1296
 msgid "Webhook"
 msgstr ""
 
-#: documents/models.py:1295
+#: documents/models.py:1300
 msgid "Workflow Action Type"
 msgstr ""
 
-#: documents/models.py:1301
+#: documents/models.py:1306
 msgid "assign title"
 msgstr ""
 
-#: documents/models.py:1306
+#: documents/models.py:1311
 msgid ""
 "Assign a document title, can include some placeholders, see documentation."
 msgstr ""
 
-#: documents/models.py:1315 paperless_mail/models.py:274
+#: documents/models.py:1320 paperless_mail/models.py:274
 msgid "assign this tag"
 msgstr ""
 
-#: documents/models.py:1324 paperless_mail/models.py:282
+#: documents/models.py:1329 paperless_mail/models.py:282
 msgid "assign this document type"
 msgstr ""
 
-#: documents/models.py:1333 paperless_mail/models.py:296
+#: documents/models.py:1338 paperless_mail/models.py:296
 msgid "assign this correspondent"
 msgstr ""
 
-#: documents/models.py:1342
+#: documents/models.py:1347
 msgid "assign this storage path"
 msgstr ""
 
-#: documents/models.py:1351
+#: documents/models.py:1356
 msgid "assign this owner"
 msgstr ""
 
-#: documents/models.py:1358
+#: documents/models.py:1363
 msgid "grant view permissions to these users"
 msgstr ""
 
-#: documents/models.py:1365
+#: documents/models.py:1370
 msgid "grant view permissions to these groups"
 msgstr ""
 
-#: documents/models.py:1372
+#: documents/models.py:1377
 msgid "grant change permissions to these users"
 msgstr ""
 
-#: documents/models.py:1379
+#: documents/models.py:1384
 msgid "grant change permissions to these groups"
 msgstr ""
 
-#: documents/models.py:1386
+#: documents/models.py:1391
 msgid "assign these custom fields"
 msgstr ""
 
-#: documents/models.py:1393
+#: documents/models.py:1398
 msgid "remove these tag(s)"
 msgstr ""
 
-#: documents/models.py:1398
+#: documents/models.py:1403
 msgid "remove all tags"
 msgstr ""
 
-#: documents/models.py:1405
+#: documents/models.py:1410
 msgid "remove these document type(s)"
 msgstr ""
 
-#: documents/models.py:1410
+#: documents/models.py:1415
 msgid "remove all document types"
 msgstr ""
 
-#: documents/models.py:1417
+#: documents/models.py:1422
 msgid "remove these correspondent(s)"
 msgstr ""
 
-#: documents/models.py:1422
+#: documents/models.py:1427
 msgid "remove all correspondents"
 msgstr ""
 
-#: documents/models.py:1429
+#: documents/models.py:1434
 msgid "remove these storage path(s)"
 msgstr ""
 
-#: documents/models.py:1434
+#: documents/models.py:1439
 msgid "remove all storage paths"
 msgstr ""
 
-#: documents/models.py:1441
+#: documents/models.py:1446
 msgid "remove these owner(s)"
 msgstr ""
 
-#: documents/models.py:1446
+#: documents/models.py:1451
 msgid "remove all owners"
 msgstr ""
 
-#: documents/models.py:1453
+#: documents/models.py:1458
 msgid "remove view permissions for these users"
 msgstr ""
 
-#: documents/models.py:1460
+#: documents/models.py:1465
 msgid "remove view permissions for these groups"
 msgstr ""
 
-#: documents/models.py:1467
+#: documents/models.py:1472
 msgid "remove change permissions for these users"
 msgstr ""
 
-#: documents/models.py:1474
+#: documents/models.py:1479
 msgid "remove change permissions for these groups"
 msgstr ""
 
-#: documents/models.py:1479
+#: documents/models.py:1484
 msgid "remove all permissions"
 msgstr ""
 
-#: documents/models.py:1486
+#: documents/models.py:1491
 msgid "remove these custom fields"
 msgstr ""
 
-#: documents/models.py:1491
+#: documents/models.py:1496
 msgid "remove all custom fields"
 msgstr ""
 
-#: documents/models.py:1500
+#: documents/models.py:1505
 msgid "email"
 msgstr ""
 
-#: documents/models.py:1509
+#: documents/models.py:1514
 msgid "webhook"
 msgstr ""
 
-#: documents/models.py:1513
+#: documents/models.py:1518
 msgid "workflow action"
 msgstr ""
 
-#: documents/models.py:1514
+#: documents/models.py:1519
 msgid "workflow actions"
 msgstr ""
 
-#: documents/models.py:1523 paperless_mail/models.py:145
+#: documents/models.py:1528 paperless_mail/models.py:145
 msgid "order"
 msgstr ""
 
-#: documents/models.py:1529
+#: documents/models.py:1534
 msgid "triggers"
 msgstr ""
 
-#: documents/models.py:1536
+#: documents/models.py:1541
 msgid "actions"
 msgstr ""
 
-#: documents/models.py:1539 paperless_mail/models.py:154
+#: documents/models.py:1544 paperless_mail/models.py:154
 msgid "enabled"
 msgstr ""
 
-#: documents/models.py:1550
+#: documents/models.py:1555
 msgid "workflow"
 msgstr ""
 
-#: documents/models.py:1554
+#: documents/models.py:1559
 msgid "workflow trigger type"
 msgstr ""
 
-#: documents/models.py:1568
+#: documents/models.py:1573
 msgid "date run"
 msgstr ""
 
-#: documents/models.py:1574
+#: documents/models.py:1579
 msgid "workflow run"
 msgstr ""
 
-#: documents/models.py:1575
+#: documents/models.py:1580
 msgid "workflow runs"
 msgstr ""
 
-#: documents/serialisers.py:127
+#: documents/serialisers.py:128
 #, python-format
 msgid "Invalid regular expression: %(error)s"
 msgstr ""
 
-#: documents/serialisers.py:553
+#: documents/serialisers.py:554
 msgid "Invalid color."
 msgstr ""
 
-#: documents/serialisers.py:1554
+#: documents/serialisers.py:1570
 #, python-format
 msgid "File type %(type)s not supported"
 msgstr ""
 
-#: documents/serialisers.py:1643
+#: documents/serialisers.py:1659
 msgid "Invalid variable detected."
 msgstr ""
 
@@ -1434,6 +1442,27 @@ msgstr ""
 msgid "As a final step, please complete the following form:"
 msgstr ""
 
+#: documents/validators.py:24
+#, python-brace-format
+msgid "Unable to parse URI {value}, missing scheme"
+msgstr ""
+
+#: documents/validators.py:29
+#, python-brace-format
+msgid "Unable to parse URI {value}, missing net location or path"
+msgstr ""
+
+#: documents/validators.py:36
+msgid ""
+"URI scheme '{parts.scheme}' is not allowed. Allowed schemes: {', '."
+"join(allowed_schemes)}"
+msgstr ""
+
+#: documents/validators.py:45
+#, python-brace-format
+msgid "Unable to parse URI {value}"
+msgstr ""
+
 #: paperless/apps.py:10
 msgid "Paperless"
 msgstr ""
@@ -1718,7 +1747,7 @@ msgstr ""
 msgid "Chinese Traditional"
 msgstr ""
 
-#: paperless/urls.py:364
+#: paperless/urls.py:369
 msgid "Paperless-ngx administration"
 msgstr ""