diff --git a/.gitignore b/.gitignore
index 6a8fd526ec8c6c600fd616bca2a7893d2dee5d3e..a8d2e8e3d8b61967e872f5daed2c0fb7e5483d29 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,3 +16,4 @@ target/
 .attach**
 .factorypath
 .vscode*
+.nx
\ No newline at end of file
diff --git a/alfa-client/.nvmrc b/alfa-client/.nvmrc
index 87ec8842b158d213e0477ba0129281a484b9d47d..48b14e6b2b56f3819ca134cef59bc09580f44fd6 100644
--- a/alfa-client/.nvmrc
+++ b/alfa-client/.nvmrc
@@ -1 +1 @@
-18.18.2
+20.14.0
diff --git a/alfa-client/libs/design-component/src/lib/form/text-editor/text-editor.component.html b/alfa-client/libs/design-component/src/lib/form/text-editor/text-editor.component.html
index 103528775105ccb5f6c0cd000052581a9cbe76de..bd8034d8366f83cf4ddbee1e54c271fb932f2c9a 100644
--- a/alfa-client/libs/design-component/src/lib/form/text-editor/text-editor.component.html
+++ b/alfa-client/libs/design-component/src/lib/form/text-editor/text-editor.component.html
@@ -6,6 +6,7 @@
   [variant]="variant"
   [attr.data-test-id]="(label | convertForDataTest) + '-text-editor'"
   [required]="required"
+  [focus]="focus"
 >
   <ods-validation-error
     error
diff --git a/alfa-client/libs/design-component/src/lib/form/text-editor/text-editor.component.spec.ts b/alfa-client/libs/design-component/src/lib/form/text-editor/text-editor.component.spec.ts
index 5e06ccb099acf25b81bdbd3df74ca21eaa8deedf..90050933f1b1efdcd32a4f69238588c7becfafe0 100644
--- a/alfa-client/libs/design-component/src/lib/form/text-editor/text-editor.component.spec.ts
+++ b/alfa-client/libs/design-component/src/lib/form/text-editor/text-editor.component.spec.ts
@@ -37,6 +37,10 @@ describe('TextEditorComponent', () => {
     expect(element).toBeInstanceOf(HTMLElement);
   });
 
+  it('should have focus set to false by default', () => {
+    expect(component.focus).toBeFalsy();
+  });
+
   describe('errors', () => {
     it('should be hidden', () => {
       const element: HTMLElement = getElementFromFixture(fixture, errorId);
diff --git a/alfa-client/libs/design-component/src/lib/form/text-editor/text-editor.component.ts b/alfa-client/libs/design-component/src/lib/form/text-editor/text-editor.component.ts
index 151bc07b6be0d5b8fba125bd58a90ed92cbbf4d3..a1881546fe7309af8c1992f7c17645fe3e692ad4 100644
--- a/alfa-client/libs/design-component/src/lib/form/text-editor/text-editor.component.ts
+++ b/alfa-client/libs/design-component/src/lib/form/text-editor/text-editor.component.ts
@@ -23,6 +23,7 @@ export class TextEditorComponent extends FormControlEditorAbstractComponent impl
   @Input() autocomplete: 'off' | 'email' = 'off';
   @Input() placeholder: string = '';
   @Input() required: boolean = false;
+  @Input() focus: boolean = false;
 
   get variant(): string {
     return this.issues.length > 0 ? 'error' : 'default';
diff --git a/alfa-client/libs/design-component/src/lib/form/textarea-editor/textarea-editor.component.html b/alfa-client/libs/design-component/src/lib/form/textarea-editor/textarea-editor.component.html
index a937dde4d2b7600b2a191542cf9aa2731c8a5ef4..73ea744d07206658aafb6af0e95533b8d106960b 100644
--- a/alfa-client/libs/design-component/src/lib/form/textarea-editor/textarea-editor.component.html
+++ b/alfa-client/libs/design-component/src/lib/form/textarea-editor/textarea-editor.component.html
@@ -6,6 +6,7 @@
   [variant]="variant"
   [attr.data-test-id]="(label | convertForDataTest) + '-textarea-editor'"
   [required]="required"
+  [focus]="focus"
 >
   <ods-validation-error
     error
diff --git a/alfa-client/libs/design-component/src/lib/form/textarea-editor/textarea-editor.component.spec.ts b/alfa-client/libs/design-component/src/lib/form/textarea-editor/textarea-editor.component.spec.ts
index 2f73ad92072533f1fd72026ec3adf65b9653d162..4edd71d78ee59fa5c97ed6bf7ec19eff5f335530 100644
--- a/alfa-client/libs/design-component/src/lib/form/textarea-editor/textarea-editor.component.spec.ts
+++ b/alfa-client/libs/design-component/src/lib/form/textarea-editor/textarea-editor.component.spec.ts
@@ -33,6 +33,10 @@ describe('TextareaEditorComponent', () => {
     expect(element).toBeInstanceOf(HTMLElement);
   });
 
+  it('should have focus set to false by default', () => {
+    expect(component.focus).toBeFalsy();
+  });
+
   describe('errors', () => {
     it('should be hidden', () => {
       const element: HTMLElement = getElementFromFixture(fixture, errorId);
diff --git a/alfa-client/libs/design-component/src/lib/form/textarea-editor/textarea-editor.component.ts b/alfa-client/libs/design-component/src/lib/form/textarea-editor/textarea-editor.component.ts
index f0a749becccd815963681662c81c28cc3f0c3c4a..1514871a5a9e0d6032e96fd0b85cd3064726ff13 100644
--- a/alfa-client/libs/design-component/src/lib/form/textarea-editor/textarea-editor.component.ts
+++ b/alfa-client/libs/design-component/src/lib/form/textarea-editor/textarea-editor.component.ts
@@ -23,6 +23,7 @@ export class TextareaEditorComponent extends FormControlEditorAbstractComponent
   @Input() placeholder: string;
   @Input() rows: number = 10;
   @Input() required: boolean = false;
+  @Input() focus: boolean = false;
 
   get variant(): string {
     return this.issues.length > 0 ? 'error' : 'default';
diff --git a/alfa-client/libs/design-system/src/lib/form/text-input/text-input.component.spec.ts b/alfa-client/libs/design-system/src/lib/form/text-input/text-input.component.spec.ts
index 9f0ce2fb81efdf97dc2f74c466046b9447b249b2..082f7135ba559f5e393f7d97311a5624f5d28dea 100644
--- a/alfa-client/libs/design-system/src/lib/form/text-input/text-input.component.spec.ts
+++ b/alfa-client/libs/design-system/src/lib/form/text-input/text-input.component.spec.ts
@@ -1,11 +1,16 @@
+import { convertForDataTest } from '@alfa-client/tech-shared';
+import { getElementFromFixture } from '@alfa-client/test-utils';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { FormControl, ReactiveFormsModule } from '@angular/forms';
 import faker from '@faker-js/faker';
+import { getDataTestIdOf } from '../../../../../tech-shared/test/data-test';
 import { TextInputComponent } from './text-input.component';
 
 describe('TextInputComponent', () => {
   let component: TextInputComponent;
   let fixture: ComponentFixture<TextInputComponent>;
+  const label: string = faker.word.noun();
+  const dataTestId: string = `${convertForDataTest(label)}-text-input`;
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
@@ -14,7 +19,7 @@ describe('TextInputComponent', () => {
 
     fixture = TestBed.createComponent(TextInputComponent);
     component = fixture.componentInstance;
-    component.label = faker.word.noun();
+    component.label = label;
     component.fieldControl = new FormControl();
     fixture.detectChanges();
   });
@@ -22,4 +27,51 @@ describe('TextInputComponent', () => {
   it('should create', () => {
     expect(component).toBeTruthy();
   });
+
+  describe('aria', () => {
+    it('should have aria-invalid attribute', () => {
+      component.variant = 'error';
+
+      fixture.detectChanges();
+
+      const element: HTMLElement = getElementFromFixture(fixture, getDataTestIdOf(dataTestId));
+      expect(element.hasAttribute('aria-invalid')).toBe(true);
+    });
+
+    it('should have aria-invalid value false', () => {
+      component.variant = 'default';
+
+      fixture.detectChanges();
+
+      const element: HTMLElement = getElementFromFixture(fixture, getDataTestIdOf(dataTestId));
+      expect(element.getAttribute('aria-invalid')).toEqual('false');
+    });
+
+    it('should have aria-invalid value true', () => {
+      component.variant = 'error';
+
+      fixture.detectChanges();
+
+      const element: HTMLElement = getElementFromFixture(fixture, getDataTestIdOf(dataTestId));
+      expect(element.getAttribute('aria-invalid')).toEqual('true');
+    });
+  });
+
+  describe('focus', () => {
+    beforeEach(() => {
+      component.inputElement.nativeElement.focus = jest.fn();
+    });
+
+    it('should focus', () => {
+      component.focus = true;
+
+      expect(component.inputElement.nativeElement.focus).toHaveBeenCalled();
+    });
+
+    it('should not focus', () => {
+      component.focus = false;
+
+      expect(component.inputElement.nativeElement.focus).not.toHaveBeenCalled();
+    });
+  });
 });
diff --git a/alfa-client/libs/design-system/src/lib/form/text-input/text-input.component.ts b/alfa-client/libs/design-system/src/lib/form/text-input/text-input.component.ts
index ffb625fbac3347909db7779389f1d42cf5bed157..87770f419954a3c32d59424b0aab2a6a6c05a96b 100644
--- a/alfa-client/libs/design-system/src/lib/form/text-input/text-input.component.ts
+++ b/alfa-client/libs/design-system/src/lib/form/text-input/text-input.component.ts
@@ -1,8 +1,8 @@
-import { convertForDataTest } from '@alfa-client/tech-shared';
+import { convertForDataTest, TechSharedModule } from '@alfa-client/tech-shared';
 import { CommonModule } from '@angular/common';
-import { Component, Input } from '@angular/core';
+import { Component, ElementRef, Input, ViewChild } from '@angular/core';
 import { FormControl, ReactiveFormsModule } from '@angular/forms';
-import { VariantProps, cva } from 'class-variance-authority';
+import { cva, VariantProps } from 'class-variance-authority';
 import { ErrorMessageComponent } from '../error-message/error-message.component';
 
 const textInputVariants = cva(
@@ -24,12 +24,13 @@ type TextInputVariants = VariantProps<typeof textInputVariants>;
 @Component({
   selector: 'ods-text-input',
   standalone: true,
-  imports: [CommonModule, ErrorMessageComponent, ReactiveFormsModule],
+  imports: [CommonModule, ErrorMessageComponent, ReactiveFormsModule, TechSharedModule],
   template: `
     <div>
       <label [for]="id" class="text-md mb-2 block font-medium text-text"
-        >{{ label }}<ng-container *ngIf="required"><i aria-hidden="true">*</i></ng-container></label
-      >
+        >{{ label }}
+        <ng-container *ngIf="required"><i aria-hidden="true">*</i></ng-container>
+      </label>
       <div class="mt-2">
         <input
           type="text"
@@ -39,6 +40,9 @@ type TextInputVariants = VariantProps<typeof textInputVariants>;
           [placeholder]="placeholder"
           [autocomplete]="autocomplete"
           [required]="required"
+          [attr.aria-invalid]="variant === 'error'"
+          [attr.data-test-id]="(label | convertForDataTest) + '-text-input'"
+          #inputElement
         />
       </div>
       <ng-content select="[error]"></ng-content>
@@ -46,6 +50,8 @@ type TextInputVariants = VariantProps<typeof textInputVariants>;
   `,
 })
 export class TextInputComponent {
+  @ViewChild('inputElement') inputElement: ElementRef;
+
   @Input({ required: true }) label: string;
   @Input() placeholder: string = '';
   @Input() autocomplete: string = 'off';
@@ -53,6 +59,12 @@ export class TextInputComponent {
   @Input() fieldControl: FormControl;
   @Input() required: boolean = false;
 
+  @Input() set focus(value: boolean) {
+    if (value && this.inputElement) {
+      this.inputElement.nativeElement.focus();
+    }
+  }
+
   textInputVariants = textInputVariants;
 
   get id(): string {
diff --git a/alfa-client/libs/design-system/src/lib/form/textarea/textarea.component.spec.ts b/alfa-client/libs/design-system/src/lib/form/textarea/textarea.component.spec.ts
index 352e8ef418e6da5cb3fe04af88c96b52eb336853..e73b09cb52e462dfe30ec98f401738ff975a0ec8 100644
--- a/alfa-client/libs/design-system/src/lib/form/textarea/textarea.component.spec.ts
+++ b/alfa-client/libs/design-system/src/lib/form/textarea/textarea.component.spec.ts
@@ -1,11 +1,16 @@
+import { convertForDataTest } from '@alfa-client/tech-shared';
+import { getElementFromFixture } from '@alfa-client/test-utils';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { FormControl, ReactiveFormsModule } from '@angular/forms';
 import faker from '@faker-js/faker';
+import { getDataTestIdOf } from '../../../../../tech-shared/test/data-test';
 import { TextareaComponent } from './textarea.component';
 
 describe('TextareaComponent', () => {
   let component: TextareaComponent;
   let fixture: ComponentFixture<TextareaComponent>;
+  const label: string = faker.word.noun();
+  const dataTestId: string = `${convertForDataTest(label)}-textarea`;
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
@@ -14,7 +19,7 @@ describe('TextareaComponent', () => {
 
     fixture = TestBed.createComponent(TextareaComponent);
     component = fixture.componentInstance;
-    component.label = faker.word.noun();
+    component.label = label;
     component.fieldControl = new FormControl();
     fixture.detectChanges();
   });
@@ -22,4 +27,51 @@ describe('TextareaComponent', () => {
   it('should create', () => {
     expect(component).toBeTruthy();
   });
+
+  describe('aria', () => {
+    it('should have aria-invalid attribute', () => {
+      component.variant = 'error';
+
+      fixture.detectChanges();
+
+      const element: HTMLElement = getElementFromFixture(fixture, getDataTestIdOf(dataTestId));
+      expect(element.hasAttribute('aria-invalid')).toBe(true);
+    });
+
+    it('should have aria-invalid value false', () => {
+      component.variant = 'default';
+
+      fixture.detectChanges();
+
+      const element: HTMLElement = getElementFromFixture(fixture, getDataTestIdOf(dataTestId));
+      expect(element.getAttribute('aria-invalid')).toEqual('false');
+    });
+
+    it('should have aria-invalid value true', () => {
+      component.variant = 'error';
+
+      fixture.detectChanges();
+
+      const element: HTMLElement = getElementFromFixture(fixture, getDataTestIdOf(dataTestId));
+      expect(element.getAttribute('aria-invalid')).toEqual('true');
+    });
+  });
+
+  describe('focus', () => {
+    beforeEach(() => {
+      component.textAreaElement.nativeElement.focus = jest.fn();
+    });
+
+    it('should focus', () => {
+      component.focus = true;
+
+      expect(component.textAreaElement.nativeElement.focus).toHaveBeenCalled();
+    });
+
+    it('should not focus', () => {
+      component.focus = false;
+
+      expect(component.textAreaElement.nativeElement.focus).not.toHaveBeenCalled();
+    });
+  });
 });
diff --git a/alfa-client/libs/design-system/src/lib/form/textarea/textarea.component.ts b/alfa-client/libs/design-system/src/lib/form/textarea/textarea.component.ts
index 9574b15496bbcf1cff81387b35383f480aaa0596..21e6c863afcc41c876cdfd0fa45704770ce39d56 100644
--- a/alfa-client/libs/design-system/src/lib/form/textarea/textarea.component.ts
+++ b/alfa-client/libs/design-system/src/lib/form/textarea/textarea.component.ts
@@ -1,8 +1,8 @@
-import { convertForDataTest } from '@alfa-client/tech-shared';
+import { convertForDataTest, TechSharedModule } from '@alfa-client/tech-shared';
 import { CommonModule } from '@angular/common';
-import { Component, Input } from '@angular/core';
+import { Component, ElementRef, Input, ViewChild } from '@angular/core';
 import { FormControl, ReactiveFormsModule } from '@angular/forms';
-import { VariantProps, cva } from 'class-variance-authority';
+import { cva, VariantProps } from 'class-variance-authority';
 
 const textareaVariants = cva(
   'block w-full rounded-lg border bg-background-50 px-3 py-2 text-base text-text leading-5 focus:border-primary focus:ring-primary outline-none',
@@ -23,12 +23,13 @@ type TextareaVariants = VariantProps<typeof textareaVariants>;
 @Component({
   selector: 'ods-textarea',
   standalone: true,
-  imports: [CommonModule, ReactiveFormsModule],
+  imports: [CommonModule, ReactiveFormsModule, TechSharedModule],
   template: `
     <div class="mt-2">
       <label [for]="id" class="text-md mb-2 block font-medium text-text"
-        >{{ label }}<ng-container *ngIf="required"><i aria-hidden="true">*</i></ng-container></label
-      >
+        >{{ label }}
+        <ng-container *ngIf="required"><i aria-hidden="true">*</i></ng-container>
+      </label>
       <textarea
         [id]="id"
         [formControl]="fieldControl"
@@ -37,12 +38,17 @@ type TextareaVariants = VariantProps<typeof textareaVariants>;
         [placeholder]="placeholder"
         [autocomplete]="autocomplete"
         [required]="required"
+        [attr.aria-invalid]="variant === 'error'"
+        [attr.data-test-id]="(label | convertForDataTest) + '-textarea'"
+        #textAreaElement
       ></textarea>
       <ng-content select="[error]"></ng-content>
     </div>
   `,
 })
 export class TextareaComponent {
+  @ViewChild('textAreaElement') textAreaElement: ElementRef;
+
   @Input({ required: true }) label!: string;
   @Input({ required: true }) placeholder!: string;
   @Input() error: string;
@@ -52,6 +58,12 @@ export class TextareaComponent {
   @Input() fieldControl: FormControl;
   @Input() required: boolean = false;
 
+  @Input() set focus(value: boolean) {
+    if (value && this.textAreaElement) {
+      this.textAreaElement.nativeElement.focus();
+    }
+  }
+
   textareaVariants = textareaVariants;
 
   get id(): string {
diff --git a/alfa-client/libs/tech-shared/src/lib/service/formservice.abstract.spec.ts b/alfa-client/libs/tech-shared/src/lib/service/formservice.abstract.spec.ts
index 65c4b159b81ac89cca0b3d82e7f086d9ccf921c0..1472e6fe3c880b33faeaf14e875f6973dde18a73 100644
--- a/alfa-client/libs/tech-shared/src/lib/service/formservice.abstract.spec.ts
+++ b/alfa-client/libs/tech-shared/src/lib/service/formservice.abstract.spec.ts
@@ -25,22 +25,14 @@ import { CommandResource } from '@alfa-client/command-shared';
 import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms';
 import { Resource } from '@ngxp/rest';
 import { cold } from 'jest-marbles';
-import {
-  createApiError,
-  createInvalidParam,
-  createIssue,
-  createProblemDetail,
-} from 'libs/tech-shared/test/error';
+import { createApiError, createInvalidParam, createIssue, createProblemDetail } from 'libs/tech-shared/test/error';
 import { Observable, of } from 'rxjs';
 import { AbstractFormService } from './formservice.abstract';
 
-import {
-  StateResource,
-  createEmptyStateResource,
-  createErrorStateResource,
-} from '../resource/resource.util';
+import { createEmptyStateResource, createErrorStateResource, createStateResource, StateResource } from '../resource/resource.util';
 import { ApiError, HttpError, InvalidParam, Issue, ProblemDetail } from '../tech.model';
 
+import { createCommandResource } from '../../../../command-shared/test/command';
 import * as ValidationUtil from '../validation/tech.validation.util';
 
 describe('AbstractFormService', () => {
@@ -63,6 +55,7 @@ describe('AbstractFormService', () => {
         TestFormService.SUBMIT_OBSERVABLE = () => of(stateResourceWithError);
         formService.handleResponse = jest.fn((stateResource) => stateResource);
       });
+
       it('should call handle response for api error', (done) => {
         formService.submit().subscribe(() => {
           expect(formService.handleResponse).toHaveBeenCalledWith(stateResourceWithError);
@@ -77,6 +70,30 @@ describe('AbstractFormService', () => {
         expect(submitObservable).toBeObservable(cold('(a|)', { a: stateResourceWithError }));
       });
     });
+
+    it('should call after submit operator function', (done) => {
+      const commandStateResource: StateResource<CommandResource> =
+        createStateResource(createCommandResource());
+      const afterSubmit = () => of(commandStateResource);
+      formService.handleResponse = jest.fn();
+
+      formService.submit(afterSubmit).subscribe(() => {
+        expect(formService.handleResponse).toHaveBeenCalledWith(commandStateResource);
+        done();
+      });
+    });
+
+    it('should pass through as default after submit', (done) => {
+      const commandStateResource: StateResource<CommandResource> =
+        createStateResource(createCommandResource());
+      TestFormService.SUBMIT_OBSERVABLE = () => of(commandStateResource);
+      formService.handleResponse = jest.fn();
+
+      formService.submit().subscribe(() => {
+        expect(formService.handleResponse).toHaveBeenCalledWith(commandStateResource);
+        done();
+      });
+    });
   });
 
   describe('handleResponse', () => {
diff --git a/alfa-client/libs/tech-shared/src/lib/service/formservice.abstract.ts b/alfa-client/libs/tech-shared/src/lib/service/formservice.abstract.ts
index a02d2bab0a0eadcc998270d2d06adc277961d236..ab647437a8483fb73bccc4fa0e4d083ef8c48cde 100644
--- a/alfa-client/libs/tech-shared/src/lib/service/formservice.abstract.ts
+++ b/alfa-client/libs/tech-shared/src/lib/service/formservice.abstract.ts
@@ -25,15 +25,12 @@ import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
 
 import { Resource } from '@ngxp/rest';
 import { isNil } from 'lodash-es';
-import { Observable } from 'rxjs';
+import { identity, Observable, OperatorFunction } from 'rxjs';
 import { map } from 'rxjs/operators';
-import { StateResource, hasStateResourceError } from '../resource/resource.util';
+import { hasStateResourceError, StateResource } from '../resource/resource.util';
 import { ApiError, HttpError, InvalidParam, Issue, ProblemDetail } from '../tech.model';
 import { isNotUndefined } from '../tech.util';
-import {
-  setInvalidParamValidationError,
-  setIssueValidationError,
-} from '../validation/tech.validation.util';
+import { setInvalidParamValidationError, setIssueValidationError } from '../validation/tech.validation.util';
 
 export abstract class AbstractFormService {
   form: UntypedFormGroup;
@@ -48,8 +45,13 @@ export abstract class AbstractFormService {
 
   protected abstract initForm(): UntypedFormGroup;
 
-  public submit(): Observable<StateResource<Resource | HttpError>> {
-    return this.doSubmit().pipe(map((result) => this.handleResponse(result)));
+  public submit(
+    afterSubmit: OperatorFunction<StateResource<Resource>, StateResource<Resource>> = identity,
+  ): Observable<StateResource<Resource | HttpError>> {
+    return this.doSubmit().pipe(
+      afterSubmit,
+      map((result) => this.handleResponse(result)),
+    );
   }
 
   protected abstract doSubmit(): Observable<StateResource<Resource | HttpError>>;
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/bescheiden.formservice.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/bescheiden.formservice.spec.ts
index 6cad6f19354bc4784e455e1f93fe7b1f0687eccf..9e29f9d8172e162e37e5187cb5729efe2dd45eaf 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/bescheiden.formservice.spec.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/bescheiden.formservice.spec.ts
@@ -467,6 +467,34 @@ describe('BescheidenFormService', () => {
     });
   });
 
+  describe('isBetreffInvalid', () => {
+    it('should return true', () => {
+      service.form.controls[BescheidenFormService.FIELD_NACHRICHT_SUBJECT].setErrors({});
+
+      expect(service.isBetreffInvalid()).toBeTruthy();
+    });
+
+    it('should return false', () => {
+      service.form.controls[BescheidenFormService.FIELD_NACHRICHT_SUBJECT].setErrors(null);
+
+      expect(service.isBetreffInvalid()).toBeFalsy();
+    });
+  });
+
+  describe('isNachrichtInvalid', () => {
+    it('should return true', () => {
+      service.form.controls[BescheidenFormService.FIELD_NACHRICHT_TEXT].setErrors({});
+
+      expect(service.isNachrichtInvalid()).toBeTruthy();
+    });
+
+    it('should return false', () => {
+      service.form.controls[BescheidenFormService.FIELD_NACHRICHT_TEXT].setErrors(null);
+
+      expect(service.isNachrichtInvalid()).toBeFalsy();
+    });
+  });
+
   describe('updateNachrichtOnSuccess', () => {
     const subject: string = faker.lorem.words(3);
     const text: string = faker.lorem.text();
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/bescheiden.formservice.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/bescheiden.formservice.ts
index 2ebd9db5811d3b3c7752ded2708e7c3156c55294..d9e05716a5c15264f7f5b671ecec6a8f61cc1ca1 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/bescheiden.formservice.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/bescheiden.formservice.ts
@@ -301,4 +301,12 @@ export class BescheidenFormService extends AbstractFormService implements OnDest
     this.showMissingBescheidDocumentError$.next(isEmpty(this.getValue().bescheidDocument));
     return isNotEmpty(this.getValue().bescheidDocument);
   }
+
+  public isBetreffInvalid(): boolean {
+    return this.form.controls[BescheidenFormService.FIELD_NACHRICHT_SUBJECT].invalid;
+  }
+
+  public isNachrichtInvalid(): boolean {
+    return this.form.controls[BescheidenFormService.FIELD_NACHRICHT_TEXT].invalid;
+  }
 }
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result-nachricht/vorgang-detail-bescheiden-result-nachricht.component.html b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result-nachricht/vorgang-detail-bescheiden-result-nachricht.component.html
index 99306a896d5938ce7495270e0ca47ad89912e824..0b4b30cf95db4e50dbaec098d73c7b5fe1d0399b 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result-nachricht/vorgang-detail-bescheiden-result-nachricht.component.html
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result-nachricht/vorgang-detail-bescheiden-result-nachricht.component.html
@@ -11,7 +11,7 @@
     [formControlName]="formServiceClass.FIELD_NACHRICHT_SUBJECT"
     label="Betreff"
     placeholder="Betreff hier eingeben"
-    required="true"
+    [focus]="focusBetreff"
   >
   </ods-text-editor>
 
@@ -19,7 +19,7 @@
     [formControlName]="formServiceClass.FIELD_NACHRICHT_TEXT"
     label="Text"
     placeholder="Nachrichtentext hier eingeben"
-    required="true"
+    [focus]="focusNachricht"
   >
   </ods-textarea-editor>
 </div>
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result-nachricht/vorgang-detail-bescheiden-result-nachricht.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result-nachricht/vorgang-detail-bescheiden-result-nachricht.component.spec.ts
index 893c337ba18e0c86c6454628e475431305b092ba..892c0f51c55deb828359fa2df54a45701f137583 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result-nachricht/vorgang-detail-bescheiden-result-nachricht.component.spec.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result-nachricht/vorgang-detail-bescheiden-result-nachricht.component.spec.ts
@@ -1,9 +1,9 @@
 import { BescheidService, DocumentResource } from '@alfa-client/bescheid-shared';
 import {
-  StateResource,
   createEmptyStateResource,
   createErrorStateResource,
   createStateResource,
+  StateResource,
 } from '@alfa-client/tech-shared';
 import { getElementFromFixture } from '@alfa-client/test-utils';
 import { registerLocaleData } from '@angular/common';
@@ -11,7 +11,7 @@ import localeDe from '@angular/common/locales/de';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { ReactiveFormsModule, UntypedFormBuilder } from '@angular/forms';
 import faker from '@faker-js/faker';
-import { TextEditorComponent, TextareaEditorComponent } from '@ods/component';
+import { TextareaEditorComponent, TextEditorComponent } from '@ods/component';
 import { Mock, mock, useFromMock } from 'libs/test-utils/src/lib/mocking';
 import { OzgcloudSvgIconComponent } from 'libs/ui/src/lib/ui/ozgcloud-svgicon/ozgcloud-svgicon.component';
 import { MockComponent } from 'ng-mocks';
@@ -111,12 +111,23 @@ describe('VorgangDetailBescheidenResultNachrichtComponent', () => {
     it('should patch form', () => {
       const documentStateResource: StateResource<DocumentResource> =
         createStateResource(createDocumentResource());
+      jest.spyOn(formService.form, 'valid', 'get').mockReturnValue(true);
 
       component.bescheidDocumentStateResource = documentStateResource;
 
       expect(formService.patchNachricht).toHaveBeenCalledWith(documentStateResource.resource);
     });
 
+    it('should not patch if form is invalid', () => {
+      const documentStateResource: StateResource<DocumentResource> =
+        createStateResource(createDocumentResource());
+      jest.spyOn(formService.form, 'valid', 'get').mockReturnValue(false);
+
+      component.bescheidDocumentStateResource = documentStateResource;
+
+      expect(formService.patchNachricht).not.toHaveBeenCalledWith(documentStateResource.resource);
+    });
+
     it('should not patch form if document loading', () => {
       component.bescheidDocumentStateResource = { ...createEmptyStateResource(), loading: true };
 
@@ -138,4 +149,66 @@ describe('VorgangDetailBescheidenResultNachrichtComponent', () => {
       },
     );
   });
+
+  describe('resetFocus', () => {
+    it('should reset betreff focus', () => {
+      component.focusBetreff = true;
+
+      component.resetFocus();
+
+      expect(component.focusBetreff).toBeFalsy();
+    });
+
+    it('should reset nachricht focus', () => {
+      component.focusNachricht = true;
+
+      component.resetFocus();
+
+      expect(component.focusNachricht).toBeFalsy();
+    });
+  });
+
+  describe('sendWithNachrichtCommandStateResource', () => {
+    beforeEach(() => {
+      component.resetFocus = jest.fn();
+    });
+
+    it('should reset focus', () => {
+      component.sendWithNachrichtCommandStateResource = createEmptyStateResource();
+
+      expect(component.resetFocus).toHaveBeenCalled();
+    });
+
+    it('should focus betreff', () => {
+      component.focusBetreff = false;
+      formService.isBetreffInvalid = jest.fn().mockReturnValue(true);
+      formService.isNachrichtInvalid = jest.fn().mockReturnValue(false);
+
+      component.sendWithNachrichtCommandStateResource = createErrorStateResource(createApiError());
+
+      expect(component.focusBetreff).toBeTruthy();
+    });
+
+    it('should focus nachricht', () => {
+      component.focusNachricht = false;
+      formService.isBetreffInvalid = jest.fn().mockReturnValue(false);
+      formService.isNachrichtInvalid = jest.fn().mockReturnValue(true);
+
+      component.sendWithNachrichtCommandStateResource = createErrorStateResource(createApiError());
+
+      expect(component.focusNachricht).toBeTruthy();
+    });
+
+    it('should focus betreff first', () => {
+      component.focusNachricht = false;
+      component.focusBetreff = false;
+      formService.isBetreffInvalid = jest.fn().mockReturnValue(true);
+      formService.isNachrichtInvalid = jest.fn().mockReturnValue(true);
+
+      component.sendWithNachrichtCommandStateResource = createErrorStateResource(createApiError());
+
+      expect(component.focusBetreff).toBeTruthy();
+      expect(component.focusNachricht).toBeFalsy();
+    });
+  });
 });
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result-nachricht/vorgang-detail-bescheiden-result-nachricht.component.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result-nachricht/vorgang-detail-bescheiden-result-nachricht.component.ts
index 9dd0fca6fb796f1d47f773d147fdd54954ae1756..71e3ba8875bb20787f28dc4027caa5ab643d8088 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result-nachricht/vorgang-detail-bescheiden-result-nachricht.component.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result-nachricht/vorgang-detail-bescheiden-result-nachricht.component.ts
@@ -1,5 +1,6 @@
 import { BescheidService, DocumentResource } from '@alfa-client/bescheid-shared';
-import { StateResource, isNotNil } from '@alfa-client/tech-shared';
+import { CommandResource } from '@alfa-client/command-shared';
+import { hasStateResourceError, isNotNil, StateResource } from '@alfa-client/tech-shared';
 import { Component, Input, OnInit } from '@angular/core';
 import { FormGroup } from '@angular/forms';
 import { Observable } from 'rxjs';
@@ -10,15 +11,38 @@ import { BescheidenFormService } from '../../bescheiden.formservice';
   templateUrl: './vorgang-detail-bescheiden-result-nachricht.component.html',
 })
 export class VorgangDetailBescheidenResultNachrichtComponent implements OnInit {
-  @Input() set bescheidDocumentStateResource(stateResource: StateResource<DocumentResource>) {
+  @Input()
+  set bescheidDocumentStateResource(stateResource: StateResource<DocumentResource>) {
     if (!stateResource.loading && !stateResource.error && isNotNil(stateResource.resource)) {
-      this.formService.patchNachricht(stateResource.resource);
+      if (isNotNil(this.form) && this.form.valid) {
+        this.formService.patchNachricht(stateResource.resource);
+      }
     }
   }
 
+  @Input()
+  set sendWithNachrichtCommandStateResource(stateResource: StateResource<CommandResource>) {
+    this.resetFocus();
+    if (isNotNil(stateResource) && hasStateResourceError(stateResource)) {
+      if (this.formService.isBetreffInvalid()) {
+        this.focusBetreff = true;
+      } else if (this.formService.isNachrichtInvalid()) {
+        this.focusNachricht = true;
+      }
+    }
+  }
+
+  resetFocus() {
+    this.focusBetreff = false;
+    this.focusNachricht = false;
+  }
+
   empfaenger$: Observable<string>;
   form: FormGroup;
 
+  public focusBetreff: boolean = false;
+  public focusNachricht: boolean = false;
+
   readonly formServiceClass = BescheidenFormService;
 
   constructor(
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result.component.html b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result.component.html
index 158859aef477901045106b1b0e6d60fe2cdab6e2..99468af54c2fca65dc40fd83f9f6e20a12c1c0bf 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result.component.html
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result.component.html
@@ -32,6 +32,7 @@
     <div *ngIf="!wizardData.sendByManual && wizardData.activeStep === 3 && (canSend$ | async)">
       <alfa-vorgang-detail-bescheiden-result-nachricht
         [bescheidDocumentStateResource]="bescheidDocument$ | async"
+        [sendWithNachrichtCommandStateResource]="sendWithNachricht$ | async"
         data-test-id="bescheid-nachricht-an-antragsteller"
       ></alfa-vorgang-detail-bescheiden-result-nachricht>
     </div>
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result.component.spec.ts
index 918867cb02f084f1d79f24aca4ac1e8cdfbd5283..09b86fb5cca6a3e276234985d4c980d39cae2ab9 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result.component.spec.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result.component.spec.ts
@@ -1,11 +1,15 @@
 import { BescheidLinkRel, BescheidResource, BescheidService } from '@alfa-client/bescheid-shared';
 import { CommandOrder, CommandResource } from '@alfa-client/command-shared';
-import { StateResource, createStateResource } from '@alfa-client/tech-shared';
 import {
-  Mock,
+  createEmptyStateResource,
+  createStateResource,
+  StateResource,
+} from '@alfa-client/tech-shared';
+import {
   dispatchEventFromFixture,
   existsAsHtmlElement,
   getElementFromFixture,
+  Mock,
   mock,
   notExistsAsHtmlElement,
 } from '@alfa-client/test-utils';
@@ -51,6 +55,8 @@ describe('VorgangDetailBescheidenResultComponent', () => {
     formService.getBescheidChanges.mockReturnValue(
       new BehaviorSubject({ beschiedenAm: new Date(), bewilligt: false }),
     );
+    formService.getActiveStep.mockReturnValue(EMPTY);
+
     await TestBed.configureTestingModule({
       declarations: [
         VorgangDetailBescheidenResultComponent,
@@ -210,6 +216,26 @@ describe('VorgangDetailBescheidenResultComponent', () => {
       expect(formService.getActiveStep).toHaveBeenCalled();
     });
 
+    it.each([1, 2])('should reset save and send in progress in step %d', (step: number) => {
+      formService.getActiveStep.mockReturnValue(of(step));
+      component.resetSend = jest.fn();
+
+      component.ngOnInit();
+
+      component.activeStep$.subscribe();
+      expect(component.resetSend).toHaveBeenCalled();
+    });
+
+    it('should not reset save and send in progress in last step', () => {
+      formService.getActiveStep.mockReturnValue(of(3));
+      component.resetSend = jest.fn();
+
+      component.ngOnInit();
+
+      component.activeStep$.subscribe();
+      expect(component.resetSend).not.toHaveBeenCalled();
+    });
+
     it('should call formservice to get current bescheid/formular', () => {
       component.ngOnInit();
 
@@ -383,16 +409,18 @@ describe('VorgangDetailBescheidenResultComponent', () => {
       expect(formService.submit).toHaveBeenCalled();
     });
 
-    it('should call send on successfully done command', () => {
+    it('should call send after successfully update', () => {
+      component.doSendAfterSuccessfullyUpdate = jest.fn();
       const sendMock = jest.fn();
 
-      component.doUpdateAndSend(bescheidDraft, sendMock).pipe(first()).subscribe();
+      component.doUpdateAndSend(bescheidDraft, sendMock).subscribe();
 
-      expect(sendMock).toHaveBeenCalled();
+      expect(component.doSendAfterSuccessfullyUpdate).toHaveBeenCalledWith(bescheidDraft, sendMock);
     });
 
     it('should close dialog on successfully done command', () => {
-      const sendMock = jest.fn().mockReturnValue(
+      const sendMock = jest.fn();
+      formService.submit = jest.fn().mockReturnValue(
         of(
           createStateResource({
             ...createCommandResource([CommandLinkRel.EFFECTED_RESOURCE]),
@@ -408,6 +436,34 @@ describe('VorgangDetailBescheidenResultComponent', () => {
     });
   });
 
+  describe('doSendAfterSuccessfullyUpdate', () => {
+    const bescheidDraft: BescheidResource = createBescheidResource();
+
+    it('should call send', () => {
+      const commandStateResource: StateResource<CommandResource> = createStateResource(
+        createCommandResource([CommandLinkRel.EFFECTED_RESOURCE]),
+      );
+      const sendMock = jest.fn();
+
+      component
+        .doSendAfterSuccessfullyUpdate(bescheidDraft, sendMock)(of(commandStateResource))
+        .subscribe();
+
+      expect(sendMock).toHaveBeenCalled();
+    });
+
+    it('should not call send', () => {
+      const commandStateResource: StateResource<CommandResource> = createEmptyStateResource();
+      const sendMock = jest.fn();
+
+      component
+        .doSendAfterSuccessfullyUpdate(bescheidDraft, sendMock)(of(commandStateResource))
+        .subscribe();
+
+      expect(sendMock).not.toHaveBeenCalled();
+    });
+  });
+
   describe('bescheid status text', () => {
     it('should NOT be visible on NOT send by manual', () => {
       component.sendByManual$ = of(false);
@@ -527,4 +583,34 @@ describe('VorgangDetailBescheidenResultComponent', () => {
       notExistsAsHtmlElement(fixture, saveAndSendButton);
     });
   });
+
+  describe('resetSend', () => {
+    it('should set to empty state resource', () => {
+      component.saveAndSendInProgress$ = of(createStateResource(createCommandResource()));
+
+      component.resetSend();
+
+      expect(component.saveAndSendInProgress$).toBeObservable(
+        singleColdCompleted(createEmptyStateResource()),
+      );
+    });
+  });
+
+  describe('ifNotLastStep', () => {
+    it.each([1, 2])('should do it in step %d', (step: number) => {
+      const doIt = jest.fn();
+
+      of(step).pipe(component.ifNotLastStep(doIt)).subscribe();
+
+      expect(doIt).toHaveBeenCalled();
+    });
+
+    it('should not do it in last step', () => {
+      const doIt = jest.fn();
+
+      of(3).pipe(component.ifNotLastStep(doIt)).subscribe();
+
+      expect(doIt).not.toHaveBeenCalled();
+    });
+  });
 });
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result.component.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result.component.ts
index 29e7e18dfa836123bfbf1232551170fc20224012..9ffa6be076415cd7e55d777845c5b7a28c04322d 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result.component.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result.component.ts
@@ -15,8 +15,8 @@ import {
 } from '@alfa-client/command-shared';
 import { createEmptyStateResource, isLoaded, StateResource } from '@alfa-client/tech-shared';
 import { Component, EventEmitter, OnInit, Output } from '@angular/core';
-import { hasLink } from '@ngxp/rest';
-import { filter, map, Observable, of } from 'rxjs';
+import { hasLink, Resource } from '@ngxp/rest';
+import { filter, map, Observable, of, OperatorFunction, tap } from 'rxjs';
 import { BescheidenFormService } from '../bescheiden.formservice';
 
 type sendBescheid = (
@@ -28,6 +28,8 @@ type sendBescheid = (
   templateUrl: './vorgang-detail-bescheiden-result.component.html',
 })
 export class VorgangDetailBescheidenResultComponent implements OnInit {
+  private static readonly LAST_STEP: number = 3;
+
   @Output() closeDialog: EventEmitter<void> = new EventEmitter();
 
   public activeStep$: Observable<number>;
@@ -55,6 +57,10 @@ export class VorgangDetailBescheidenResultComponent implements OnInit {
     createEmptyStateResource<CommandResource>(),
   );
 
+  public sendWithNachricht$: Observable<StateResource<CommandResource>> = of(
+    createEmptyStateResource<CommandResource>(),
+  );
+
   public canSave$: Observable<boolean> = of(true);
   public canSend$: Observable<boolean> = of(true);
   public showMissingBescheidDocumentError$: Observable<boolean> = of(false);
@@ -75,7 +81,9 @@ export class VorgangDetailBescheidenResultComponent implements OnInit {
       this.bescheidService.getCreateBescheidDocumentInProgress();
     this.bescheidDocument$ = this.bescheidService.getBescheidDocument();
 
-    this.activeStep$ = this.formService.getActiveStep();
+    this.activeStep$ = this.formService
+      .getActiveStep()
+      .pipe(this.ifNotLastStep(() => this.resetSend()));
     this.bescheid$ = this.formService.getBescheidChanges();
     this.sendByManual$ = this.formService.isSendByManual();
 
@@ -94,6 +102,23 @@ export class VorgangDetailBescheidenResultComponent implements OnInit {
     this.showMissingBescheidDocumentError$ = this.formService.getShowMissingBescheidDocumentError();
   }
 
+  ifNotLastStep(doIt: () => void): OperatorFunction<number, number> {
+    return (source: Observable<number>) => {
+      return source.pipe(
+        tap((step: number) => {
+          if (step < VorgangDetailBescheidenResultComponent.LAST_STEP) {
+            doIt();
+          }
+        }),
+      );
+    };
+  }
+
+  resetSend(): void {
+    this.saveAndSendInProgress$ = of(createEmptyStateResource<CommandResource>());
+    this.sendWithNachricht$ = of(createEmptyStateResource<CommandResource>());
+  }
+
   public deleteBescheidDocument(): void {
     this.formService.clearBescheidDocumentFile();
     this.bescheidService.deleteBescheidDocument();
@@ -107,17 +132,17 @@ export class VorgangDetailBescheidenResultComponent implements OnInit {
   }
 
   public saveAndSendWithNachricht(bescheidDraft: BescheidResource): void {
-    this.saveAndSendInProgress$ = this.doUpdateAndSend(bescheidDraft, (bescheidResource) =>
-      this.bescheidService.sendBescheidToAntragsteller(bescheidResource),
-    );
+    this.saveAndSendInProgress$ = this.doUpdateAndSend(bescheidDraft, (bescheidResource) => {
+      this.sendWithNachricht$ = this.bescheidService.sendBescheidToAntragsteller(bescheidResource);
+      return this.sendWithNachricht$;
+    });
   }
 
   doUpdateAndSend(
     bescheidDraft: BescheidResource,
     send: sendBescheid,
   ): Observable<StateResource<CommandResource>> {
-    return this.formService.submit().pipe(
-      switchMapCommandSuccessfullyDone(() => send(bescheidDraft)),
+    return this.formService.submit(this.doSendAfterSuccessfullyUpdate(bescheidDraft, send)).pipe(
       tapOnCommandSuccessfullyDone((commandStateResource: StateResource<CommandResource>) => {
         if (this.isSendBescheidCommand(commandStateResource)) {
           this.closeDialog.emit();
@@ -126,6 +151,13 @@ export class VorgangDetailBescheidenResultComponent implements OnInit {
     );
   }
 
+  doSendAfterSuccessfullyUpdate(
+    bescheidDraft: BescheidResource,
+    send: sendBescheid,
+  ): OperatorFunction<StateResource<Resource>, StateResource<Resource>> {
+    return switchMapCommandSuccessfullyDone(() => send(bescheidDraft));
+  }
+
   private isSendBescheidCommand(commandStateResource: StateResource<CommandResource>): boolean {
     return commandStateResource.resource.order == CommandOrder.SEND_BESCHEID;
   }
diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/bescheid/Bescheid.java b/alfa-service/src/main/java/de/ozgcloud/alfa/bescheid/Bescheid.java
index 67cb7eb4c7f5432aa2433a65b784c788f4b9869c..76d8324789bfcec50208634004b8082eef732414 100644
--- a/alfa-service/src/main/java/de/ozgcloud/alfa/bescheid/Bescheid.java
+++ b/alfa-service/src/main/java/de/ozgcloud/alfa/bescheid/Bescheid.java
@@ -1,7 +1,10 @@
 package de.ozgcloud.alfa.bescheid;
 
+import static de.ozgcloud.alfa.common.ValidationMessageCodes.*;
+
 import java.util.List;
 
+import jakarta.validation.constraints.NotEmpty;
 import jakarta.validation.constraints.NotNull;
 
 import com.fasterxml.jackson.annotation.JsonIgnore;
@@ -53,7 +56,9 @@ public class Bescheid implements CommandBody {
 
 	@LinkedResource(controllerClass = BinaryFileController.class)
 	private List<FileId> attachments;
+	@NotEmpty(message = FIELD_IS_EMPTY, groups = BescheidNachrichtValidation.class)
 	private String nachrichtText;
+	@NotEmpty(message = FIELD_IS_EMPTY, groups = BescheidNachrichtValidation.class)
 	private String nachrichtSubject;
 	private SendBy sendBy;
 	private BescheidStatus status;
diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/bescheid/BescheidCommandController.java b/alfa-service/src/main/java/de/ozgcloud/alfa/bescheid/BescheidCommandController.java
new file mode 100644
index 0000000000000000000000000000000000000000..bbafe89749c95817519ef54be25ff303950b84c0
--- /dev/null
+++ b/alfa-service/src/main/java/de/ozgcloud/alfa/bescheid/BescheidCommandController.java
@@ -0,0 +1,47 @@
+package de.ozgcloud.alfa.bescheid;
+
+import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.*;
+
+import org.springframework.hateoas.EntityModel;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import de.ozgcloud.alfa.common.command.Command;
+import de.ozgcloud.alfa.common.command.CommandController;
+import de.ozgcloud.alfa.common.command.CommandService;
+import de.ozgcloud.alfa.common.command.CreateCommand;
+import de.ozgcloud.common.errorhandling.TechnicalException;
+import lombok.RequiredArgsConstructor;
+
+@RestController
+@RequestMapping(BescheidCommandController.PATH)
+@RequiredArgsConstructor
+class BescheidCommandController {
+
+	static final String PATH = "/api/vorgangs/{vorgangId}/bescheids/{bescheidId}/{bescheidVersion}/commands"; // NOSONAR
+
+	private final BescheidService bescheidService;
+	private final CommandService commandService;
+	private final BescheidSendenCommandValidator bescheidSendenCommandValidator;
+
+	@PostMapping
+	public ResponseEntity<EntityModel<Command>> createCommand(@PathVariable String vorgangId, @PathVariable String bescheidId,
+			@PathVariable long bescheidVersion, @RequestBody CreateCommand command) {
+		command = command.toBuilder().vorgangId(vorgangId).relationId(bescheidId).build();
+
+		validate(vorgangId, command);
+
+		var created = commandService.createCommand(command, bescheidVersion);
+		return ResponseEntity.created(linkTo(CommandController.class).slash(created.getId()).toUri()).build();
+	}
+
+	void validate(String vorgangId, CreateCommand command) {
+		var bescheid = bescheidService.getBescheidDraft(vorgangId)
+				.orElseThrow(() -> new TechnicalException("BescheidDraft not found"));
+		bescheidSendenCommandValidator.validate(command.toBuilder().body(bescheid).build());
+	}
+}
diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/bescheid/BescheidModelAssembler.java b/alfa-service/src/main/java/de/ozgcloud/alfa/bescheid/BescheidModelAssembler.java
index f8d3c4a12eb145cdc898cf59d783f01e8c0d935c..c0f66edba7f3ef926872008c378d0e586a105fbd 100644
--- a/alfa-service/src/main/java/de/ozgcloud/alfa/bescheid/BescheidModelAssembler.java
+++ b/alfa-service/src/main/java/de/ozgcloud/alfa/bescheid/BescheidModelAssembler.java
@@ -61,6 +61,9 @@ public class BescheidModelAssembler implements RepresentationModelAssembler<Besc
 		var attachmentsLink = linkTo(methodOn(BescheidController.class).getAttachments(bescheid.getId(), bescheid.getVorgangId()));
 		var createCommandLink = buildCreateCommandLink(bescheid);
 		var vorgangWithEingang = vorgangController.getVorgang(bescheid.getVorgangId());
+		var bescheidenUndSendenLink = linkTo(
+				methodOn(BescheidCommandController.class).createCommand(vorgangWithEingang.getId(), bescheid.getId(), bescheid.getVersion(),
+						null));
 
 		return ModelBuilder.fromEntity(bescheid)
 				.addLink(selfLink.withSelfRel())
@@ -75,7 +78,7 @@ public class BescheidModelAssembler implements RepresentationModelAssembler<Besc
 				.addLink(createCommandLink.withRel(REL_CREATE_DOCUMENT))
 				.addLink(createCommandLink.withRel(REL_CREATE_DOCUMENT_FROM_FILE))
 				.ifMatch(() -> canSendMessageToAntragsteller(vorgangWithEingang))
-				.addLink(createCommandLink.withRel(REL_BESCHEIDEN_UND_SENDEN))
+				.addLink(bescheidenUndSendenLink.withRel(REL_BESCHEIDEN_UND_SENDEN))
 				.addLink(createCommandLink.withRel(REL_BESCHEIDEN))
 				.buildModel();
 	}
diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/bescheid/BescheidNachrichtValidation.java b/alfa-service/src/main/java/de/ozgcloud/alfa/bescheid/BescheidNachrichtValidation.java
new file mode 100644
index 0000000000000000000000000000000000000000..13e50b003feb81845b571a78148235252d852457
--- /dev/null
+++ b/alfa-service/src/main/java/de/ozgcloud/alfa/bescheid/BescheidNachrichtValidation.java
@@ -0,0 +1,4 @@
+package de.ozgcloud.alfa.bescheid;
+
+interface BescheidNachrichtValidation {
+}
diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/bescheid/BescheidSendenCommandValidator.java b/alfa-service/src/main/java/de/ozgcloud/alfa/bescheid/BescheidSendenCommandValidator.java
new file mode 100644
index 0000000000000000000000000000000000000000..f304a0428a6a923900e5ba657d16cc8faea20d6f
--- /dev/null
+++ b/alfa-service/src/main/java/de/ozgcloud/alfa/bescheid/BescheidSendenCommandValidator.java
@@ -0,0 +1,17 @@
+package de.ozgcloud.alfa.bescheid;
+
+import jakarta.validation.Valid;
+
+import org.springframework.stereotype.Component;
+import org.springframework.validation.annotation.Validated;
+
+import de.ozgcloud.alfa.common.command.CreateCommand;
+
+@Validated(BescheidNachrichtValidation.class)
+@Component
+class BescheidSendenCommandValidator {
+
+	public void validate(@Valid CreateCommand command) {
+		// noop
+	}
+}
diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/bescheid/BescheidModelAssemblerTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/bescheid/BescheidModelAssemblerTest.java
index 4372f02417565a329e9fe8b3b25bc5b7556e2611..159f038b04b56863c3532950ec5ebef062bf48f4 100644
--- a/alfa-service/src/test/java/de/ozgcloud/alfa/bescheid/BescheidModelAssemblerTest.java
+++ b/alfa-service/src/test/java/de/ozgcloud/alfa/bescheid/BescheidModelAssemblerTest.java
@@ -177,7 +177,7 @@ class BescheidModelAssemblerTest {
 
 			assertThat(model.getLink(REL_BESCHEIDEN_UND_SENDEN))
 					.isPresent().get()
-					.extracting(Link::getHref).isEqualTo(createCommandLink());
+					.extracting(Link::getHref).isEqualTo(bescheidenUndSendenLink());
 		}
 
 		@Test
@@ -225,6 +225,11 @@ class BescheidModelAssemblerTest {
 					.expand(VorgangHeaderTestFactory.ID, BescheidTestFactory.ID, BescheidTestFactory.VERSION).toString();
 		}
 
+		private String bescheidenUndSendenLink() {
+			return new UriTemplate(BescheidCommandController.PATH)
+					.expand(VorgangHeaderTestFactory.ID, BescheidTestFactory.ID, BescheidTestFactory.VERSION).toString();
+		}
+
 		private EntityModel<Bescheid> callToModel() {
 			return callToModel(bescheid);
 		}
@@ -240,6 +245,8 @@ class BescheidModelAssemblerTest {
 
 		@Test
 		void shouldCallToModel() {
+			when(vorgangController.getVorgang(VorgangHeaderTestFactory.ID)).thenReturn(VorgangWithEingangTestFactory.create());
+
 			callMethod();
 
 			verify(assembler).toCollectionModel(List.of(bescheid));
@@ -257,6 +264,8 @@ class BescheidModelAssemblerTest {
 
 		@Test
 		void shouldHaveSelfLink() {
+			when(vorgangController.getVorgang(VorgangHeaderTestFactory.ID)).thenReturn(VorgangWithEingangTestFactory.create());
+
 			var collectionModel = callMethod();
 
 			assertThat(collectionModel.getLinks())
diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/bescheid/BescheidSendenCommandControllerTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/bescheid/BescheidSendenCommandControllerTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..5bb9c0e7cc0eb3b363e62f723ab4c7cafc224f99
--- /dev/null
+++ b/alfa-service/src/test/java/de/ozgcloud/alfa/bescheid/BescheidSendenCommandControllerTest.java
@@ -0,0 +1,183 @@
+package de.ozgcloud.alfa.bescheid;
+
+import static de.ozgcloud.alfa.common.command.CommandController.*;
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.Mockito.*;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
+
+import java.util.Optional;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+import org.springframework.http.MediaType;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.ResultActions;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+
+import de.ozgcloud.alfa.common.command.Command;
+import de.ozgcloud.alfa.common.command.CommandOrder;
+import de.ozgcloud.alfa.common.command.CommandService;
+import de.ozgcloud.alfa.common.command.CommandTestFactory;
+import de.ozgcloud.alfa.common.command.CreateCommand;
+import de.ozgcloud.alfa.vorgang.VorgangHeaderTestFactory;
+import de.ozgcloud.common.errorhandling.TechnicalException;
+import lombok.SneakyThrows;
+
+class BescheidSendenCommandControllerTest {
+
+	@Spy
+	@InjectMocks
+	private BescheidCommandController controller;
+
+	@Mock
+	private BescheidService bescheidService;
+	@Mock
+	private CommandService commandService;
+
+	@Mock
+	private BescheidSendenCommandValidator bescheidSendenCommandValidator;
+
+	private MockMvc mockMvc;
+
+	@BeforeEach
+	void setUp() {
+		mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
+	}
+
+	@Nested
+	class TestCreateCommand {
+
+		private final Command command = CommandTestFactory.create();
+
+		@Captor
+		private ArgumentCaptor<CreateCommand> createCommandArgumentCaptor;
+
+		@BeforeEach
+		void setUp() {
+			doNothing().when(controller).validate(eq(VorgangHeaderTestFactory.ID), any(CreateCommand.class));
+			when(commandService.createCommand(any(CreateCommand.class), eq(BescheidTestFactory.VERSION))).thenReturn(command);
+		}
+
+		@SneakyThrows
+		@Test
+		void shouldValidate() {
+			doRequest();
+
+			verify(controller).validate(eq(VorgangHeaderTestFactory.ID), any(CreateCommand.class));
+		}
+
+		@SneakyThrows
+		@Test
+		void shouldSetVorgangIdOnCreateCommand() {
+			doRequest();
+
+			verify(controller).validate(eq(VorgangHeaderTestFactory.ID), createCommandArgumentCaptor.capture());
+			assertThat(createCommandArgumentCaptor.getValue().getVorgangId()).isEqualTo(VorgangHeaderTestFactory.ID);
+		}
+
+		@SneakyThrows
+		@Test
+		void shouldSetRelationIdOnCreateCommand() {
+			doRequest();
+
+			verify(controller).validate(eq(VorgangHeaderTestFactory.ID), createCommandArgumentCaptor.capture());
+			assertThat(createCommandArgumentCaptor.getValue().getRelationId()).isEqualTo(BescheidTestFactory.ID);
+		}
+
+		@SneakyThrows
+		@Test
+		void shouldCallCommandService() {
+			doRequest();
+
+			verify(commandService).createCommand(any(CreateCommand.class), eq(BescheidTestFactory.VERSION));
+		}
+
+		@SneakyThrows
+		@Test
+		void shouldReturnCreated() {
+			var response = doRequest();
+
+			response.andExpect(status().isCreated());
+		}
+
+		@SneakyThrows
+		@Test
+		void shouldReturnCommand() {
+			doRequest()
+					.andExpect(header().stringValues("location", "http://localhost" + COMMANDS_PATH + "/" + CommandTestFactory.ID));
+		}
+
+		@SneakyThrows
+		private ResultActions doRequest() {
+			return mockMvc.perform(
+					post(BescheidCommandController.PATH,
+							VorgangHeaderTestFactory.ID,
+							BescheidTestFactory.ID,
+							BescheidTestFactory.VERSION)
+							.content(CommandTestFactory.buildCreateCommandContent(CommandOrder.SEND_BESCHEID))
+							.contentType(MediaType.APPLICATION_JSON));
+		}
+
+	}
+
+	@Nested
+	class TestValidate {
+
+		private final CreateCommand createCommand = CommandTestFactory.createCreateCommand();
+		private final Bescheid bescheid = BescheidTestFactory.create();
+
+		@Captor
+		private ArgumentCaptor<CreateCommand> commandArgumentCaptor;
+
+		@Nested
+		class WhenBescheidExists {
+
+			@BeforeEach
+			void setUp() {
+				when(bescheidService.getBescheidDraft(VorgangHeaderTestFactory.ID)).thenReturn(Optional.of(bescheid));
+				doNothing().when(bescheidSendenCommandValidator).validate(any(CreateCommand.class));
+			}
+
+			@Test
+			void shouldGetBescheidDraft() {
+				controller.validate(VorgangHeaderTestFactory.ID, createCommand);
+
+				verify(bescheidService).getBescheidDraft(VorgangHeaderTestFactory.ID);
+			}
+
+			@Test
+			void shouldValidate() {
+				controller.validate(VorgangHeaderTestFactory.ID, createCommand);
+
+				verify(bescheidSendenCommandValidator).validate(any(CreateCommand.class));
+			}
+
+			@Test
+			void shouldAddBescheidToCommand() {
+				controller.validate(VorgangHeaderTestFactory.ID, createCommand);
+
+				verify(bescheidSendenCommandValidator).validate(commandArgumentCaptor.capture());
+				assertThat(commandArgumentCaptor.getValue()).usingRecursiveComparison().isEqualTo(createCommand.toBuilder().body(bescheid).build());
+			}
+		}
+
+		@Nested
+		class WhenBescheidNotExists {
+
+			@Test
+			void shouldThrowTechnicalException() {
+				when(bescheidService.getBescheidDraft(VorgangHeaderTestFactory.ID)).thenReturn(Optional.empty());
+
+				assertThatThrownBy(() -> controller.validate(VorgangHeaderTestFactory.ID, createCommand)).isInstanceOf(TechnicalException.class);
+			}
+		}
+	}
+
+}
\ No newline at end of file
diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/common/command/CommandITCase.java b/alfa-service/src/test/java/de/ozgcloud/alfa/common/command/CommandITCase.java
index 38bcfb3ea39aaa6bed30d27089e6b557076e5a40..7ee0005a679ae552bd6e78cdc24ae00e6ab99213 100644
--- a/alfa-service/src/test/java/de/ozgcloud/alfa/common/command/CommandITCase.java
+++ b/alfa-service/src/test/java/de/ozgcloud/alfa/common/command/CommandITCase.java
@@ -94,7 +94,7 @@ public class CommandITCase {
 		}
 
 		private String createContent() {
-			return TestUtils.loadTextFile("jsonTemplates/command/createCommandWithBody.json.tmpl", CommandOrder.ASSIGN_USER.name(),
+			return CommandTestFactory.buildCreateCommandWithBodyContent(CommandOrder.ASSIGN_USER,
 					TestUtils.loadTextFile("jsonTemplates/command/commandAssignedToBody",
 							TestUtils.addQuote("/api/users/" + UserProfileTestFactory.ID.toString())));
 		}
@@ -299,9 +299,9 @@ public class CommandITCase {
 		ResultActions doRequest(String content) throws Exception {
 			return mockMvc.perform(post("/api/vorgangs/" + CommandTestFactory.VORGANG_ID + "/relations/" + CommandTestFactory.RELATION_ID + "/"
 					+ CommandTestFactory.RELATION_VERSION + "/commands")
-							.with(csrf())
-							.contentType(MediaType.APPLICATION_JSON)
-							.content(content));
+					.with(csrf())
+					.contentType(MediaType.APPLICATION_JSON)
+					.content(content));
 		}
 	}
 }
\ No newline at end of file
diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/common/command/CommandTestFactory.java b/alfa-service/src/test/java/de/ozgcloud/alfa/common/command/CommandTestFactory.java
index ddeae6623ab16ea0ee506f310ad96220561ea451..614a48500ac9dadb18ccf9a135b7f769fbbb7e32 100644
--- a/alfa-service/src/test/java/de/ozgcloud/alfa/common/command/CommandTestFactory.java
+++ b/alfa-service/src/test/java/de/ozgcloud/alfa/common/command/CommandTestFactory.java
@@ -79,4 +79,18 @@ public class CommandTestFactory {
 	public static String buildCreateVorgangCommandContent(String order) {
 		return TestUtils.loadTextFile("jsonTemplates/command/createVorgangCommand.json.tmpl", order);
 	}
+
+	public static String buildCreateCommandContent(CommandOrder order) {
+		return TestUtils.loadTextFile("jsonTemplates/command/createCommandWithBody.json.tmpl",
+				order.name(),
+				null);
+
+	}
+
+	public static String buildCreateCommandWithBodyContent(CommandOrder order, String body) {
+		return TestUtils.loadTextFile("jsonTemplates/command/createCommandWithBody.json.tmpl",
+				order.name(),
+				body);
+
+	}
 }
\ No newline at end of file
diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/PostfachMailCommandControllerTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/PostfachMailCommandControllerTest.java
index c074c935bd8cbb0a52a34fce1600e0f577247bdf..55d5e8e1fe0fc5dbf439fe49a21010bc182881ff 100644
--- a/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/PostfachMailCommandControllerTest.java
+++ b/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/PostfachMailCommandControllerTest.java
@@ -159,7 +159,7 @@ class PostfachMailCommandControllerTest {
 		private ResultActions doRequest(CommandOrder order) {
 			return mockMvc.perform(post("/api/postfachMails/" + PostfachMailTestFactory.ID + "/commands")
 					.contentType(MediaType.APPLICATION_JSON)
-					.content(PostfachMailTestFactory.buildCreateCommandPostfachNachrichtContent(order)));
+					.content(CommandTestFactory.buildCreateCommandWithBodyContent(order, "{}")));
 		}
 	}
 }
\ No newline at end of file
diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/PostfachMailTestFactory.java b/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/PostfachMailTestFactory.java
index cd7b4ecdc14bbe650f2e49642233fffab1fc1a31..11d1d0ed7bb0c9aaf6b013b018346aa79c7169f6 100644
--- a/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/PostfachMailTestFactory.java
+++ b/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/PostfachMailTestFactory.java
@@ -112,8 +112,4 @@ public class PostfachMailTestFactory {
 		var fileId = postfachMail.getAttachments().get(0).toString();
 		return "[\"api/binaryFiles/" + fileId + "\"]";
 	}
-
-	public static String buildCreateCommandPostfachNachrichtContent(CommandOrder order) {
-		return TestUtils.loadTextFile("jsonTemplates/command/createCommandWithBody.json.tmpl", order.name(), "{}");
-	}
 }
\ No newline at end of file