diff --git a/alfa-client/apps/admin/src/app/app.component.html b/alfa-client/apps/admin/src/app/app.component.html
index e504907b9ccb1ec0508e433b30f040f7ca174f99..f9f6573f38f14c261b0d6c431ad1fb0a1cd327c5 100644
--- a/alfa-client/apps/admin/src/app/app.component.html
+++ b/alfa-client/apps/admin/src/app/app.component.html
@@ -2,18 +2,22 @@
   <header class="flex items-center justify-between bg-white p-6" data-test-id="admin-header">
     <div class="text-ozgblue font-extrabold">OZG-Cloud Administration</div>
     <div>
-	  <user-profile-button-container data-test-id="user-profile-button"></user-profile-button-container>
+      <user-profile-button-container
+        data-test-id="user-profile-button"
+      ></user-profile-button-container>
     </div>
   </header>
   <div class="relative flex w-full flex-auto justify-center">
-    <div class="w-96 bg-slate-300 p-6">
-		<nav>
-			NAV
-		</nav>
-	</div>
+    <div class="w-60 bg-slate-100 p-6">
+      <nav>
+        <postfach-navigation-item
+          data-test-id="postfach-navigation-item"
+        ></postfach-navigation-item>
+      </nav>
+    </div>
     <main class="flex-auto bg-slate-200 p-6">
-		<router-outlet></router-outlet>
+      <router-outlet></router-outlet>
     </main>
   </div>
   <span data-test-id="build-version">Version: {{ apiRoot.buildVersion }}</span>
-</ng-container>
\ No newline at end of file
+</ng-container>
diff --git a/alfa-client/apps/admin/src/app/app.component.spec.ts b/alfa-client/apps/admin/src/app/app.component.spec.ts
index 29671cb8504f5d6630a96f8b757de417386b917b..0fd3f5bb0cc54356d34ab02ddcff92a344d730bc 100644
--- a/alfa-client/apps/admin/src/app/app.component.spec.ts
+++ b/alfa-client/apps/admin/src/app/app.component.spec.ts
@@ -10,6 +10,7 @@ import { of } from 'rxjs';
 import { createApiRootResource } from 'libs/api-root-shared/test/api-root';
 import { MockComponent } from 'ng-mocks';
 import { UserProfileButtonContainerComponent } from '../common/user-profile-button-container/user-profile.button-container.component';
+import { PostfachNavigationItemComponent } from '../pages/postfach/postfach-navigation-item/postfach-navigation-item.component';
 
 describe('AppComponent', () => {
   let component: AppComponent;
@@ -18,13 +19,18 @@ describe('AppComponent', () => {
   const adminHeader: string = getDataTestIdOf('admin-header');
   const buildVersion: string = getDataTestIdOf('build-version');
   const userProfileButton: string = getDataTestIdOf('user-profile-button');
+  const postfachNavigationItem: string = getDataTestIdOf('postfach-navigation-item');
 
   const authService: Mock<AuthService> = mock(AuthService);
   const apiRootService: Mock<ApiRootService> = mock(ApiRootService);
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      declarations: [AppComponent, MockComponent(UserProfileButtonContainerComponent)],
+      declarations: [
+        AppComponent,
+        MockComponent(UserProfileButtonContainerComponent),
+        MockComponent(PostfachNavigationItemComponent),
+      ],
       imports: [RouterTestingModule],
       providers: [
         {
@@ -94,6 +100,17 @@ describe('AppComponent', () => {
     });
   });
 
+  describe('navigation', () => {
+    beforeEach(() => {
+      component.apiRoot$ = of(createStateResource(createApiRootResource()));
+    });
+    it('should have postfach item', () => {
+      fixture.detectChanges();
+
+      existsAsHtmlElement(fixture, postfachNavigationItem);
+    });
+  });
+
   describe('build version', () => {
     beforeEach(() => {
       component.apiRoot$ = of(createStateResource(createApiRootResource()));
diff --git a/alfa-client/apps/admin/src/app/app.module.ts b/alfa-client/apps/admin/src/app/app.module.ts
index 1c61909253212188bb0e527b6238e60c33f3ddae..e13deaf980ec4811058fd72666bd6a47659f2c47 100644
--- a/alfa-client/apps/admin/src/app/app.module.ts
+++ b/alfa-client/apps/admin/src/app/app.module.ts
@@ -16,11 +16,19 @@ import { environment } from '../environments/environment';
 import { AppComponent } from './app.component';
 import { initializeKeycloak } from './app.config';
 import { appRoutes } from './app.routes';
+import { PostfachPageComponent } from '../pages/postfach/postfach-page/postfach-page.component';
 import { FormsModule, ReactiveFormsModule } from '@angular/forms';
 import { UserProfileButtonContainerComponent } from '../common/user-profile-button-container/user-profile.button-container.component';
+import { AdminSettingsModule } from '@admin-client/admin-settings';
+import { PostfachNavigationItemComponent } from '../pages/postfach/postfach-navigation-item/postfach-navigation-item.component';
 
 @NgModule({
-  declarations: [AppComponent, UserProfileButtonContainerComponent],
+  declarations: [
+    AppComponent,
+    PostfachPageComponent,
+    UserProfileButtonContainerComponent,
+    PostfachNavigationItemComponent,
+  ],
   imports: [
     CommonModule,
     TestbtnComponent,
@@ -37,6 +45,7 @@ import { UserProfileButtonContainerComponent } from '../common/user-profile-butt
     StoreRouterConnectingModule.forRoot(),
     FormsModule,
     ReactiveFormsModule,
+    AdminSettingsModule,
   ],
   providers: [
     {
diff --git a/alfa-client/apps/admin/src/app/app.routes.ts b/alfa-client/apps/admin/src/app/app.routes.ts
index 8762dfe2c6510c01425b35c6cf76371cc0b332c6..1834aa696228932a34d0b76ea2398d7e6a80b9c6 100644
--- a/alfa-client/apps/admin/src/app/app.routes.ts
+++ b/alfa-client/apps/admin/src/app/app.routes.ts
@@ -1,3 +1,15 @@
 import { Route } from '@angular/router';
+import { PostfachPageComponent } from '../pages/postfach/postfach-page/postfach-page.component';
 
-export const appRoutes: Route[] = [];
+export const appRoutes: Route[] = [
+  {
+    path: '',
+    redirectTo: 'postfach',
+    pathMatch: 'full',
+  },
+  {
+    path: 'postfach',
+    component: PostfachPageComponent,
+    title: 'Admin | Postfach',
+  },
+];
diff --git a/alfa-client/apps/admin/src/assets/mail.svg b/alfa-client/apps/admin/src/assets/mail.svg
new file mode 100644
index 0000000000000000000000000000000000000000..510a1dc44dadd31e431e74cae39be8f248344465
--- /dev/null
+++ b/alfa-client/apps/admin/src/assets/mail.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="24" width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 14H4V8l8 5 8-5v10zm-8-7L4 6h16l-8 5z"/></svg>
\ No newline at end of file
diff --git a/alfa-client/apps/admin/src/main.ts b/alfa-client/apps/admin/src/main.ts
index 5d388e265a6adda237cd7b2c9650f0055ca1457d..5e03b925b784465a49e2f49ead63c0801124b6b0 100644
--- a/alfa-client/apps/admin/src/main.ts
+++ b/alfa-client/apps/admin/src/main.ts
@@ -1,22 +1,23 @@
 import { loadEnvironment } from '@alfa-client/environment-shared';
 import { enableProdMode } from '@angular/core';
 import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
-import { isNil } from 'lodash-es';
 import { AppModule } from './app/app.module';
+import { isNil } from 'lodash-es';
 import { environment } from './environments/environment';
 
 loadEnvironment(environment.environmentUrl).then((env) => {
-	if (isNil(env)) {
-		console.error('Connection Error: environment is undefined');
-		return;
-	}
-	if (env.production) {
-		enableProdMode();
-	}
-	console.info('init bootstrap application...');
-	//Für Standalone AppComponent
-	//bootstrapApplication(AppComponent, appConfig).catch(err => console.error(err));
-	platformBrowserDynamic()
-		.bootstrapModule(AppModule)
-		.catch((err) => console.log(err));
+  if (isNil(env?.production)) {
+    console.error('Connection Error: environment is ', env);
+    return;
+  }
+
+  if (env.production) {
+    enableProdMode();
+  }
+  console.info('init bootstrap application...');
+  //Für Standalone AppComponent
+  //bootstrapApplication(AppComponent, appConfig).catch(err => console.error(err));
+  platformBrowserDynamic()
+    .bootstrapModule(AppModule)
+    .catch((err) => console.log(err));
 });
diff --git a/alfa-client/apps/admin/src/pages/postfach/postfach-navigation-item/postfach-navigation-item.component.html b/alfa-client/apps/admin/src/pages/postfach/postfach-navigation-item/postfach-navigation-item.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..aeceb900769ddcc0a0c4865c1b50fc0bf86f7a7b
--- /dev/null
+++ b/alfa-client/apps/admin/src/pages/postfach/postfach-navigation-item/postfach-navigation-item.component.html
@@ -0,0 +1 @@
+<navigation-item name="Postfach" imageSrc="/assets/mail.svg" link="/postfach"></navigation-item>
diff --git a/alfa-client/apps/admin/src/pages/postfach/postfach-navigation-item/postfach-navigation-item.component.spec.ts b/alfa-client/apps/admin/src/pages/postfach/postfach-navigation-item/postfach-navigation-item.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d56e1f5c365d0aa5f650dcba1ae0345a3e41e8c9
--- /dev/null
+++ b/alfa-client/apps/admin/src/pages/postfach/postfach-navigation-item/postfach-navigation-item.component.spec.ts
@@ -0,0 +1,28 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { PostfachNavigationItemComponent } from './postfach-navigation-item.component';
+import { MockComponent } from 'ng-mocks';
+import { ReactiveFormsModule } from '@angular/forms';
+import { NavigationItemComponent } from '@admin-client/admin-settings';
+
+describe('PostfachPageComponent', () => {
+  let component: PostfachNavigationItemComponent;
+  let fixture: ComponentFixture<PostfachNavigationItemComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [PostfachNavigationItemComponent, MockComponent(NavigationItemComponent)],
+      imports: [ReactiveFormsModule],
+    }).compileComponents();
+  });
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(PostfachNavigationItemComponent);
+    component = fixture.componentInstance;
+
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/alfa-client/apps/admin/src/pages/postfach/postfach-navigation-item/postfach-navigation-item.component.ts b/alfa-client/apps/admin/src/pages/postfach/postfach-navigation-item/postfach-navigation-item.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4c4820aa819932b900cd38d56aeb455124937ff5
--- /dev/null
+++ b/alfa-client/apps/admin/src/pages/postfach/postfach-navigation-item/postfach-navigation-item.component.ts
@@ -0,0 +1,7 @@
+import { Component } from '@angular/core';
+
+@Component({
+  selector: 'postfach-navigation-item',
+  templateUrl: './postfach-navigation-item.component.html',
+})
+export class PostfachNavigationItemComponent {}
diff --git a/alfa-client/apps/admin/src/pages/postfach/postfach-page/postfach-page.component.html b/alfa-client/apps/admin/src/pages/postfach/postfach-page/postfach-page.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..f066382bdd23dcf46af0b372491f28b4ba678b06
--- /dev/null
+++ b/alfa-client/apps/admin/src/pages/postfach/postfach-page/postfach-page.component.html
@@ -0,0 +1 @@
+<postfach-container></postfach-container>
diff --git a/alfa-client/apps/admin/src/pages/postfach/postfach-page/postfach-page.component.spec.ts b/alfa-client/apps/admin/src/pages/postfach/postfach-page/postfach-page.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..8392b508a608c5dae1ba4c1edb6df5bf7e223114
--- /dev/null
+++ b/alfa-client/apps/admin/src/pages/postfach/postfach-page/postfach-page.component.spec.ts
@@ -0,0 +1,28 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { PostfachPageComponent } from './postfach-page.component';
+import { MockComponent } from 'ng-mocks';
+import { ReactiveFormsModule } from '@angular/forms';
+import { PostfachContainerComponent } from '@admin-client/admin-settings';
+
+describe('PostfachPageComponent', () => {
+  let component: PostfachPageComponent;
+  let fixture: ComponentFixture<PostfachPageComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [PostfachPageComponent, MockComponent(PostfachContainerComponent)],
+      imports: [ReactiveFormsModule],
+    }).compileComponents();
+  });
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(PostfachPageComponent);
+    component = fixture.componentInstance;
+
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/alfa-client/apps/admin/src/pages/postfach/postfach-page/postfach-page.component.ts b/alfa-client/apps/admin/src/pages/postfach/postfach-page/postfach-page.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..1d9a54ceddbd6e663477e382dbbff95d9ab13c66
--- /dev/null
+++ b/alfa-client/apps/admin/src/pages/postfach/postfach-page/postfach-page.component.ts
@@ -0,0 +1,7 @@
+import { Component } from '@angular/core';
+
+@Component({
+  selector: 'postfach-page',
+  templateUrl: './postfach-page.component.html',
+})
+export class PostfachPageComponent {}
diff --git a/alfa-client/libs/admin-settings/.eslintrc.json b/alfa-client/libs/admin-settings/.eslintrc.json
new file mode 100644
index 0000000000000000000000000000000000000000..adbe7ae2dfabd4a42804f00846baec80877f4c5c
--- /dev/null
+++ b/alfa-client/libs/admin-settings/.eslintrc.json
@@ -0,0 +1,25 @@
+{
+  "extends": ["../../.eslintrc.json"],
+  "ignorePatterns": ["!**/*"],
+  "overrides": [
+    {
+      "files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
+      "rules": {}
+    },
+    {
+      "files": ["*.ts", "*.tsx"],
+      "rules": {}
+    },
+    {
+      "files": ["*.js", "*.jsx"],
+      "rules": {}
+    },
+    {
+      "files": ["*.json"],
+      "parser": "jsonc-eslint-parser",
+      "rules": {
+        "@nx/dependency-checks": "error"
+      }
+    }
+  ]
+}
diff --git a/alfa-client/libs/admin-settings/README.md b/alfa-client/libs/admin-settings/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..01b723f8400c9c3dd0f79fe697c5b1be2441a3eb
--- /dev/null
+++ b/alfa-client/libs/admin-settings/README.md
@@ -0,0 +1,7 @@
+# admin-settings
+
+This library was generated with [Nx](https://nx.dev).
+
+## Running unit tests
+
+Run `nx test admin-settings` to execute the unit tests via [Jest](https://jestjs.io).
diff --git a/alfa-client/libs/admin-settings/jest.config.ts b/alfa-client/libs/admin-settings/jest.config.ts
new file mode 100644
index 0000000000000000000000000000000000000000..84427413b7cbe34595a96099da2cfafce5e69036
--- /dev/null
+++ b/alfa-client/libs/admin-settings/jest.config.ts
@@ -0,0 +1,23 @@
+/* eslint-disable */
+export default {
+  displayName: 'admin-settings',
+  preset: '../../jest.preset.js',
+  setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'],
+  globals: {},
+  coverageDirectory: '../../coverage/libs/admin-settings',
+  transform: {
+    '^.+\\.(ts|mjs|js|html)$': [
+      'jest-preset-angular',
+      {
+        tsconfig: '<rootDir>/tsconfig.spec.json',
+        stringifyContentPathRegex: '\\.(html|svg)$',
+      },
+    ],
+  },
+  transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'],
+  snapshotSerializers: [
+    'jest-preset-angular/build/serializers/no-ng-attributes',
+    'jest-preset-angular/build/serializers/ng-snapshot',
+    'jest-preset-angular/build/serializers/html-comment',
+  ],
+};
diff --git a/alfa-client/libs/admin-settings/project.json b/alfa-client/libs/admin-settings/project.json
new file mode 100644
index 0000000000000000000000000000000000000000..073f1bfb8ef6bc708062de6387ef1a3fd9e31dd6
--- /dev/null
+++ b/alfa-client/libs/admin-settings/project.json
@@ -0,0 +1,25 @@
+{
+  "name": "admin-settings",
+  "$schema": "../../node_modules/nx/schemas/project-schema.json",
+  "sourceRoot": "libs/admin-settings/src",
+  "projectType": "library",
+  "prefix": "admin",
+  "targets": {
+    "lint": {
+      "executor": "@nx/eslint:lint",
+      "outputs": ["{options.outputFile}"],
+      "options": {
+        "lintFilePatterns": ["libs/admin-settings/package.json"]
+      }
+    },
+    "test": {
+      "executor": "@nx/jest:jest",
+      "outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
+      "options": {
+        "jestConfig": "libs/admin-settings/jest.config.ts",
+        "passWithNoTests": true
+      }
+    }
+  },
+  "tags": []
+}
diff --git a/alfa-client/libs/admin-settings/src/index.ts b/alfa-client/libs/admin-settings/src/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c0ce9b0d2d421edb40ae3069ce1adcb3884b6d36
--- /dev/null
+++ b/alfa-client/libs/admin-settings/src/index.ts
@@ -0,0 +1,3 @@
+export * from './lib/admin-settings.module';
+export * from './lib/postfach/postfach-container/postfach-container.component';
+export * from './lib/shared/navigation-item/navigation-item.component';
diff --git a/alfa-client/libs/admin-settings/src/lib/admin-settings.module.spec.ts b/alfa-client/libs/admin-settings/src/lib/admin-settings.module.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..088fd75aa2076bf00593453f508704a6e6634344
--- /dev/null
+++ b/alfa-client/libs/admin-settings/src/lib/admin-settings.module.spec.ts
@@ -0,0 +1,14 @@
+import { TestBed } from '@angular/core/testing';
+import { AdminSettingsModule } from './admin-settings.module';
+
+describe('AdminSettingsModule', () => {
+  beforeEach(() => {
+    TestBed.configureTestingModule({
+      imports: [AdminSettingsModule],
+    });
+  });
+
+  it('should create', () => {
+    expect(AdminSettingsModule).toBeDefined();
+  });
+});
diff --git a/alfa-client/libs/admin-settings/src/lib/admin-settings.module.ts b/alfa-client/libs/admin-settings/src/lib/admin-settings.module.ts
new file mode 100644
index 0000000000000000000000000000000000000000..7e62764c345cbfc8915b7d11d2132e0e3382c83a
--- /dev/null
+++ b/alfa-client/libs/admin-settings/src/lib/admin-settings.module.ts
@@ -0,0 +1,21 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { TechSharedModule } from '@alfa-client/tech-shared';
+import { NavigationItemComponent } from './shared/navigation-item/navigation-item.component';
+import { RouterModule } from '@angular/router';
+import { ReactiveFormsModule } from '@angular/forms';
+import { PostfachContainerComponent } from './postfach/postfach-container/postfach-container.component';
+import { PostfachFormComponent } from './postfach/postfach-container/postfach-form/postfach-form.component';
+import { TextFieldComponent } from './shared/text-field/text-field.component';
+
+@NgModule({
+  declarations: [
+    PostfachContainerComponent,
+    PostfachFormComponent,
+    NavigationItemComponent,
+    TextFieldComponent,
+  ],
+  imports: [CommonModule, TechSharedModule, RouterModule, ReactiveFormsModule],
+  exports: [PostfachContainerComponent, NavigationItemComponent],
+})
+export class AdminSettingsModule {}
diff --git a/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-container.component.html b/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-container.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..f2e1c9803bf2ba4b38f629bdac9187c6a5d22a2c
--- /dev/null
+++ b/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-container.component.html
@@ -0,0 +1 @@
+<postfach-form></postfach-form>
diff --git a/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-container.component.scss b/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-container.component.scss
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-container.component.spec.ts b/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-container.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6d086752157a5429e787661c76783f5250df42e9
--- /dev/null
+++ b/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-container.component.spec.ts
@@ -0,0 +1,31 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { PostfachContainerComponent } from '@admin-client/admin-settings';
+
+import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
+import { ReactiveFormsModule, UntypedFormGroup } from '@angular/forms';
+
+import { PostfachFormComponent } from './postfach-form/postfach-form.component';
+import { MockComponent } from 'ng-mocks';
+
+describe('PostfachContainerComponent', () => {
+  let component: PostfachContainerComponent;
+  let fixture: ComponentFixture<PostfachContainerComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [PostfachContainerComponent, MockComponent(PostfachFormComponent)],
+      imports: [ReactiveFormsModule],
+    }).compileComponents();
+  });
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(PostfachContainerComponent);
+    component = fixture.componentInstance;
+
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-container.component.ts b/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-container.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6a9e73281ece58b6f3c416d8bd34a95d9eb9d217
--- /dev/null
+++ b/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-container.component.ts
@@ -0,0 +1,8 @@
+import { Component } from '@angular/core';
+
+@Component({
+  selector: 'postfach-container',
+  templateUrl: './postfach-container.component.html',
+  styleUrls: ['./postfach-container.component.scss'],
+})
+export class PostfachContainerComponent {}
diff --git a/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach-form.component.html b/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach-form.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..4ddfd2b7a927afdb4016395058ed22486429588a
--- /dev/null
+++ b/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach-form.component.html
@@ -0,0 +1,53 @@
+<form class="form flex-col" [formGroup]="formService.form">
+  <h1 class="text-2xl font-bold">Absender</h1>
+  <p id="absender-desc" class="p-1">Hinterlegen Sie Absenderinformationen zu Ihrem Postfach.</p>
+  <div aria-describedby="absender-desc" class="grid-col-1 mb-2 mt-2 grid w-96 gap-1">
+    <text-field
+      inputId="absender-name"
+	  data-test-id="absender-name"
+      label="Name"
+      [formControlName]="PostfachFormService.NAME_FIELD"
+    ></text-field>
+    <text-field
+      inputId="absender-anschrift"
+	  data-test-id="absender-anschrift"
+      label="Anschrift"
+      [formControlName]="PostfachFormService.ANSCHRIFT_FIELD"
+    ></text-field>
+    <text-field
+      inputId="absender-dienst"
+	  data-test-id="absender-dienst"
+      label="Dienst"
+      [formControlName]="PostfachFormService.DIENST_FIELD"
+    ></text-field>
+    <text-field
+      inputId="absender-mandant"
+	  data-test-id="absender-mandant"
+      label="Mandant"
+      [formControlName]="PostfachFormService.MANDANT_FIELD"
+    ></text-field>
+    <text-field
+      inputId="absender-gemeindeschluessel"
+	  data-test-id="absender-gemeindeschluessel"
+      label="Gemeindeschlüssel"
+      [formControlName]="PostfachFormService.GEMEINDESCHLUESSEL_FIELD"
+    ></text-field>
+  </div>
+  <div class="h-20"></div>
+  <h1 class="text-2xl font-bold">Signatur</h1>
+  <p id="signatur-desc">Erstellen oder ändern Sie die Signatur für Nachrichten.</p>
+  <textarea
+    data-test-id="signatur-text"
+    aria-describedby="signatur-desc"
+    [formControlName]="PostfachFormService.SIGNATUR_FIELD"
+    class="mb-2 mt-2 block h-40 w-96 p-1"
+  ></textarea>
+
+  <button
+    (click)="submit()"
+    data-test-id="save-button"
+    class="bg-ozgblue-700 hover:bg-ozgblue-600 active:bg-ozgblue-600/90 focus-visible:outline-ozgblue-800 rounded-md px-3 py-2 text-sm font-semibold text-white shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2"
+  >
+    Speichern
+  </button>
+</form>
diff --git a/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach-form.component.scss b/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach-form.component.scss
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach-form.component.spec.ts b/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach-form.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ee99eb6160254fa35e04559a9f11fa2bece3e8f4
--- /dev/null
+++ b/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach-form.component.spec.ts
@@ -0,0 +1,93 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { PostfachFormComponent } from './postfach-form.component';
+import { FormsModule, ReactiveFormsModule, UntypedFormGroup } from '@angular/forms';
+import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
+import {
+  dispatchEventFromFixture,
+  existsAsHtmlElement,
+  getElementFromFixture,
+} from '@alfa-client/test-utils';
+import { PostfachFormService } from './postfach.formservice';
+import { MockComponent } from 'ng-mocks';
+import { TextFieldComponent } from '../../../shared/text-field/text-field.component';
+
+describe('PostfachFormComponent', () => {
+  let component: PostfachFormComponent;
+  let fixture: ComponentFixture<PostfachFormComponent>;
+  let form: UntypedFormGroup;
+
+  const saveButton: string = getDataTestIdOf('save-button');
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [PostfachFormComponent, MockComponent(TextFieldComponent)],
+      imports: [ReactiveFormsModule, FormsModule],
+    }).compileComponents();
+  });
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(PostfachFormComponent);
+    component = fixture.componentInstance;
+    form = fixture.componentInstance.formService.form;
+
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+
+  describe('Absender section', () => {
+    const fields = [
+      [PostfachFormService.NAME_FIELD, 'Name', 'absender-name'],
+      [PostfachFormService.ANSCHRIFT_FIELD, 'Anschrift', 'absender-anschrift'],
+      [PostfachFormService.DIENST_FIELD, 'Dienst', 'absender-dienst'],
+      [PostfachFormService.MANDANT_FIELD, 'Mandant', 'absender-mandant'],
+      [
+        PostfachFormService.GEMEINDESCHLUESSEL_FIELD,
+        'Gemeindeschlüssel',
+        'absender-gemeindeschluessel',
+      ],
+    ];
+
+    test.each(fields)(
+      'should have label for field "%s" with name "%s"',
+      (fieldName, text, inputId) => {
+        const textFieldElement = getElementFromFixture(fixture, getDataTestIdOf(inputId));
+        expect(textFieldElement.getAttribute('label')).toBe(text);
+      },
+    );
+
+    test.each(fields)('should have inputId for field "%s"', (fieldName, text, inputId) => {
+      const textFieldElement = getElementFromFixture(fixture, getDataTestIdOf(inputId));
+      expect(textFieldElement.getAttribute('inputId')).toBe(inputId);
+    });
+  });
+
+  describe('Signatur section', () => {
+    const signaturTextarea = getDataTestIdOf('signatur-text');
+
+    it('should have signatur-text', () => {
+      existsAsHtmlElement(fixture, signaturTextarea);
+    });
+
+    it('should use form control for signatur-text', () => {
+      const someText = 'some signatur text';
+
+      form.get(PostfachFormService.SIGNATUR_FIELD).setValue(someText);
+
+      const signatur = getElementFromFixture(fixture, signaturTextarea);
+      expect(signatur.value).toBe(someText);
+    });
+  });
+
+  describe('save button', () => {
+    it('should call submit on click', () => {
+      component.submit = jest.fn();
+
+      dispatchEventFromFixture(fixture, saveButton, 'click');
+
+      expect(component.submit).toHaveBeenCalled();
+    });
+  });
+});
diff --git a/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach-form.component.ts b/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach-form.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f63f202379e5516f96668102acda229996af14f8
--- /dev/null
+++ b/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach-form.component.ts
@@ -0,0 +1,18 @@
+import { Component } from '@angular/core';
+import { PostfachFormService } from './postfach.formservice';
+
+@Component({
+  selector: 'postfach-form',
+  templateUrl: './postfach-form.component.html',
+  styleUrls: ['./postfach-form.component.scss'],
+  providers: [PostfachFormService],
+})
+export class PostfachFormComponent {
+  constructor(public formService: PostfachFormService) {}
+
+  protected readonly PostfachFormService = PostfachFormService;
+
+  public submit() {
+    this.formService.submit();
+  }
+}
diff --git a/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach.formservice.spec.ts b/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach.formservice.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..0927e3991e8386cae53cb79bd05ec7b1f8359d91
--- /dev/null
+++ b/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach.formservice.spec.ts
@@ -0,0 +1,16 @@
+import { FormBuilder } from '@angular/forms';
+import { PostfachFormService } from './postfach.formservice';
+
+describe('PostfachFormService', () => {
+  let formService: PostfachFormService;
+
+  const formBuilder: FormBuilder = new FormBuilder();
+
+  beforeEach(() => {
+    formService = new PostfachFormService(formBuilder);
+  });
+
+  it('should create', () => {
+    expect(formService).toBeTruthy();
+  });
+});
diff --git a/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach.formservice.ts b/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach.formservice.ts
new file mode 100644
index 0000000000000000000000000000000000000000..53829e1fce73f0d3dbb83fcb30d91fafc1a576d0
--- /dev/null
+++ b/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach.formservice.ts
@@ -0,0 +1,43 @@
+import {
+  AbstractFormService,
+  StateResource,
+  createEmptyStateResource,
+} from '@alfa-client/tech-shared';
+import { Injectable } from '@angular/core';
+import { FormControl, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
+import { Resource } from '@ngxp/rest';
+import { Observable, of } from 'rxjs';
+
+@Injectable()
+export class PostfachFormService extends AbstractFormService {
+  public static readonly NAME_FIELD: string = 'name';
+  public static readonly ANSCHRIFT_FIELD: string = 'anschrift';
+  public static readonly DIENST_FIELD: string = 'dienst';
+  public static readonly MANDANT_FIELD: string = 'mandant';
+  public static readonly GEMEINDESCHLUESSEL_FIELD: string = 'gemeindeschluessel';
+  public static readonly SIGNATUR_FIELD: string = 'signatur';
+
+  constructor(formBuilder: UntypedFormBuilder) {
+    super(formBuilder);
+  }
+
+  protected initForm(): UntypedFormGroup {
+    return this.formBuilder.group({
+      [PostfachFormService.NAME_FIELD]: new FormControl(),
+      [PostfachFormService.ANSCHRIFT_FIELD]: new FormControl(),
+      [PostfachFormService.DIENST_FIELD]: new FormControl(),
+      [PostfachFormService.MANDANT_FIELD]: new FormControl(),
+      [PostfachFormService.GEMEINDESCHLUESSEL_FIELD]: new FormControl(),
+      [PostfachFormService.SIGNATUR_FIELD]: new FormControl(),
+    });
+  }
+
+  protected doSubmit(): Observable<StateResource<Resource>> {
+    console.info('FormValue: ', this.getFormValue());
+    return of(createEmptyStateResource<Resource>());
+  }
+
+  protected getPathPrefix(): string {
+    return '';
+  }
+}
diff --git a/alfa-client/libs/admin-settings/src/lib/shared/navigation-item/navigation-item.component.html b/alfa-client/libs/admin-settings/src/lib/shared/navigation-item/navigation-item.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..c9f7e36c16335c9f94d205e9724542a219c62612
--- /dev/null
+++ b/alfa-client/libs/admin-settings/src/lib/shared/navigation-item/navigation-item.component.html
@@ -0,0 +1,9 @@
+<a
+  [routerLink]="link"
+  routerLinkActive="active-link"
+  data-test-id="anchor"
+  class="hover:bg-ozgblue-200 active:bg-ozgblue-200/75 flex items-center gap-4 rounded-full p-3 font-semibold"
+>
+	<img [src]="imageSrc" [alt]="name" class="w-6" [attr.data-test-id]="'image-' + name" />
+	<span [attr.data-test-id]="'navigation-label-' + name | convertForDataTest">{{ name }}</span>
+</a>
diff --git a/alfa-client/libs/admin-settings/src/lib/shared/navigation-item/navigation-item.component.scss b/alfa-client/libs/admin-settings/src/lib/shared/navigation-item/navigation-item.component.scss
new file mode 100644
index 0000000000000000000000000000000000000000..9214426c081848ac1a46efac41e715a120eeff02
--- /dev/null
+++ b/alfa-client/libs/admin-settings/src/lib/shared/navigation-item/navigation-item.component.scss
@@ -0,0 +1,3 @@
+.active-link:not(:hover):not(:active) {
+  @apply bg-ozgblue-100;
+}
diff --git a/alfa-client/libs/admin-settings/src/lib/shared/navigation-item/navigation-item.component.spec.ts b/alfa-client/libs/admin-settings/src/lib/shared/navigation-item/navigation-item.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e800d7acf9df48a08b81190c029858010e332ad3
--- /dev/null
+++ b/alfa-client/libs/admin-settings/src/lib/shared/navigation-item/navigation-item.component.spec.ts
@@ -0,0 +1,67 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ReactiveFormsModule } from '@angular/forms';
+import { NavigationItemComponent } from './navigation-item.component';
+import { getElementFromFixture } from '@alfa-client/test-utils';
+import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
+import { RouterTestingModule } from '@angular/router/testing';
+import { ConvertForDataTestPipe } from '@alfa-client/tech-shared';
+
+describe('NavigationItemComponent', () => {
+  let component: NavigationItemComponent;
+  let fixture: ComponentFixture<NavigationItemComponent>;
+
+  const anchorLink = getDataTestIdOf('anchor');
+  const navigationLabelName = 'test';
+  const image = getDataTestIdOf('image-' + navigationLabelName);
+  const label = getDataTestIdOf('navigation-label-' + navigationLabelName);
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [NavigationItemComponent, ConvertForDataTestPipe],
+      imports: [ReactiveFormsModule, RouterTestingModule],
+    }).compileComponents();
+  });
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(NavigationItemComponent);
+    component = fixture.componentInstance;
+    component.name = 'test';
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+
+  it('should use imageSrc input', () => {
+    const imageSrc = 'imagesrc';
+    component.imageSrc = imageSrc;
+
+    fixture.detectChanges();
+
+    const imageElement: HTMLImageElement = getElementFromFixture(fixture, image);
+    expect(imageElement.getAttribute('src')).toBe(imageSrc);
+  });
+
+  it('should use router link', () => {
+    const link = '/testroute';
+    component.link = link;
+
+    fixture.detectChanges();
+
+    const anchorElement: HTMLAnchorElement = getElementFromFixture(fixture, anchorLink);
+    expect(anchorElement.getAttribute('ng-reflect-router-link')).toBe(link);
+  });
+
+  describe('image name', () => {
+    it('should be used for alt', () => {
+      const imageElement = getElementFromFixture(fixture, image);
+      expect(imageElement.alt).toBe(navigationLabelName);
+    });
+
+    it('should be used for navigation-label', () => {
+      const labelElement = getElementFromFixture(fixture, label);
+      expect(labelElement.textContent).toBe(navigationLabelName);
+    });
+  });
+});
diff --git a/alfa-client/libs/admin-settings/src/lib/shared/navigation-item/navigation-item.component.ts b/alfa-client/libs/admin-settings/src/lib/shared/navigation-item/navigation-item.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f1b2e5f0f36c2575bf567d660fb63f1ff6da2938
--- /dev/null
+++ b/alfa-client/libs/admin-settings/src/lib/shared/navigation-item/navigation-item.component.ts
@@ -0,0 +1,15 @@
+import { Component, Input } from '@angular/core';
+
+@Component({
+  selector: 'navigation-item',
+  templateUrl: './navigation-item.component.html',
+  styleUrls: ['./navigation-item.component.scss'],
+})
+export class NavigationItemComponent {
+  @Input()
+  link: string;
+  @Input()
+  imageSrc: string;
+  @Input()
+  name = 'Navigations-Link';
+}
diff --git a/alfa-client/libs/admin-settings/src/lib/shared/text-field/text-field.component.html b/alfa-client/libs/admin-settings/src/lib/shared/text-field/text-field.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..c11e2cfdb73de1e35a9eb09c2e32846a8cbe4265
--- /dev/null
+++ b/alfa-client/libs/admin-settings/src/lib/shared/text-field/text-field.component.html
@@ -0,0 +1,8 @@
+<label class="grid grid-cols-2">
+  <span [attr.data-test-id]="'text-field-span-' + label | convertForDataTest">{{ label }}</span>
+  <input
+    [attr.data-test-id]="'text-field-input-' + label | convertForDataTest"
+    type="text"
+    [formControl]="fieldControl"
+  />
+</label>
diff --git a/alfa-client/libs/admin-settings/src/lib/shared/text-field/text-field.component.spec.ts b/alfa-client/libs/admin-settings/src/lib/shared/text-field/text-field.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..27baea4a3893bd7107800d210579220e9c621f93
--- /dev/null
+++ b/alfa-client/libs/admin-settings/src/lib/shared/text-field/text-field.component.spec.ts
@@ -0,0 +1,46 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { TextFieldComponent } from './text-field.component';
+import { getElementFromFixture } from '@alfa-client/test-utils';
+import { ReactiveFormsModule } from '@angular/forms';
+import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
+import { ConvertForDataTestPipe } from '@alfa-client/tech-shared';
+
+describe('TextFieldComponent', () => {
+  let component: TextFieldComponent;
+  let fixture: ComponentFixture<TextFieldComponent>;
+
+  const label = 'custom';
+  const span = getDataTestIdOf('text-field-span-' + label);
+  const input = getDataTestIdOf('text-field-input-' + label);
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [TextFieldComponent, ConvertForDataTestPipe],
+      imports: [ReactiveFormsModule],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(TextFieldComponent);
+    component = fixture.componentInstance;
+    component.label = label;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+
+  it('should use label', () => {
+    const labelElement = getElementFromFixture(fixture, span);
+    expect(labelElement.textContent).toBe(label);
+  });
+
+  it('should use form control', () => {
+    const fieldText = 'text';
+    component.writeValue(fieldText);
+
+    fixture.detectChanges();
+
+    const inputElement = getElementFromFixture(fixture, input);
+    expect(inputElement.value).toBe(fieldText);
+  });
+});
diff --git a/alfa-client/libs/admin-settings/src/lib/shared/text-field/text-field.component.ts b/alfa-client/libs/admin-settings/src/lib/shared/text-field/text-field.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..92abc83d9409865ee79be841d06d3b255c57ff3a
--- /dev/null
+++ b/alfa-client/libs/admin-settings/src/lib/shared/text-field/text-field.component.ts
@@ -0,0 +1,11 @@
+import { Component, Input } from '@angular/core';
+import { FormControlEditorAbstractComponent } from 'libs/ui/src/lib/ui/editor/formcontrol-editor.abstract.component';
+
+@Component({
+  selector: 'text-field',
+  templateUrl: './text-field.component.html',
+})
+export class TextFieldComponent extends FormControlEditorAbstractComponent {
+  @Input()
+  label: string;
+}
diff --git a/alfa-client/libs/admin-settings/src/test-setup.ts b/alfa-client/libs/admin-settings/src/test-setup.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e09d95a1bd4455db9bfd16809b94659c30a83956
--- /dev/null
+++ b/alfa-client/libs/admin-settings/src/test-setup.ts
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+import '@testing-library/jest-dom';
+import 'jest-preset-angular/setup-jest';
+
+import { getTestBed } from '@angular/core/testing';
+import {
+  BrowserDynamicTestingModule,
+  platformBrowserDynamicTesting,
+} from '@angular/platform-browser-dynamic/testing';
+
+getTestBed().resetTestEnvironment();
+getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), {
+  teardown: { destroyAfterEach: false },
+  errorOnUnknownProperties: true,
+  errorOnUnknownElements: true,
+});
diff --git a/alfa-client/libs/admin-settings/tsconfig.json b/alfa-client/libs/admin-settings/tsconfig.json
new file mode 100644
index 0000000000000000000000000000000000000000..03261df5a47903bb7d4de17fbef9e9a14b048bed
--- /dev/null
+++ b/alfa-client/libs/admin-settings/tsconfig.json
@@ -0,0 +1,16 @@
+{
+  "extends": "../../tsconfig.base.json",
+  "files": [],
+  "include": [],
+  "references": [
+    {
+      "path": "./tsconfig.lib.json"
+    },
+    {
+      "path": "./tsconfig.spec.json"
+    }
+  ],
+  "compilerOptions": {
+    "target": "es2020"
+  }
+}
diff --git a/alfa-client/libs/admin-settings/tsconfig.lib.json b/alfa-client/libs/admin-settings/tsconfig.lib.json
new file mode 100644
index 0000000000000000000000000000000000000000..dcc35a71ee8a26bc9394b9cf96b02996be26ec16
--- /dev/null
+++ b/alfa-client/libs/admin-settings/tsconfig.lib.json
@@ -0,0 +1,12 @@
+{
+  "extends": "./tsconfig.json",
+  "compilerOptions": {
+    "outDir": "../../dist/out-tsc",
+    "declaration": true,
+    "declarationMap": true,
+    "inlineSources": true,
+    "types": []
+  },
+  "exclude": ["src/test-setup.ts", "src/**/*.spec.ts", "jest.config.ts", "src/**/*.test.ts"],
+  "include": ["src/**/*.ts"]
+}
diff --git a/alfa-client/libs/admin-settings/tsconfig.spec.json b/alfa-client/libs/admin-settings/tsconfig.spec.json
new file mode 100644
index 0000000000000000000000000000000000000000..c3cb17f784fa2f7b9a4b0e7c9b03663500f4ee3d
--- /dev/null
+++ b/alfa-client/libs/admin-settings/tsconfig.spec.json
@@ -0,0 +1,12 @@
+{
+  "extends": "./tsconfig.json",
+  "compilerOptions": {
+    "outDir": "../../dist/out-tsc",
+    "module": "commonjs",
+    "types": ["jest", "node"],
+    "target": "ES2022",
+    "useDefineForClassFields": false
+  },
+  "files": ["src/test-setup.ts"],
+  "include": ["**/*.test.ts", "**/*.spec.ts", "**/*.d.ts", "jest.config.ts"]
+}
diff --git a/alfa-client/libs/api-root-shared/src/lib/api-root.linkrel.ts b/alfa-client/libs/api-root-shared/src/lib/api-root.linkrel.ts
index d8a70c20e7bccf6401fe08087ee4508002b14288..f4f18e65571d33e43ad0c3ea9f27a30107b9c463 100644
--- a/alfa-client/libs/api-root-shared/src/lib/api-root.linkrel.ts
+++ b/alfa-client/libs/api-root-shared/src/lib/api-root.linkrel.ts
@@ -51,6 +51,9 @@ export enum ApiRootLinkRel {
   ALL_WIEDERVORLAGEN = 'vorgaenge_wiedervorlagen_all',
   MY_WIEDERVORLAGEN = 'vorgaenge_wiedervorlagen_my',
   UNASSIGNED_WIEDERVORLAGEN = 'vorgaenge_wiedervorlagen_unassigned',
+  ALL_UNGELESENE_NACHRICHTEN = 'vorgaenge_ungelesene_nachrichten_all',
+  MY_UNGELESENE_NACHRICHTEN = 'vorgaenge_ungelesene_nachrichten_my',
+  UNASSIGNED_UNGELESENE_NACHRICHTEN = 'vorgaenge_ungelesene_nachrichten_unassigned',
   ALLE_VORGAENGE_ZU_LOESCHEN = 'vorgaenge_zu_loeschen_all',
   MEINE_VORGAENGE_ZU_LOESCHEN = 'vorgaenge_zu_loeschen_my',
   UNASSIGNED_ZU_LOESCHEN = 'vorgaenge_zu_loeschen_unassigned',
diff --git a/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.reducer.ts b/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.reducer.ts
index 94216faa5f7884f6fa1252e711f49e26d957462c..c7a5be544eed27c2ee84715549bd578f02b079c7 100644
--- a/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.reducer.ts
+++ b/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.reducer.ts
@@ -143,6 +143,7 @@ function createEmptyVorgangStatistic(): VorgangStatistic {
     },
     wiedervorlagen: null,
     existsWiedervorlageOverdue: false,
+    ungeleseneNachrichten: 0,
   };
 }
 
diff --git a/alfa-client/libs/vorgang-shared/src/lib/vorgang-navigation.util.ts b/alfa-client/libs/vorgang-shared/src/lib/vorgang-navigation.util.ts
index 67f6e3da2c32b30e3fe1140a25047b97196b193e..9214160eaabd1f68c97f33762312139fbe2241e9 100644
--- a/alfa-client/libs/vorgang-shared/src/lib/vorgang-navigation.util.ts
+++ b/alfa-client/libs/vorgang-shared/src/lib/vorgang-navigation.util.ts
@@ -42,6 +42,7 @@ export const BESCHIEDEN_ROUTE_PARAM: string = 'beschieden';
 export const ABGESCHLOSSEN_ROUTE_PARAM: string = 'abgeschlossen';
 export const VERWORFEN_ROUTE_PARAM: string = 'verworfen';
 export const WIEDERVORLAGEN_ROUTE_PARAM: string = 'wiedervorlagen';
+export const UNGELESENE_NACHRICHTEN_ROUTE_PARAM: string = 'ungelesene_nachrichten';
 export const ZU_LOESCHEN_ROUTE_PARAM: string = 'zu_loeschen';
 export const SEARCH_ROUTE_PARAM: string = 'search';
 
@@ -56,6 +57,7 @@ export const ROUTE_PARAM_BY_VORGANG_VIEW: { [view: string]: string } = {
   [VorgangView.VERWORFEN]: VERWORFEN_ROUTE_PARAM,
   [VorgangView.VORGANG_LIST]: EMPTY_STRING,
   [VorgangView.WIEDERVORLAGEN]: WIEDERVORLAGEN_ROUTE_PARAM,
+  [VorgangView.UNGELESENE_NACHRICHTEN]: UNGELESENE_NACHRICHTEN_ROUTE_PARAM,
   [VorgangView.ZU_LOESCHEN]: ZU_LOESCHEN_ROUTE_PARAM,
   [VorgangView.SEARCH]: SEARCH_ROUTE_PARAM,
 };
@@ -68,6 +70,7 @@ export const VORGANG_VIEW_BY_ROUTE_PARAM: { [routeParam: string]: VorgangView }
   [ABGESCHLOSSEN_ROUTE_PARAM]: VorgangView.ABGESCHLOSSEN,
   [VERWORFEN_ROUTE_PARAM]: VorgangView.VERWORFEN,
   [WIEDERVORLAGEN_ROUTE_PARAM]: VorgangView.WIEDERVORLAGEN,
+  [UNGELESENE_NACHRICHTEN_ROUTE_PARAM]: VorgangView.UNGELESENE_NACHRICHTEN,
   [ZU_LOESCHEN_ROUTE_PARAM]: VorgangView.ZU_LOESCHEN,
   [SEARCH_ROUTE_PARAM]: VorgangView.SEARCH,
 };
diff --git a/alfa-client/libs/vorgang-shared/src/lib/vorgang.model.ts b/alfa-client/libs/vorgang-shared/src/lib/vorgang.model.ts
index 41b412c9839bb98940bbdd55ea74e8fcd1e47cb3..c18d952fcec598790bc40eee1a0522742c0eccd3 100644
--- a/alfa-client/libs/vorgang-shared/src/lib/vorgang.model.ts
+++ b/alfa-client/libs/vorgang-shared/src/lib/vorgang.model.ts
@@ -109,6 +109,7 @@ export interface VorgangStatistic {
   byStatus: ByStatus;
   wiedervorlagen: number;
   existsWiedervorlageOverdue: boolean;
+  ungeleseneNachrichten: number;
 }
 
 export interface ByStatus {
@@ -163,6 +164,7 @@ export enum VorgangView {
   WIEDERVORLAGEN,
   SEARCH,
   ZU_LOESCHEN,
+  UNGELESENE_NACHRICHTEN,
 }
 
 export interface StatusCommandMap {
diff --git a/alfa-client/libs/vorgang-shared/test/vorgang.ts b/alfa-client/libs/vorgang-shared/test/vorgang.ts
index 743c5e65339cfc65091a3db158cdbf8664863b3c..8bddc8cc501bf26b18890d8106b0eef67dc3a3ff 100644
--- a/alfa-client/libs/vorgang-shared/test/vorgang.ts
+++ b/alfa-client/libs/vorgang-shared/test/vorgang.ts
@@ -145,6 +145,7 @@ export function createVorgangStatistic(): VorgangStatistic {
     byStatus: createByStatus(),
     wiedervorlagen: faker.datatype.number(),
     existsWiedervorlageOverdue: false,
+    ungeleseneNachrichten: faker.datatype.number(),
   };
 }
 
diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-views-menu.component.html b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-views-menu.component.html
index c7d9d6fc8850a44c562412d25b77ea4a0c2cda83..6c874f1b35f4c2e6ea7955504a4dc69a5937fa6b 100644
--- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-views-menu.component.html
+++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-views-menu.component.html
@@ -130,6 +130,22 @@
     >
       <div class="dot zu-loeschen"></div>
     </alfa-vorgang-view-item-container>
+    <alfa-vorgang-view-item-container
+      *ngIf="
+        apiRootResource
+          | hasAnyLink
+            : apiRootLinkRel.ALL_UNGELESENE_NACHRICHTEN
+            : apiRootLinkRel.MY_UNGELESENE_NACHRICHTEN
+            : apiRootLinkRel.UNASSIGNED_UNGELESENE_NACHRICHTEN
+      "
+      data-test-id="vorgang-ungelesene-nachrichten-view"
+      label="Ungelesen"
+      [view]="vorgangView.UNGELESENE_NACHRICHTEN"
+      [count]="statistic.ungeleseneNachrichten"
+      class="top-border"
+    >
+      <ozgcloud-postfach-icon [showBadge]="true"></ozgcloud-postfach-icon>
+    </alfa-vorgang-view-item-container>
     <alfa-vorgang-view-item-container
       *ngIf="
         apiRootResource
@@ -142,7 +158,6 @@
       label="Wiedervorlagen"
       [view]="vorgangView.WIEDERVORLAGEN"
       [count]="statistic.wiedervorlagen"
-      class="top-border"
     >
       <alfa-wiedervorlage-icon
         [isOverdue]="statistic.existsWiedervorlageOverdue"
diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-views-menu.component.scss b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-views-menu.component.scss
index 4b089df917f623d3d02d1f44fcca2dc9e7ba79c1..6c9cb3c6e3416570c16839d351389bcc3519ff18 100644
--- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-views-menu.component.scss
+++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-views-menu.component.scss
@@ -70,6 +70,8 @@ body.dark :host {
   }
 }
 
-ozgcloud-icon {
+ozgcloud-icon,
+ozgcloud-postfach-icon {
   margin-right: 6px;
+  height: $iconHeight;
 }
diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-views-menu.component.spec.ts b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-views-menu.component.spec.ts
index cf4f8bd301a92a054afbf9e6c3d22c7c1af0b5fe..2d312f19021b016c3985e0b17b487fc982210f79 100644
--- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-views-menu.component.spec.ts
+++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-views-menu.component.spec.ts
@@ -25,7 +25,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { ApiRootLinkRel } from '@alfa-client/api-root-shared';
 import { HasLinkPipe, createStateResource } from '@alfa-client/tech-shared';
 import { existsAsHtmlElement, notExistsAsHtmlElement } from '@alfa-client/test-utils';
-import { OzgcloudIconComponent } from '@alfa-client/ui';
+import { OzgcloudIconComponent, PostfachIconComponent } from '@alfa-client/ui';
 import { createApiRootResource } from 'libs/api-root-shared/test/api-root';
 import { HasAnyLinkPipe } from 'libs/tech-shared/src/lib/pipe/has-any-link.pipe';
 import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
@@ -48,6 +48,7 @@ describe('VorgangViewsMenuComponent', () => {
   const abgeschlossenView: string = getDataTestIdOf('vorgang-abgeschlossen-view');
   const verworfenView: string = getDataTestIdOf('vorgang-verworfen-view');
   const wiedervorlagenView: string = getDataTestIdOf('vorgang-wiedervorlagen-view');
+  const ungeleseneNachrichtenView: string = getDataTestIdOf('vorgang-ungelesene-nachrichten-view');
   const vorgangListView: string = getDataTestIdOf('vorgang-vorgang-list-view');
   const searchView: string = getDataTestIdOf('vorgang-search-view');
 
@@ -62,6 +63,7 @@ describe('VorgangViewsMenuComponent', () => {
         MockComponent(VorgangViewItemComponent),
         MockComponent(VorgangSearchViewItemContainerComponent),
         MockComponent(OzgcloudIconComponent),
+        MockComponent(PostfachIconComponent),
       ],
     }).compileComponents();
 
@@ -215,6 +217,26 @@ describe('VorgangViewsMenuComponent', () => {
     });
   });
 
+  describe('ungelesene nachrichten view', () => {
+    it.each([
+      ApiRootLinkRel.ALL_UNGELESENE_NACHRICHTEN,
+      ApiRootLinkRel.MY_UNGELESENE_NACHRICHTEN,
+      ApiRootLinkRel.UNASSIGNED_UNGELESENE_NACHRICHTEN,
+    ])('should show if %s link exists', (linkRel: string) => {
+      component.apiRootResource = createApiRootResource([linkRel]);
+      fixture.detectChanges();
+
+      existsAsHtmlElement(fixture, ungeleseneNachrichtenView);
+    });
+
+    it('should hide if link not exists', () => {
+      component.apiRootResource = createApiRootResource();
+      fixture.detectChanges();
+
+      notExistsAsHtmlElement(fixture, ungeleseneNachrichtenView);
+    });
+  });
+
   describe('vorgangList view', () => {
     it.each([
       ApiRootLinkRel.ALLE_VORGAENGE,
diff --git a/alfa-client/tsconfig.base.json b/alfa-client/tsconfig.base.json
index d0242502a79252e59ba623be19ca9200a4e3ae4e..273aa6f0fd7e8b8dc7bfe7e87a4f644820431bf8 100644
--- a/alfa-client/tsconfig.base.json
+++ b/alfa-client/tsconfig.base.json
@@ -16,6 +16,7 @@
     "skipDefaultLibCheck": true,
     "baseUrl": ".",
     "paths": {
+      "@admin-client/admin-settings": ["libs/admin-settings/src/index.ts"],
       "@alfa-client/api-root-shared": ["libs/api-root-shared/src/index.ts"],
       "@alfa-client/app-shared": ["libs/app-shared/src/index.ts"],
       "@alfa-client/bescheid": ["libs/bescheid/src/index.ts"],
diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/FrontendEnvironment.java b/alfa-service/src/main/java/de/ozgcloud/alfa/Environment.java
similarity index 97%
rename from alfa-service/src/main/java/de/ozgcloud/alfa/FrontendEnvironment.java
rename to alfa-service/src/main/java/de/ozgcloud/alfa/Environment.java
index 218f2f1f4732c4bb0b856403f9fd0e8b9eafec73..d4506a9c0e64e2b842680a1c69d66fcd36cf8709 100644
--- a/alfa-service/src/main/java/de/ozgcloud/alfa/FrontendEnvironment.java
+++ b/alfa-service/src/main/java/de/ozgcloud/alfa/Environment.java
@@ -30,7 +30,7 @@ import lombok.Getter;
 
 @Getter
 @Builder
-public class FrontendEnvironment {
+public class Environment {
 
 	private boolean production;
 	private String remoteHost;
diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/EnvironmentController.java b/alfa-service/src/main/java/de/ozgcloud/alfa/EnvironmentController.java
index 65f0ef8f07d25157d8fc52f73cc3852a13c2cd90..aa126fda712b2ed9ad962bbb745b0a4ee51233d4 100644
--- a/alfa-service/src/main/java/de/ozgcloud/alfa/EnvironmentController.java
+++ b/alfa-service/src/main/java/de/ozgcloud/alfa/EnvironmentController.java
@@ -48,8 +48,8 @@ public class EnvironmentController {
 	private VorgangProcessorProperties vorgangProcessorProperties;
 
 	@GetMapping
-	public FrontendEnvironment getFrontendEnvironment() {
-		return FrontendEnvironment.builder()
+	public Environment getEnvironment() {
+		return Environment.builder()
 				.production(productionProperties.isProduction())
 				.remoteHost(linkTo(RootController.class).toUri().toString())
 				.authServer(oAuth2Properties.getAuthServerUrl())
diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/RootViewLinkHandler.java b/alfa-service/src/main/java/de/ozgcloud/alfa/RootViewLinkHandler.java
index e8d834618a56d3efd308efa231d6ca5c13cc13ef..b5d79fcc0ab64557b88236b0903d0aafc14e125f 100644
--- a/alfa-service/src/main/java/de/ozgcloud/alfa/RootViewLinkHandler.java
+++ b/alfa-service/src/main/java/de/ozgcloud/alfa/RootViewLinkHandler.java
@@ -38,6 +38,10 @@ class RootViewLinkHandler {
 	static final String SEARCH_MY_VORGEANGE_REL = "search_my";
 	static final String SEARCH_UNASSIGNED_VORGEANGE_REL = "search_unassigned";
 
+	static final String ALL_UNGELESENE_NACHRICHTEN_REL = "vorgaenge_ungelesene_nachrichten_all";
+	static final String MY_UNGELESENE_NACHRICHTEN_REL = "vorgaenge_ungelesene_nachrichten_my";
+	static final String UNASSIGNED_UNGELESENE_NACHRICHTEN_REL = "vorgaenge_ungelesene_nachrichten_unassigned";
+
 	static final int PAGE_SIZE = 100;
 
 	@Autowired
@@ -100,6 +104,8 @@ class RootViewLinkHandler {
 		modelBuilder
 				.addLink(buildGetAllByAssignedToAndHasNextWiedervorlageFristLink(UserId.empty(), UNASSIGNED_WIEDERVORLAGEN_REL));
 		userId.map(id -> buildGetAllByAssignedToAndHasNextWiedervorlageFristLink(id, MY_WIEDERVORLAGEN_REL)).ifPresent(modelBuilder::addLink);
+
+		addGetByUngeleseneNachrichtenLinks(modelBuilder, userId);
 	}
 
 	Link buildGetAllUnassignedVorgaengeLink() {
@@ -169,4 +175,22 @@ class RootViewLinkHandler {
 		return linkTo(methodOn(VorgangController.class).getAllByAssignedToAndHasNextWiedervorlageFrist(0, PAGE_SIZE, userId,
 				VorgangController.PARAM_NEXT_WIEDERVORLAGE_FRIST_EXISTS)).withRel(linkRel);
 	}
+
+	void addGetByUngeleseneNachrichtenLinks(ModelBuilder<Root> modelBuilder, Optional<UserId> userId) {
+		modelBuilder.addLink(buildGelAllByUngeleseneNachrichtenLink());
+		modelBuilder.addLink(buildGetAllByAssignedToAndUngeleseneNachrichten(UserId.empty(), UNASSIGNED_UNGELESENE_NACHRICHTEN_REL));
+		userId.map(id -> buildGetAllByAssignedToAndUngeleseneNachrichten(id, MY_UNGELESENE_NACHRICHTEN_REL)).ifPresent(modelBuilder::addLink);
+	}
+
+	Link buildGelAllByUngeleseneNachrichtenLink() {
+		return linkTo(methodOn(VorgangController.class)
+				.getAllByUngeleseneNachrichten(0, PAGE_SIZE, VorgangController.PARAM_NACHRICHTEN_UNGELESENE))
+				.withRel(ALL_UNGELESENE_NACHRICHTEN_REL);
+	}
+
+	Link buildGetAllByAssignedToAndUngeleseneNachrichten(@NonNull UserId userId, String linkRel) {
+		return linkTo(methodOn(VorgangController.class)
+				.getAllByAssignedToAndUngeleseneNachrichten(0, PAGE_SIZE, userId, VorgangController.PARAM_NACHRICHTEN_UNGELESENE))
+				.withRel(linkRel);
+	}
 }
\ No newline at end of file
diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/statistic/Statistic.java b/alfa-service/src/main/java/de/ozgcloud/alfa/statistic/Statistic.java
index 2a17cc875696000782390062587d6e91474db53f..855d2ef1c57c58cc69cebffe7fb37facf972a25f 100644
--- a/alfa-service/src/main/java/de/ozgcloud/alfa/statistic/Statistic.java
+++ b/alfa-service/src/main/java/de/ozgcloud/alfa/statistic/Statistic.java
@@ -12,4 +12,5 @@ public class Statistic {
 	private ByStatus byStatus;
 	private int wiedervorlagen;
 	private boolean existsWiedervorlageOverdue;
+	private int ungeleseneNachrichten;
 }
diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/statistic/StatisticRemoteService.java b/alfa-service/src/main/java/de/ozgcloud/alfa/statistic/StatisticRemoteService.java
index cd508d6198827251fd4f661a7e0a4815570fa898..b39e47178187ac8a31b838d794bf7580f6748c67 100644
--- a/alfa-service/src/main/java/de/ozgcloud/alfa/statistic/StatisticRemoteService.java
+++ b/alfa-service/src/main/java/de/ozgcloud/alfa/statistic/StatisticRemoteService.java
@@ -11,9 +11,9 @@ import org.springframework.stereotype.Service;
 import de.ozgcloud.alfa.AlfaProperties;
 import de.ozgcloud.alfa.common.GrpcUtil;
 import de.ozgcloud.alfa.vorgang.Vorgang.VorgangStatus;
+import de.ozgcloud.vorgang.common.GrpcQueryOperator;
 import de.ozgcloud.vorgang.statistic.GrpcVorgangStatisticQuery;
 import de.ozgcloud.vorgang.statistic.GrpcVorgangStatisticQuery.GroupMethod;
-import de.ozgcloud.vorgang.statistic.GrpcVorgangStatisticQuery.Operator;
 import de.ozgcloud.vorgang.statistic.GrpcVorgangStatisticRequest;
 import de.ozgcloud.vorgang.statistic.GrpcVorgangStatisticResponse;
 import de.ozgcloud.vorgang.statistic.StatisticServiceGrpc.StatisticServiceBlockingStub;
@@ -25,9 +25,11 @@ class StatisticRemoteService {
 	static final String COUNT_VORGANG_STATUS_RESULT_NAME_FORMAT = "countVorgangStatus_%s";
 	static final String COUNT_WIEDERVORLAGE_NEXT_FRIST_RESULT_NAME = "countWiedervorlage";
 	static final String EXISTS_WIEDERVORLAGE_OVERDUE_RESULT_NAME = "existsWiedervorlageOverdue";
+	static final String COUNT_VORGAENGE_WITH_UNGELESENE_NACHRICHTEN_RESULT_NAME = "countVorgaengeWithUngeleseneNachrichten";
 
 	static final String STATUS_PATH = "Vorgang.status";
 	static final String WIEDERVORLAGE_NEXT_FRIST_PATH_TEMPLATE = "ClientAttribute.%s.nextWiedervorlageFrist";
+	static final String VORGAENGE_WITH_UNGELESENE_NACHRICHTEN_PATH = "ClientAttribute.OzgCloud_NachrichtenManager.hasNewPostfachNachricht";
 
 	static final String OPERAND_TODAY_DATE = "today()";
 
@@ -43,6 +45,7 @@ class StatisticRemoteService {
 				.addAllQuery(buildCountByStatusQueries(countByVorgangStatus))
 				.addQuery(buildCountWiedervorlageNextFristQuery())
 				.addQuery(buildExistsWiedervorlageOverdueQuery())
+				.addQuery(buildCountVorgaengeWithUngeleseneNachrichtenQuery())
 				.build();
 
 		var grpcResponse = statisticServiceStub.getVorgangStatistic(grpcRequest);
@@ -59,7 +62,7 @@ class StatisticRemoteService {
 				.setResultName(buildCountByStatusResultName(vorgangStatus))
 				.setPath(STATUS_PATH)
 				.setGroupMethod(GroupMethod.COUNT)
-				.setOperator(Operator.EQUAL)
+				.setOperator(GrpcQueryOperator.EQUAL)
 				.setOperandStringValue(vorgangStatus.name())
 				.build();
 	}
@@ -69,7 +72,7 @@ class StatisticRemoteService {
 				.setResultName(COUNT_WIEDERVORLAGE_NEXT_FRIST_RESULT_NAME)
 				.setPath(String.format(WIEDERVORLAGE_NEXT_FRIST_PATH_TEMPLATE, alfaProperties.getApplicationName()))
 				.setGroupMethod(GroupMethod.COUNT)
-				.setOperator(Operator.UNEQUAL)
+				.setOperator(GrpcQueryOperator.UNEQUAL)
 				.build();
 	}
 
@@ -78,7 +81,7 @@ class StatisticRemoteService {
 				.setResultName(EXISTS_WIEDERVORLAGE_OVERDUE_RESULT_NAME)
 				.setPath(String.format(WIEDERVORLAGE_NEXT_FRIST_PATH_TEMPLATE, alfaProperties.getApplicationName()))
 				.setGroupMethod(GroupMethod.EXISTS)
-				.setOperator(Operator.LESS_THEN_OR_EQUAL_TO)
+				.setOperator(GrpcQueryOperator.LESS_THEN_OR_EQUAL_TO)
 				.setOperandStringValue(OPERAND_TODAY_DATE)
 				.build();
 	}
@@ -93,4 +96,14 @@ class StatisticRemoteService {
 				.map(mapper::toResult)
 				.collect(Collectors.toMap(StatisticResult::getName, Function.identity()));
 	}
+
+	public GrpcVorgangStatisticQuery buildCountVorgaengeWithUngeleseneNachrichtenQuery() {
+		return GrpcVorgangStatisticQuery.newBuilder()
+				.setResultName(COUNT_VORGAENGE_WITH_UNGELESENE_NACHRICHTEN_RESULT_NAME)
+				.setPath(VORGAENGE_WITH_UNGELESENE_NACHRICHTEN_PATH)
+				.setGroupMethod(GroupMethod.COUNT)
+				.setOperator(GrpcQueryOperator.EQUAL)
+				.setOperandBoolValue(true)
+				.build();
+	}
 }
\ No newline at end of file
diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/statistic/StatisticService.java b/alfa-service/src/main/java/de/ozgcloud/alfa/statistic/StatisticService.java
index 68b9ab06c4d73f5b6810035b9b1312a6d3edbd2c..6b88ba78d635f291e3db330f661119f131ceb019 100644
--- a/alfa-service/src/main/java/de/ozgcloud/alfa/statistic/StatisticService.java
+++ b/alfa-service/src/main/java/de/ozgcloud/alfa/statistic/StatisticService.java
@@ -48,6 +48,7 @@ class StatisticService {
 		return Statistic.builder()
 				.existsWiedervorlageOverdue(getBooleanResult(response, StatisticRemoteService.EXISTS_WIEDERVORLAGE_OVERDUE_RESULT_NAME))
 				.wiedervorlagen(getIntResult(response, StatisticRemoteService.COUNT_WIEDERVORLAGE_NEXT_FRIST_RESULT_NAME))
+				.ungeleseneNachrichten(getIntResult(response, StatisticRemoteService.COUNT_VORGAENGE_WITH_UNGELESENE_NACHRICHTEN_RESULT_NAME))
 				.byStatus(ByStatus.builder()
 						.neu(getIntResult(response, remoteService.buildCountByStatusResultName(VorgangStatus.NEU)))
 						.abgeschlossen(getIntResult(response, remoteService.buildCountByStatusResultName(VorgangStatus.ABGESCHLOSSEN)))
diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/FilterCriteria.java b/alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/FilterCriteria.java
index c80e8617af570fb48b34bf5bea4cd4070212630f..89fe664537bdb8c0f58eece1b848ce0a4e00b395 100644
--- a/alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/FilterCriteria.java
+++ b/alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/FilterCriteria.java
@@ -22,4 +22,5 @@ class FilterCriteria {
 	@Builder.Default
 	private Optional<UserId> assignedTo = Optional.empty();
 	private boolean hasNextWiedervorlageFrist;
+	private boolean hasUngeleseneNachrichten;
 }
diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/VorgangController.java b/alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/VorgangController.java
index 35062413fb4a816eaf0263aa284d2bc5b32b4e6a..8d23095292dea0d30595fcdde1a13e3191e61d28 100644
--- a/alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/VorgangController.java
+++ b/alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/VorgangController.java
@@ -25,8 +25,6 @@ package de.ozgcloud.alfa.vorgang;
 
 import java.util.Optional;
 
-import jakarta.servlet.http.HttpServletResponse;
-
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.hateoas.EntityModel;
@@ -46,6 +44,7 @@ import de.ozgcloud.alfa.common.clientattribute.ClientAttributeService;
 import de.ozgcloud.alfa.common.user.UserId;
 import de.ozgcloud.alfa.statistic.StatisticController;
 import de.ozgcloud.alfa.vorgang.Vorgang.VorgangStatus;
+import jakarta.servlet.http.HttpServletResponse;
 
 @RestController
 @RequestMapping(VorgangController.PATH)
@@ -58,8 +57,10 @@ public class VorgangController {
 	static final String PARAM_ASSIGNED_TO = "assignedTo";
 	static final String PARAM_STATUS = "status";
 	static final String PARAM_NEXT_WIEDERVORLAGE_FRIST = "nextFrist";
+	static final String PARAM_NACHRICHTEN = "nachrichten";
 
 	public static final String PARAM_NEXT_WIEDERVORLAGE_FRIST_EXISTS = "exists";
+	public static final String PARAM_NACHRICHTEN_UNGELESENE = "ungelesene";
 
 	@Autowired
 	private VorgangService vorgangService;
@@ -189,4 +190,27 @@ public class VorgangController {
 		clientAttributeService.resetPostfachNachricht(vorgangId);
 		response.setStatus(HttpStatus.NO_CONTENT.value());
 	}
+
+	@GetMapping(params = { PARAM_PAGE, PARAM_LIMIT, PARAM_NACHRICHTEN })
+	public RepresentationModel<EntityModel<EnhancedVorgang>> getAllByUngeleseneNachrichten(@RequestParam int page, @RequestParam Integer limit,
+			@RequestParam String nachrichten) {
+		var requestCriteria = FindVorgaengeHeaderRequestCriteria.builder().page(page).limit(limit)
+				.filterCriteria(FilterCriteria.builder().hasUngeleseneNachrichten(PARAM_NACHRICHTEN_UNGELESENE.equals(nachrichten)).build())
+				.build();
+
+		return handleGetAllRequest(requestCriteria);
+	}
+
+	@GetMapping(params = { PARAM_PAGE, PARAM_LIMIT, PARAM_ASSIGNED_TO, PARAM_NACHRICHTEN })
+	public RepresentationModel<EntityModel<EnhancedVorgang>> getAllByAssignedToAndUngeleseneNachrichten(@RequestParam int page,
+			@RequestParam Integer limit, @RequestParam UserId assignedTo, @RequestParam String nachrichten) {
+		var requestCriteria = FindVorgaengeHeaderRequestCriteria.builder().page(page).limit(limit)
+				.filterCriteria(FilterCriteria.builder()
+						.filterByAssignedTo(true).assignedTo(asOptional(assignedTo))
+						.hasUngeleseneNachrichten(PARAM_NACHRICHTEN_UNGELESENE.equals(nachrichten))
+						.build())
+				.build();
+
+		return handleGetAllRequest(requestCriteria);
+	}
 }
\ No newline at end of file
diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/VorgangRemoteService.java b/alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/VorgangRemoteService.java
index bb2d49e67b4e7c57dac52b54c1aa27d329fd9525..a6d44d0c43309ab1f751b909d66d7a2483b5e492 100644
--- a/alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/VorgangRemoteService.java
+++ b/alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/VorgangRemoteService.java
@@ -29,18 +29,23 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import de.ozgcloud.alfa.common.GrpcUtil;
+import de.ozgcloud.vorgang.common.GrpcQueryOperator;
 import de.ozgcloud.vorgang.vorgang.GrpcFilterBy;
 import de.ozgcloud.vorgang.vorgang.GrpcFindVorgangRequest;
 import de.ozgcloud.vorgang.vorgang.GrpcFindVorgangRequest.GrpcOrderBy;
 import de.ozgcloud.vorgang.vorgang.GrpcFindVorgangResponse;
 import de.ozgcloud.vorgang.vorgang.GrpcFindVorgangWithEingangRequest;
 import de.ozgcloud.vorgang.vorgang.GrpcFindVorgangWithEingangResponse;
+import de.ozgcloud.vorgang.vorgang.GrpcQuery;
+import de.ozgcloud.vorgang.vorgang.GrpcVorgangQueryExpression;
 import de.ozgcloud.vorgang.vorgang.VorgangServiceGrpc.VorgangServiceBlockingStub;
 import net.devh.boot.grpc.client.inject.GrpcClient;
 
 @Service
 class VorgangRemoteService {
 
+	static final String VORGAENGE_WITH_UNGELESENE_NACHRICHTEN_PATH = "ClientAttribute.OzgCloud_NachrichtenManager.hasNewPostfachNachricht";
+
 	@GrpcClient(GrpcUtil.VORGANG_MANAGER_GRPC_CLIENT)
 	private VorgangServiceBlockingStub vorgangServiceStub;
 	@Autowired
@@ -70,7 +75,24 @@ class VorgangRemoteService {
 				.setOrderBy(GrpcOrderBy.valueOf(requestCriteria.getOrderBy().name()))
 				.setLimit(requestCriteria.getLimit())
 				.setOffset(requestCriteria.getPage() * requestCriteria.getLimit())
-				.setFilterBy(mapFilterCriteria(filterCriteria));
+				.setQuery(createQuery(filterCriteria))
+				.setFilterBy(createFilterBy(filterCriteria));
+	}
+
+	GrpcQuery createQuery(FilterCriteria filterCriteria) {
+		var queryBuilder = GrpcQuery.newBuilder();
+		if (filterCriteria.isHasUngeleseneNachrichten()) {
+			addUngeleseneNachrichtenExpression(queryBuilder);
+		}
+		return queryBuilder.build();
+	}
+
+	private void addUngeleseneNachrichtenExpression(GrpcQuery.Builder queryBuilder) {
+		queryBuilder.addExpressions(GrpcVorgangQueryExpression.newBuilder()
+				.setPath(VORGAENGE_WITH_UNGELESENE_NACHRICHTEN_PATH)
+				.setOperator(GrpcQueryOperator.EQUAL)
+				.setOperandBoolValue(true)
+				.build());
 	}
 
 	VorgaengeHeaderResponse buildVorgaengeHeaderResponse(GrpcFindVorgangResponse response) {
@@ -90,10 +112,10 @@ class VorgangRemoteService {
 	}
 
 	GrpcFindVorgangWithEingangRequest buildFindVorgangWithEingangRequest(String vorgangId, FilterCriteria filterCriteria) {
-		return GrpcFindVorgangWithEingangRequest.newBuilder().setId(vorgangId).setFilterBy(mapFilterCriteria(filterCriteria)).build();
+		return GrpcFindVorgangWithEingangRequest.newBuilder().setId(vorgangId).setFilterBy(createFilterBy(filterCriteria)).build();
 	}
 
-	GrpcFilterBy mapFilterCriteria(FilterCriteria filterCriteria) {
+	GrpcFilterBy createFilterBy(FilterCriteria filterCriteria) {
 		var filterCriteriaBuilder = GrpcFilterBy.newBuilder()
 				.setFilterByAssignedTo(filterCriteria.isFilterByAssignedTo())
 				.setFilterByOrganisationseinheitenId(filterCriteria.isFilterByOrganisationseinheitenId())
diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/EnvironmentControllerTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/EnvironmentControllerTest.java
index 154de97e2243536056b9502ea6eac01d37cc2306..f8338cd99ed64bb6f6aeb63b798165c7671d1507 100644
--- a/alfa-service/src/test/java/de/ozgcloud/alfa/EnvironmentControllerTest.java
+++ b/alfa-service/src/test/java/de/ozgcloud/alfa/EnvironmentControllerTest.java
@@ -62,9 +62,9 @@ class EnvironmentControllerTest {
 		mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
 	}
 
-	@DisplayName("Get frontend environment")
+	@DisplayName("Get environment")
 	@Nested
-	class TestGetFrontendEnvironment {
+	class TestGetEnvironment {
 
 		private static final String CLIENT = LoremIpsum.getInstance().getFirstName() + "Client";
 		private static final boolean PRODUCTION = true;
diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/RootViewLinkHandlerTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/RootViewLinkHandlerTest.java
index 64f4aadcf97daf229570e1affc1273dc9423da7a..84733b060eff9e273ab5bb84f97ccd00588bf73e 100644
--- a/alfa-service/src/test/java/de/ozgcloud/alfa/RootViewLinkHandlerTest.java
+++ b/alfa-service/src/test/java/de/ozgcloud/alfa/RootViewLinkHandlerTest.java
@@ -6,6 +6,7 @@ import static org.mockito.Mockito.*;
 
 import java.util.Optional;
 
+import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
@@ -18,6 +19,8 @@ import org.mockito.Spy;
 import org.springframework.hateoas.Link;
 import org.springframework.hateoas.LinkRelation;
 
+import com.thedeanda.lorem.LoremIpsum;
+
 import de.ozgcloud.alfa.common.ModelBuilder;
 import de.ozgcloud.alfa.common.user.CurrentUserService;
 import de.ozgcloud.alfa.common.user.UserId;
@@ -282,6 +285,13 @@ class RootViewLinkHandlerTest {
 							.get().extracting(Link::getHref).isEqualTo("/api/vorgangs?page=0&limit=100&assignedTo=&nextFrist=exists");
 				}
 			}
+
+			@Test
+			void shouldAddLinksForUngeleseneNachrichten() {
+				viewLinkHandler.addViewLinksForVerwaltungUser(modelBuilder, Optional.of(UserProfileTestFactory.ID));
+
+				verify(viewLinkHandler).addGetByUngeleseneNachrichtenLinks(modelBuilder, Optional.of(UserProfileTestFactory.ID));
+			}
 		}
 
 		@DisplayName("search all vorgaenge")
@@ -318,7 +328,7 @@ class RootViewLinkHandlerTest {
 			void shouldBeAddedIfUserIsPresent() {
 				var link = viewLinkHandler.buildMyVorgaengeLink(UserProfileTestFactory.ID);
 
-				assertThat(link.getHref()).isEqualTo("/api/vorgangs?page=0&limit=100&assignedTo=" + UserProfileTestFactory.ID.toString());
+				assertThat(link.getHref()).isEqualTo("/api/vorgangs?page=0&limit=100&assignedTo=" + UserProfileTestFactory.ID);
 			}
 		}
 
@@ -504,6 +514,176 @@ class RootViewLinkHandlerTest {
 		}
 	}
 
+	@Nested
+	class TestBuildGelAllByUngeleseneNachrichtenLink {
+
+		@Test
+		void shouldHaveLinkHref() {
+			var link = viewLinkHandler.buildGelAllByUngeleseneNachrichtenLink();
+
+			assertThat(link)
+					.extracting(Link::getHref)
+					.isEqualTo("/api/vorgangs?page=0&limit=100&nachrichten=ungelesene");
+		}
+
+		@Test
+		void shouldHaveLinkRel() {
+			var link = viewLinkHandler.buildGelAllByUngeleseneNachrichtenLink();
+
+			assertThat(link)
+					.extracting(Link::getRel)
+					.extracting(LinkRelation::value)
+					.isEqualTo(RootViewLinkHandler.ALL_UNGELESENE_NACHRICHTEN_REL);
+		}
+	}
+
+	@Nested
+	class TestBuildGetAllByAssignedToAndUngeleseneNachrichten {
+
+		@Nested
+		class AssignTo {
+
+			@Test
+			void shouldHaveLink() {
+				var link = viewLinkHandler.buildGetAllByAssignedToAndUngeleseneNachrichten(UserProfileTestFactory.ID,
+						RootViewLinkHandler.MY_UNGELESENE_NACHRICHTEN_REL);
+
+				assertThat(link)
+						.extracting(Link::getHref)
+						.isEqualTo("/api/vorgangs?page=0&limit=100&assignedTo=" + UserProfileTestFactory.ID + "&nachrichten=ungelesene");
+			}
+
+			@Test
+			void shouldHaveLinkRel() {
+				var link = viewLinkHandler.buildGetAllByAssignedToAndUngeleseneNachrichten(UserProfileTestFactory.ID,
+						RootViewLinkHandler.MY_UNGELESENE_NACHRICHTEN_REL);
+
+				assertThat(link)
+						.extracting(Link::getRel)
+						.extracting(LinkRelation::value)
+						.isEqualTo(RootViewLinkHandler.MY_UNGELESENE_NACHRICHTEN_REL);
+			}
+		}
+
+		@Nested
+		class Unassigned {
+
+			@Test
+			void shouldHaveLink() {
+				var link = viewLinkHandler.buildGetAllByAssignedToAndUngeleseneNachrichten(UserId.empty(),
+						RootViewLinkHandler.UNASSIGNED_UNGELESENE_NACHRICHTEN_REL);
+
+				assertThat(link)
+						.extracting(Link::getHref)
+						.isEqualTo("/api/vorgangs?page=0&limit=100&assignedTo=&nachrichten=ungelesene");
+			}
+
+			@Test
+			void shouldHaveLinkRel() {
+				var link = viewLinkHandler.buildGetAllByAssignedToAndUngeleseneNachrichten(UserId.empty(),
+						RootViewLinkHandler.UNASSIGNED_UNGELESENE_NACHRICHTEN_REL);
+
+				assertThat(link)
+						.extracting(Link::getRel)
+						.extracting(LinkRelation::value)
+						.isEqualTo(RootViewLinkHandler.UNASSIGNED_UNGELESENE_NACHRICHTEN_REL);
+			}
+
+		}
+
+	}
+
+	@Nested
+	class TestAddGetByUngeleseneNachrichtenLinks {
+
+		@Mock
+		private Root rootResource;
+		private final ModelBuilder<Root> modelBuilder = ModelBuilder.fromEntity(rootResource);
+		private final Link linkAllUngeleseneNachrichten = Link.of(LoremIpsum.getInstance().getUrl());
+		private final Link linkMyUngeleseneNachrichten = Link.of(LoremIpsum.getInstance().getUrl());
+		private final Link linkUnassignedUngeleseneNachrichten = Link.of(LoremIpsum.getInstance().getUrl());
+
+		@BeforeEach
+		void setUp() {
+			doReturn(linkAllUngeleseneNachrichten).when(viewLinkHandler).buildGelAllByUngeleseneNachrichtenLink();
+			doReturn(linkUnassignedUngeleseneNachrichten).when(viewLinkHandler)
+					.buildGetAllByAssignedToAndUngeleseneNachrichten(UserId.empty(), RootViewLinkHandler.UNASSIGNED_UNGELESENE_NACHRICHTEN_REL);
+		}
+
+		@Test
+		void shouldBuildLinkForUngeleseneNachrichten() {
+			viewLinkHandler.addGetByUngeleseneNachrichtenLinks(modelBuilder, Optional.of(UserProfileTestFactory.ID));
+
+			verify(viewLinkHandler).buildGelAllByUngeleseneNachrichtenLink();
+		}
+
+		@Test
+		void shouldAddLinkForUngeleseneNachrichten() {
+			var modelBuilder = ModelBuilder.fromEntity(rootResource);
+
+			viewLinkHandler.addGetByUngeleseneNachrichtenLinks(modelBuilder, Optional.of(UserProfileTestFactory.ID));
+
+			assertThat(modelBuilder.buildModel().getLinks()).contains(linkAllUngeleseneNachrichten);
+		}
+
+		@Test
+		void shouldBuildLinkForUnassignedUngeleseneNachrichten() {
+			viewLinkHandler.addGetByUngeleseneNachrichtenLinks(modelBuilder, Optional.empty());
+
+			verify(viewLinkHandler).buildGetAllByAssignedToAndUngeleseneNachrichten(UserId.empty(),
+					RootViewLinkHandler.UNASSIGNED_UNGELESENE_NACHRICHTEN_REL);
+		}
+
+		@Test
+		void shouldAddLinkForUnassignedUngeleseneNachrichten() {
+			var modelBuilder = ModelBuilder.fromEntity(rootResource);
+
+			viewLinkHandler.addGetByUngeleseneNachrichtenLinks(modelBuilder, Optional.empty());
+
+			assertThat(modelBuilder.buildModel().getLinks()).contains(linkUnassignedUngeleseneNachrichten);
+		}
+
+		@Nested
+		class UsedIdExists {
+
+			@BeforeEach
+			void setUp() {
+				doReturn(linkMyUngeleseneNachrichten).when(viewLinkHandler).buildGetAllByAssignedToAndUngeleseneNachrichten(UserProfileTestFactory.ID,
+						RootViewLinkHandler.MY_UNGELESENE_NACHRICHTEN_REL);
+			}
+
+			@Test
+			void shouldBuildLinkForMyUngeleseneNachrichten() {
+				viewLinkHandler.addGetByUngeleseneNachrichtenLinks(modelBuilder, Optional.of(UserProfileTestFactory.ID));
+
+				verify(viewLinkHandler).buildGetAllByAssignedToAndUngeleseneNachrichten(UserProfileTestFactory.ID,
+						RootViewLinkHandler.MY_UNGELESENE_NACHRICHTEN_REL);
+			}
+
+			@Test
+			void shouldAddLinkForMyUngeleseneNachrichten() {
+				var modelBuilder = ModelBuilder.fromEntity(rootResource);
+
+				viewLinkHandler.addGetByUngeleseneNachrichtenLinks(modelBuilder, Optional.of(UserProfileTestFactory.ID));
+
+				assertThat(modelBuilder.buildModel().getLinks()).contains(linkMyUngeleseneNachrichten);
+			}
+		}
+
+		@Nested
+		class UserIdEmpty {
+
+			@Test
+			void shouldNotBuildLinkForMyUngeleseneNachrichten() {
+				viewLinkHandler.addGetByUngeleseneNachrichtenLinks(modelBuilder, Optional.empty());
+
+				verify(viewLinkHandler, never()).buildGetAllByAssignedToAndUngeleseneNachrichten(UserProfileTestFactory.ID,
+						RootViewLinkHandler.MY_UNGELESENE_NACHRICHTEN_REL);
+			}
+		}
+
+	}
+
 	//	@DisplayName("Test user assistance documentation link")
 	//	@Nested
 	//	class TestDocumentationLink {
diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/statistic/GrpcVorgangStatisticQueryTestFactory.java b/alfa-service/src/test/java/de/ozgcloud/alfa/statistic/GrpcVorgangStatisticQueryTestFactory.java
index 0d26d330dc055948cec844b3cfd851f4adf72fd5..517f2f4495241c63259375ad45e7e6389b120f67 100644
--- a/alfa-service/src/test/java/de/ozgcloud/alfa/statistic/GrpcVorgangStatisticQueryTestFactory.java
+++ b/alfa-service/src/test/java/de/ozgcloud/alfa/statistic/GrpcVorgangStatisticQueryTestFactory.java
@@ -1,14 +1,19 @@
 package de.ozgcloud.alfa.statistic;
 
+import com.thedeanda.lorem.LoremIpsum;
+
 import de.ozgcloud.vorgang.statistic.GrpcVorgangStatisticQuery;
 
 public class GrpcVorgangStatisticQueryTestFactory {
 
+	public static final String RESULT_NAME = LoremIpsum.getInstance().getWords(1);
+
 	public static GrpcVorgangStatisticQuery create() {
 		return createBuilder().build();
 	}
 
 	public static GrpcVorgangStatisticQuery.Builder createBuilder() {
-		return GrpcVorgangStatisticQuery.newBuilder();
+		return GrpcVorgangStatisticQuery.newBuilder()
+				.setResultName(RESULT_NAME);
 	}
 }
diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/statistic/StatisticRemoteServiceTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/statistic/StatisticRemoteServiceTest.java
index 5716d65c2197741fbf8d03e498f3b283e398cc17..8306173ae997b9ade430cb8dfe93a2a4749b531f 100644
--- a/alfa-service/src/test/java/de/ozgcloud/alfa/statistic/StatisticRemoteServiceTest.java
+++ b/alfa-service/src/test/java/de/ozgcloud/alfa/statistic/StatisticRemoteServiceTest.java
@@ -15,6 +15,8 @@ import org.junit.jupiter.api.Test;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.EnumSource;
 import org.junit.jupiter.params.provider.EnumSource.Mode;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.mockito.Spy;
@@ -23,9 +25,10 @@ import com.thedeanda.lorem.LoremIpsum;
 
 import de.ozgcloud.alfa.AlfaProperties;
 import de.ozgcloud.alfa.vorgang.Vorgang.VorgangStatus;
+import de.ozgcloud.vorgang.common.GrpcQueryOperator;
 import de.ozgcloud.vorgang.statistic.GrpcVorgangStatisticQuery;
 import de.ozgcloud.vorgang.statistic.GrpcVorgangStatisticQuery.GroupMethod;
-import de.ozgcloud.vorgang.statistic.GrpcVorgangStatisticQuery.Operator;
+import de.ozgcloud.vorgang.statistic.GrpcVorgangStatisticRequest;
 import de.ozgcloud.vorgang.statistic.GrpcVorgangStatisticResponse;
 import de.ozgcloud.vorgang.statistic.GrpcVorgangStatisticResult;
 import de.ozgcloud.vorgang.statistic.StatisticServiceGrpc.StatisticServiceBlockingStub;
@@ -79,7 +82,7 @@ class StatisticRemoteServiceTest {
 		void shouldContainOperator(VorgangStatus vorgangStatus) {
 			var query = service.buildCountByVorgangStatusQuery(vorgangStatus);
 
-			assertThat(query.getOperator()).isEqualTo(Operator.EQUAL);
+			assertThat(query.getOperator()).isEqualTo(GrpcQueryOperator.EQUAL);
 		}
 
 		@ParameterizedTest
@@ -126,7 +129,7 @@ class StatisticRemoteServiceTest {
 					.contains(
 							COUNT_WIEDERVORLAGE_NEXT_FRIST_RESULT_NAME,
 							String.format(StatisticRemoteService.WIEDERVORLAGE_NEXT_FRIST_PATH_TEMPLATE, applicationName),
-							Operator.UNEQUAL,
+							GrpcQueryOperator.UNEQUAL,
 							GroupMethod.COUNT
 					);
 		}
@@ -167,7 +170,7 @@ class StatisticRemoteServiceTest {
 		void shouldContainOperator() {
 			var query = service.buildExistsWiedervorlageOverdueQuery();
 
-			assertThat(query.getOperator()).isEqualTo(Operator.LESS_THEN_OR_EQUAL_TO);
+			assertThat(query.getOperator()).isEqualTo(GrpcQueryOperator.LESS_THEN_OR_EQUAL_TO);
 		}
 
 		@Test
@@ -190,12 +193,20 @@ class StatisticRemoteServiceTest {
 	class TestGetVorgaengeStatistics {
 
 		private final GrpcVorgangStatisticResponse response = GrpcVorgangStatisticResponseTestFactory.create();
+		private final GrpcVorgangStatisticQuery countVorgaengeWithUngeleseneNachrichtenQuery = GrpcVorgangStatisticQueryTestFactory.createBuilder()
+				.setResultName("ungelesene nachrichten").build();
+		private final GrpcVorgangStatisticQuery existsWiedervorlageOverdueQuery = GrpcVorgangStatisticQueryTestFactory.createBuilder()
+				.setResultName("exists overdue").build();
+
+		@Captor
+		private ArgumentCaptor<GrpcVorgangStatisticRequest> grpcRequestCaptor;
 
 		@BeforeEach
 		void beforeEach() {
 			when(serviceStub.getVorgangStatistic(any())).thenReturn(response);
 
-			doReturn(GrpcVorgangStatisticQueryTestFactory.create()).when(service).buildExistsWiedervorlageOverdueQuery();
+			doReturn(existsWiedervorlageOverdueQuery).when(service).buildExistsWiedervorlageOverdueQuery();
+			doReturn(countVorgaengeWithUngeleseneNachrichtenQuery).when(service).buildCountVorgaengeWithUngeleseneNachrichtenQuery();
 		}
 
 		@Test
@@ -232,6 +243,21 @@ class StatisticRemoteServiceTest {
 
 			verify(service).buildStatisticResult(response);
 		}
+
+		@Test
+		void shouldCallBuildCountVorgaengeWithUngeleseneNachrichtenQuery() {
+			service.getVorgaengeStatistics(STATUSES_TO_COUNT);
+
+			verify(service).buildCountVorgaengeWithUngeleseneNachrichtenQuery();
+		}
+
+		@Test
+		void shouldAddCountVorgaengeWithUngeleseneNachrichtenQuery() {
+			service.getVorgaengeStatistics(STATUSES_TO_COUNT);
+
+			verify(serviceStub).getVorgangStatistic(grpcRequestCaptor.capture());
+			assertThat(grpcRequestCaptor.getValue().getQueryList()).contains(countVorgaengeWithUngeleseneNachrichtenQuery);
+		}
 	}
 
 	@Nested
@@ -270,4 +296,47 @@ class StatisticRemoteServiceTest {
 					.hasEntrySatisfying(RESULT_NAME, statisticResult -> assertThat(statisticResult.getIntValue()).isEqualTo(RESULT_INT));
 		}
 	}
+
+	@Nested
+	class TestBuildCountVorgaengeWithUngeleseneNachrichtenQuery {
+
+		@Test
+		void shouldHaveResultName() {
+			var query = callService();
+
+			assertThat(query.getResultName()).isEqualTo(COUNT_VORGAENGE_WITH_UNGELESENE_NACHRICHTEN_RESULT_NAME);
+		}
+
+		@Test
+		void shouldHavePath() {
+			var query = callService();
+
+			assertThat(query.getPath()).isEqualTo(VORGAENGE_WITH_UNGELESENE_NACHRICHTEN_PATH);
+		}
+
+		@Test
+		void shouldHaveGroupingMethod() {
+			var query = callService();
+
+			assertThat(query.getGroupMethod()).isEqualTo(GroupMethod.COUNT);
+		}
+
+		@Test
+		void shouldHaveOperator() {
+			var query = callService();
+
+			assertThat(query.getOperator()).isEqualTo(GrpcQueryOperator.EQUAL);
+		}
+
+		@Test
+		void shouldHaveOperandValue() {
+			var query = callService();
+
+			assertThat(query.getOperandBoolValue()).isTrue();
+		}
+
+		private GrpcVorgangStatisticQuery callService() {
+			return service.buildCountVorgaengeWithUngeleseneNachrichtenQuery();
+		}
+	}
 }
\ No newline at end of file
diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/statistic/StatisticServiceTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/statistic/StatisticServiceTest.java
index 1b030d675d4eec8e8cee9f8c2bcb0f3f83e339e1..e35e1de7fecbdcfeae02ca7e75064d40e354546d 100644
--- a/alfa-service/src/test/java/de/ozgcloud/alfa/statistic/StatisticServiceTest.java
+++ b/alfa-service/src/test/java/de/ozgcloud/alfa/statistic/StatisticServiceTest.java
@@ -138,6 +138,14 @@ class StatisticServiceTest {
 
 			assertThat(statistic.getByStatus().getNeu()).isZero();
 		}
+
+		@Test
+		void shouldContainUngeleseneNachrichten() {
+			var statistic = service.buildGetVorgaengeStatisticResult(
+					Map.of(COUNT_VORGAENGE_WITH_UNGELESENE_NACHRICHTEN_RESULT_NAME, StatisticResultTestFactory.create()));
+
+			assertThat(statistic.getUngeleseneNachrichten()).isEqualTo(StatisticResultTestFactory.INT_VALUE);
+		}
 	}
 
 	@Nested
diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/statistic/StatisticTestFactory.java b/alfa-service/src/test/java/de/ozgcloud/alfa/statistic/StatisticTestFactory.java
index d4acbda72b80abdb119b6e736812291208ae0411..5808eb9355941f76f27cf1e036c4eabd9fc410ec 100644
--- a/alfa-service/src/test/java/de/ozgcloud/alfa/statistic/StatisticTestFactory.java
+++ b/alfa-service/src/test/java/de/ozgcloud/alfa/statistic/StatisticTestFactory.java
@@ -4,6 +4,7 @@ public class StatisticTestFactory {
 
 	public static final int COUNT_WIEDERVORLAGEN = 8;
 	public static final boolean EXISTS_WIEDERVORLAGE_OVERDUE = true;
+	public static final int COUNT_UNGELESENE_NACHRICHTEN = 5;
 
 	public static Statistic create() {
 		return createBuilder().build();
@@ -13,6 +14,7 @@ public class StatisticTestFactory {
 		return Statistic.builder()
 				.byStatus(ByStatusTestFactory.create())
 				.wiedervorlagen(COUNT_WIEDERVORLAGEN)
-				.existsWiedervorlageOverdue(EXISTS_WIEDERVORLAGE_OVERDUE);
+				.existsWiedervorlageOverdue(EXISTS_WIEDERVORLAGE_OVERDUE)
+				.ungeleseneNachrichten(COUNT_UNGELESENE_NACHRICHTEN);
 	}
 }
diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/FilterCriteriaTestFactory.java b/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/FilterCriteriaTestFactory.java
index a4572dc1eaf28498d41b9aa0da67f8a935ea837b..a6fd2febaf7e1c665f9fbee464ba4d0c48f45f68 100644
--- a/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/FilterCriteriaTestFactory.java
+++ b/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/FilterCriteriaTestFactory.java
@@ -10,11 +10,10 @@ public class FilterCriteriaTestFactory {
 
 	public static final boolean FILTER_BY_ORGANISATIONS_EINHEITEN_ID = true;
 	public static final boolean FILTER_BY_ASSIGNED_TO = true;
-
 	public static final VorgangStatus VORGANG_STATUS = VorgangStatus.NEU;
 	public static final String ORGANISATIONS_EINHEIT_ID = ZustaendigeStelleTestFactory.ORGANISATIONSEINHEITEN_ID;
-
 	public static final boolean HAS_NEXT_WIEDERVORLAGE_FRIST = false;
+	public static final boolean HAS_UNGELESENE_NACHRICHTEN = false;
 
 	public static FilterCriteria create() {
 		return createBuilder().build();
@@ -27,6 +26,7 @@ public class FilterCriteriaTestFactory {
 				.filterByAssignedTo(FILTER_BY_ASSIGNED_TO)
 				.assignedTo(Optional.of(UserProfileTestFactory.ID))
 				.organisationsEinheitenId(List.of(ORGANISATIONS_EINHEIT_ID))
-				.hasNextWiedervorlageFrist(HAS_NEXT_WIEDERVORLAGE_FRIST);
+				.hasNextWiedervorlageFrist(HAS_NEXT_WIEDERVORLAGE_FRIST)
+				.hasUngeleseneNachrichten(HAS_UNGELESENE_NACHRICHTEN);
 	}
 }
diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/GrpcQueryTestFactory.java b/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/GrpcQueryTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..33c4fe7c36a9af6b5a85423c00b649af863ab468
--- /dev/null
+++ b/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/GrpcQueryTestFactory.java
@@ -0,0 +1,14 @@
+package de.ozgcloud.alfa.vorgang;
+
+import de.ozgcloud.vorgang.vorgang.GrpcQuery;
+
+public class GrpcQueryTestFactory {
+
+	public static GrpcQuery create() {
+		return createBuilder().build();
+	}
+
+	public static GrpcQuery.Builder createBuilder() {
+		return GrpcQuery.newBuilder();
+	}
+}
diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/VorgangControllerITCase.java b/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/VorgangControllerITCase.java
index 8eea6215c5ed51e9cd4d184c627a70ba5ee5a55a..c93835bcb0da848cf565cdedfc35ee677880ce3a 100644
--- a/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/VorgangControllerITCase.java
+++ b/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/VorgangControllerITCase.java
@@ -142,42 +142,42 @@ class VorgangControllerITCase {
 				private static final String BY_STATUS_PATH = "$.statistic.byStatus.";
 
 				@Test
-				void shouldContainsNeu() throws Exception {
+				void shouldContainNeu() throws Exception {
 					var response = doRequest();
 
 					response.andExpect(jsonPath(BY_STATUS_PATH + "neu").value(ByStatusTestFactory.NEU_COUNT));
 				}
 
 				@Test
-				void shouldContainsAngenommen() throws Exception {
+				void shouldContainAngenommen() throws Exception {
 					var response = doRequest();
 
 					response.andExpect(jsonPath(BY_STATUS_PATH + "angenommen").value(ByStatusTestFactory.ANGENOMMEN_COUNT));
 				}
 
 				@Test
-				void shouldContainsInBearbeitung() throws Exception {
+				void shouldContainInBearbeitung() throws Exception {
 					var response = doRequest();
 
 					response.andExpect(jsonPath(BY_STATUS_PATH + "inBearbeitung").value(ByStatusTestFactory.IN_BEARBEITUNG_COUNT));
 				}
 
 				@Test
-				void shouldContainsBeschieden() throws Exception {
+				void shouldContainBeschieden() throws Exception {
 					var response = doRequest();
 
 					response.andExpect(jsonPath(BY_STATUS_PATH + "beschieden").value(ByStatusTestFactory.BESCHIEDEN_COUNT));
 				}
 
 				@Test
-				void shouldContainsAbgeschlossen() throws Exception {
+				void shouldContainAbgeschlossen() throws Exception {
 					var response = doRequest();
 
 					response.andExpect(jsonPath(BY_STATUS_PATH + "abgeschlossen").value(ByStatusTestFactory.ABGESCHLOSSEN_COUNT));
 				}
 
 				@Test
-				void shouldContainsVerworfen() throws Exception {
+				void shouldContainVerworfen() throws Exception {
 					var response = doRequest();
 
 					response.andExpect(jsonPath(BY_STATUS_PATH + "verworfen").value(ByStatusTestFactory.VERWORFEN_COUNT));
@@ -185,11 +185,18 @@ class VorgangControllerITCase {
 			}
 
 			@Test
-			void shouldContainsWiedervorlagen() throws Exception {
+			void shouldContainWiedervorlagen() throws Exception {
 				var response = doRequest();
 
 				response.andExpect(jsonPath("$.statistic.wiedervorlagen").value(StatisticTestFactory.COUNT_WIEDERVORLAGEN));
 			}
+
+			@Test
+			void shouldContainUngeleseneNachrichten() throws Exception {
+				var response = doRequest();
+
+				response.andExpect(jsonPath("$.statistic.ungeleseneNachrichten").value(StatisticTestFactory.COUNT_UNGELESENE_NACHRICHTEN));
+			}
 		}
 	}
 
diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/VorgangControllerTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/VorgangControllerTest.java
index eb68a2d7b8716df1ac05a12ae42ffc6b34e89600..4c237346f037043fb98cf7c8c49a3a72b8e65bfd 100644
--- a/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/VorgangControllerTest.java
+++ b/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/VorgangControllerTest.java
@@ -30,10 +30,15 @@ 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.List;
+
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+import org.junit.jupiter.params.provider.ValueSource;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Captor;
 import org.mockito.InjectMocks;
@@ -606,6 +611,163 @@ class VorgangControllerTest {
 				}
 			}
 		}
+
+		@Nested
+		class TestGetAllByUngeleseneNachrichten {
+
+			@ParameterizedTest
+			@MethodSource("nachrichtenValues")
+			void shouldCallHandleGetAllRequest(String nachrichtenValue) {
+				doRequestWithNachrichtenParam(nachrichtenValue);
+
+				verify(controller).handleGetAllRequest(any(FindVorgaengeHeaderRequestCriteria.class));
+			}
+
+			@ParameterizedTest
+			@MethodSource("nachrichtenValues")
+			void shouldCriteriaHavePage(String nachrichtenValue) {
+				doRequestWithNachrichtenParam(nachrichtenValue);
+
+				verify(controller).handleGetAllRequest(criteriaCaptor.capture());
+				assertThat(criteriaCaptor.getValue().getPage()).isEqualTo(PAGE);
+			}
+
+			@ParameterizedTest
+			@MethodSource("nachrichtenValues")
+			void shouldCriteriaHaveLimit(String nachrichtenValue) {
+				doRequestWithNachrichtenParam(nachrichtenValue);
+
+				verify(controller).handleGetAllRequest(criteriaCaptor.capture());
+				assertThat(criteriaCaptor.getValue().getLimit()).isEqualTo(LIMIT);
+			}
+
+			static List<String> nachrichtenValues() {
+				return List.of(VorgangController.PARAM_NACHRICHTEN_UNGELESENE, "", "dummy");
+			}
+
+			@Nested
+			class WithParamNachrichtenUngelesene {
+
+				@Test
+				void shouldCriteriaHaveHasUngeleseneNachrichtenTrue() {
+					doRequestWithNachrichtenParam(VorgangController.PARAM_NACHRICHTEN_UNGELESENE);
+
+					verify(controller).handleGetAllRequest(criteriaCaptor.capture());
+					assertThat(criteriaCaptor.getValue().getFilterCriteria().isHasUngeleseneNachrichten()).isTrue();
+				}
+			}
+
+			@Nested
+			class WithoutParamNachrichtenUngelesene {
+
+				@ParameterizedTest
+				@ValueSource(strings = {"", "dummy"})
+				void shouldCriteriaHaveHasUngeleseneNachrichtenFalse(String nachrichtenValue) {
+					doRequestWithNachrichtenParam(nachrichtenValue);
+
+					verify(controller).handleGetAllRequest(criteriaCaptor.capture());
+					assertThat(criteriaCaptor.getValue().getFilterCriteria().isHasUngeleseneNachrichten()).isFalse();
+				}
+			}
+
+			@SneakyThrows
+			private void doRequestWithNachrichtenParam(String paramValue) {
+				mockMvc.perform(get(PATH)
+								.param(VorgangController.PARAM_PAGE, Integer.toString(PAGE))
+								.param(VorgangController.PARAM_LIMIT, Integer.toString(LIMIT))
+								.param(VorgangController.PARAM_NACHRICHTEN, paramValue))
+						.andExpect(status().isOk());
+			}
+		}
+
+		@Nested
+		class TestGetAllByAssignedToAndUngeleseneNachrichten {
+
+			private static final UserId ASSIGNED_TO = UserProfileTestFactory.ID;
+
+			@ParameterizedTest
+			@MethodSource("nachrichtenValues")
+			void shouldCallHandleGetAllRequest(String nachrichtenValue) {
+				doRequestWithNachrichtenParam(nachrichtenValue);
+
+				verify(controller).handleGetAllRequest(any(FindVorgaengeHeaderRequestCriteria.class));
+			}
+
+			@ParameterizedTest
+			@MethodSource("nachrichtenValues")
+			void shouldCriteriaHavePage(String nachrichtenValue) {
+				doRequestWithNachrichtenParam(nachrichtenValue);
+
+				verify(controller).handleGetAllRequest(criteriaCaptor.capture());
+				assertThat(criteriaCaptor.getValue().getPage()).isEqualTo(PAGE);
+			}
+
+			@ParameterizedTest
+			@MethodSource("nachrichtenValues")
+			void shouldCriteriaHaveLimit(String nachrichtenValue) {
+				doRequestWithNachrichtenParam(nachrichtenValue);
+
+				verify(controller).handleGetAllRequest(criteriaCaptor.capture());
+				assertThat(criteriaCaptor.getValue().getLimit()).isEqualTo(LIMIT);
+			}
+
+			@ParameterizedTest
+			@MethodSource("nachrichtenValues")
+			void shouldCriteriaHaveAssignedTo(String nachrichtenValue) {
+				doRequestWithNachrichtenParam(nachrichtenValue);
+
+				verify(controller).handleGetAllRequest(criteriaCaptor.capture());
+				assertThat(criteriaCaptor.getValue().getFilterCriteria().getAssignedTo()).hasValue(ASSIGNED_TO);
+			}
+
+			@ParameterizedTest
+			@MethodSource("nachrichtenValues")
+			void shouldSetFilterByAssignedTo(String nachrichtenValue) {
+				doRequestWithNachrichtenParam(nachrichtenValue);
+
+				verify(controller).handleGetAllRequest(criteriaCaptor.capture());
+				assertThat(criteriaCaptor.getValue().getFilterCriteria().isFilterByAssignedTo()).isTrue();
+			}
+
+			static List<String> nachrichtenValues() {
+				return List.of(VorgangController.PARAM_NACHRICHTEN_UNGELESENE, "", "dummy");
+			}
+
+			@Nested
+			class WithParamNachrichtenUngelesene {
+
+				@Test
+				void shouldCriteriaHaveHasUngeleseneNachrichtenTrue() {
+					doRequestWithNachrichtenParam(VorgangController.PARAM_NACHRICHTEN_UNGELESENE);
+
+					verify(controller).handleGetAllRequest(criteriaCaptor.capture());
+					assertThat(criteriaCaptor.getValue().getFilterCriteria().isHasUngeleseneNachrichten()).isTrue();
+				}
+			}
+
+			@Nested
+			class WithoutParamNachrichtenUngelesene {
+
+				@ParameterizedTest
+				@ValueSource(strings = {"", "dummy"})
+				void shouldCriteriaHaveHasUngeleseneNachrichtenFalse(String nachrichtenValue) {
+					doRequestWithNachrichtenParam(nachrichtenValue);
+
+					verify(controller).handleGetAllRequest(criteriaCaptor.capture());
+					assertThat(criteriaCaptor.getValue().getFilterCriteria().isHasUngeleseneNachrichten()).isFalse();
+				}
+			}
+
+			@SneakyThrows
+			private void doRequestWithNachrichtenParam(String paramValue) {
+				mockMvc.perform(get(PATH)
+								.param(VorgangController.PARAM_PAGE, Integer.toString(PAGE))
+								.param(VorgangController.PARAM_LIMIT, Integer.toString(LIMIT))
+								.param(VorgangController.PARAM_ASSIGNED_TO, ASSIGNED_TO.toString())
+								.param(VorgangController.PARAM_NACHRICHTEN, paramValue))
+						.andExpect(status().isOk());
+			}
+		}
 	}
 
 	@DisplayName("As Optional")
diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/VorgangRemoteServiceTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/VorgangRemoteServiceTest.java
index c2c4eb8db070a11c9fecdc60473d9325d3e77745..be66261c6e40450b44a08d50d9f325ce6b2df18a 100644
--- a/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/VorgangRemoteServiceTest.java
+++ b/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/VorgangRemoteServiceTest.java
@@ -23,6 +23,7 @@
  */
 package de.ozgcloud.alfa.vorgang;
 
+import static de.ozgcloud.alfa.vorgang.VorgangRemoteService.*;
 import static org.assertj.core.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
@@ -39,9 +40,12 @@ import org.mockito.Mock;
 import org.mockito.Spy;
 
 import de.ozgcloud.alfa.common.user.UserProfileTestFactory;
+import de.ozgcloud.vorgang.common.GrpcQueryOperator;
 import de.ozgcloud.vorgang.vorgang.GrpcFilterBy;
 import de.ozgcloud.vorgang.vorgang.GrpcFindVorgangRequest;
 import de.ozgcloud.vorgang.vorgang.GrpcFindVorgangResponse;
+import de.ozgcloud.vorgang.vorgang.GrpcQuery;
+import de.ozgcloud.vorgang.vorgang.GrpcVorgangQueryExpression;
 import de.ozgcloud.vorgang.vorgang.VorgangServiceGrpc.VorgangServiceBlockingStub;
 
 class VorgangRemoteServiceTest {
@@ -59,6 +63,8 @@ class VorgangRemoteServiceTest {
 
 	private final GrpcFilterBy filterBy = GrpcFilterByTestFactory.create();
 
+	private final GrpcQuery query = GrpcQueryTestFactory.create();
+
 	@DisplayName("Find vorgaenge header")
 	@Nested
 	class TestFindVorgaengeHeader {
@@ -73,7 +79,8 @@ class VorgangRemoteServiceTest {
 
 			@BeforeEach
 			void initMockReturnValues() {
-				doReturn(filterBy).when(service).mapFilterCriteria(any());
+				doReturn(query).when(service).createQuery(any());
+				doReturn(filterBy).when(service).createFilterBy(any());
 				doReturn(VorgangListResponseTestFactory.create()).when(service).buildVorgaengeHeaderResponse(any());
 			}
 
@@ -84,11 +91,18 @@ class VorgangRemoteServiceTest {
 				verify(service).buildFindVorgangRequest(requestCriteria, filterCriteria);
 			}
 
+			@Test
+			void callCreateQuery() {
+				callService();
+
+				verify(service).createQuery(filterCriteria);
+			}
+
 			@Test
 			void callCreateFilterBy() {
 				callService();
 
-				verify(service).mapFilterCriteria(filterCriteria);
+				verify(service).createFilterBy(filterCriteria);
 			}
 
 			@Test
@@ -109,7 +123,8 @@ class VorgangRemoteServiceTest {
 
 			@BeforeEach
 			void initMockReturnValues() {
-				doReturn(filterBy).when(service).mapFilterCriteria(any());
+				doReturn(query).when(service).createQuery(any());
+				doReturn(filterBy).when(service).createFilterBy(any());
 			}
 
 			@Test
@@ -127,6 +142,13 @@ class VorgangRemoteServiceTest {
 						.isEqualTo(FindVorgaengeRequestCriteriaTestFactory.PAGE * FindVorgaengeRequestCriteriaTestFactory.LIMIT);
 			}
 
+			@Test
+			void shouldSetQuery() {
+				var request = callService();
+
+				assertThat(request.getQuery()).isEqualTo(query);
+			}
+
 			@Test
 			void shouldSetFilterBy() {
 				var request = callService();
@@ -186,13 +208,64 @@ class VorgangRemoteServiceTest {
 		}
 	}
 
+	@Nested
+	class TestCreateQuery {
+
+		@Nested
+		class WhenHasUngeleseneNachrichtenIsTrue {
+
+			private final FilterCriteria filterCriteria = FilterCriteriaTestFactory.createBuilder().hasUngeleseneNachrichten(true).build();
+
+			@Test
+			void shouldAddExpression() {
+				var query = service.createQuery(filterCriteria);
+
+				assertThat(query.getExpressionsList()).extracting(GrpcVorgangQueryExpression::getPath)
+						.containsOnlyOnce(VORGAENGE_WITH_UNGELESENE_NACHRICHTEN_PATH);
+			}
+
+			@Test
+			void shouldHaveOperator() {
+				var expression = getExpression(service.createQuery(filterCriteria));
+
+				assertThat(expression.getOperator()).isEqualTo(GrpcQueryOperator.EQUAL);
+			}
+
+			@Test
+			void shouldHaveOperandBoolValue() {
+				var expression = getExpression(service.createQuery(filterCriteria));
+
+				assertThat(expression.getOperandBoolValue()).isTrue();
+			}
+
+			private GrpcVorgangQueryExpression getExpression(GrpcQuery query) {
+				return query.getExpressionsList().stream()
+						.filter(expression -> expression.getPath().equals(VORGAENGE_WITH_UNGELESENE_NACHRICHTEN_PATH)).findFirst().orElseThrow();
+			}
+		}
+
+		@Nested
+		class WhenHasUngeleseneNachrichtenIsFalse {
+
+			private final FilterCriteria filterCriteria = FilterCriteriaTestFactory.createBuilder().hasUngeleseneNachrichten(false).build();
+
+			@Test
+			void shouldNotAddExpression() {
+				var query = service.createQuery(filterCriteria);
+
+				assertThat(query.getExpressionsList()).extracting(GrpcVorgangQueryExpression::getPath)
+						.isNotEqualTo(VORGAENGE_WITH_UNGELESENE_NACHRICHTEN_PATH);
+			}
+		}
+	}
+
 	@DisplayName("Create filterBy")
 	@Nested
 	class TestCreateFilterBy {
 
 		@Test
 		void shouldSetFilterByOrganisationsEinheitId() {
-			var filterCriteria = mapFilterCriteria();
+			var filterCriteria = createFilterBy();
 
 			assertThat(filterCriteria.getFilterByOrganisationseinheitenId())
 					.isEqualTo(FilterCriteriaTestFactory.FILTER_BY_ORGANISATIONS_EINHEITEN_ID);
@@ -200,7 +273,7 @@ class VorgangRemoteServiceTest {
 
 		@Test
 		void shouldSetOrganisationsEinheitIds() {
-			var filterCriteria = mapFilterCriteria();
+			var filterCriteria = createFilterBy();
 
 			assertThat(filterCriteria.getOrganisationseinheitIdList()).containsExactly(FilterCriteriaTestFactory.ORGANISATIONS_EINHEIT_ID);
 		}
@@ -211,7 +284,7 @@ class VorgangRemoteServiceTest {
 
 			@Test
 			void shouldBeSet() {
-				var filterCriteria = mapFilterCriteria();
+				var filterCriteria = createFilterBy();
 
 				assertThat(filterCriteria.getFilterByAssignedTo()).isTrue();
 			}
@@ -223,14 +296,14 @@ class VorgangRemoteServiceTest {
 
 			@Test
 			void shouldBeSetIfExists() {
-				var filterCriteria = mapFilterCriteria();
+				var filterCriteria = createFilterBy();
 
 				assertThat(filterCriteria.getAssignedTo()).isEqualTo(UserProfileTestFactory.ID.toString());
 			}
 
 			@Test
 			void shouldNotBeSetIfNotExist() {
-				var filterCriteria = mapFilterCriteria(FilterCriteriaTestFactory.createBuilder().assignedTo(Optional.empty()).build());
+				var filterCriteria = createFilterBy(FilterCriteriaTestFactory.createBuilder().assignedTo(Optional.empty()).build());
 
 				assertThat(filterCriteria.getAssignedTo()).isEqualTo(StringUtils.EMPTY);
 			}
@@ -242,14 +315,14 @@ class VorgangRemoteServiceTest {
 
 			@Test
 			void shouldBeSetIfExists() {
-				var filterCriteria = mapFilterCriteria();
+				var filterCriteria = createFilterBy();
 
 				assertThat(filterCriteria.getStatusList()).containsExactly(FilterCriteriaTestFactory.VORGANG_STATUS.toString());
 			}
 
 			@Test
 			void shouldNotBeSetIfNotExist() {
-				var filterCriteria = mapFilterCriteria(FilterCriteriaTestFactory.createBuilder().status(Optional.empty()).build());
+				var filterCriteria = createFilterBy(FilterCriteriaTestFactory.createBuilder().status(Optional.empty()).build());
 
 				assertThat(filterCriteria.getStatusCount()).isZero();
 
@@ -262,25 +335,25 @@ class VorgangRemoteServiceTest {
 
 			@Test
 			void shouldBeSetToFalse() {
-				var filterCriteria = mapFilterCriteria(FilterCriteriaTestFactory.createBuilder().hasNextWiedervorlageFrist(false).build());
+				var filterCriteria = createFilterBy(FilterCriteriaTestFactory.createBuilder().hasNextWiedervorlageFrist(false).build());
 
 				assertThat(filterCriteria.getHasNextWiedervorlageFrist()).isFalse();
 			}
 
 			@Test
 			void shouldNotBeSetToTrue() {
-				var filterCriteria = mapFilterCriteria(FilterCriteriaTestFactory.createBuilder().hasNextWiedervorlageFrist(true).build());
+				var filterCriteria = createFilterBy(FilterCriteriaTestFactory.createBuilder().hasNextWiedervorlageFrist(true).build());
 
 				assertThat(filterCriteria.getHasNextWiedervorlageFrist()).isTrue();
 			}
 		}
 
-		private GrpcFilterBy mapFilterCriteria() {
-			return mapFilterCriteria(FilterCriteriaTestFactory.create());
+		private GrpcFilterBy createFilterBy() {
+			return createFilterBy(FilterCriteriaTestFactory.create());
 		}
 
-		private GrpcFilterBy mapFilterCriteria(FilterCriteria filterCriteria) {
-			return service.mapFilterCriteria(filterCriteria);
+		private GrpcFilterBy createFilterBy(FilterCriteria filterCriteria) {
+			return service.createFilterBy(filterCriteria);
 		}
 	}
 
@@ -300,14 +373,14 @@ class VorgangRemoteServiceTest {
 				when(serviceStub.findVorgangWithEingang(any()))
 						.thenReturn(GrpcVorgangWithEingangResponseTestFactory.createVorgangWithEingangResponse());
 				when(vorgangWithEingangMapper.toVorgangWithEingang(any())).thenReturn(vorgangWithEingang);
-				doReturn(filterBy).when(service).mapFilterCriteria(any());
+				doReturn(filterBy).when(service).createFilterBy(any());
 			}
 
 			@Test
 			void shouldCreateFilterBy() {
 				callService();
 
-				verify(service).mapFilterCriteria(any());
+				verify(service).createFilterBy(any());
 			}
 
 			@Test
@@ -345,7 +418,7 @@ class VorgangRemoteServiceTest {
 
 			@BeforeEach
 			void mockReturnValue() {
-				doReturn(filterBy).when(service).mapFilterCriteria(any());
+				doReturn(filterBy).when(service).createFilterBy(any());
 			}
 
 			@Test
diff --git a/pom.xml b/pom.xml
index 4f00d84c16a1cc6f981d55ab11f3d1d05e2eb9fd..63d83b82f45e7cb960bc3f0d3382c29e7a999119 100644
--- a/pom.xml
+++ b/pom.xml
@@ -50,7 +50,7 @@
 		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
 
-		<vorgang-manager.version>2.3.0</vorgang-manager.version>
+		<vorgang-manager.version>2.4.0-SNAPSHOT</vorgang-manager.version>
 		<ozgcloud-common-pdf.version>3.0.1</ozgcloud-common-pdf.version>
 		<user-manager.version>2.2.0</user-manager.version>