diff --git a/.gitignore b/.gitignore
index 46d572ccd238a27143d93968afb8f8a797b1f7ed..3585f2b73ecf1c9ddc9c46a21d91f18dbe79b937 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,5 @@
+*private.env.json
+
 ### VisualStudioCode template
 .vscode/*
 !.vscode/settings.json
diff --git a/DummyClient/.dockerignore b/DummyClient/.dockerignore
new file mode 100644
index 0000000000000000000000000000000000000000..38bece4e1ed9968d70beb5815ba4dcead8b592d5
--- /dev/null
+++ b/DummyClient/.dockerignore
@@ -0,0 +1,25 @@
+**/.dockerignore
+**/.env
+**/.git
+**/.gitignore
+**/.project
+**/.settings
+**/.toolstarget
+**/.vs
+**/.vscode
+**/.idea
+**/*.*proj.user
+**/*.dbmdl
+**/*.jfm
+**/azds.yaml
+**/bin
+**/charts
+**/docker-compose*
+**/Dockerfile*
+**/node_modules
+**/npm-debug.log
+**/obj
+**/secrets.dev.yaml
+**/values.dev.yaml
+LICENSE
+README.md
\ No newline at end of file
diff --git a/DummyClient/Dockerfile b/DummyClient/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..2e2e405808c74fafa716b3126ca341d547c3dbfb
--- /dev/null
+++ b/DummyClient/Dockerfile
@@ -0,0 +1,18 @@
+FROM mcr.microsoft.com/dotnet/runtime:6.0 AS base
+WORKDIR /app
+
+FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
+WORKDIR /src
+COPY ["DummyClient/DummyClient.csproj", "DummyClient/"]
+RUN dotnet restore "DummyClient/DummyClient.csproj"
+COPY . .
+WORKDIR "/src/DummyClient"
+RUN dotnet build "DummyClient.csproj" -c Release -o /app/build
+
+FROM build AS publish
+RUN dotnet publish "DummyClient.csproj" -c Release -o /app/publish
+
+FROM base AS final
+WORKDIR /app
+COPY --from=publish /app/publish .
+ENTRYPOINT ["dotnet", "DummyClient.dll"]
diff --git a/DummyClient/DummyClient.csproj b/DummyClient/DummyClient.csproj
new file mode 100644
index 0000000000000000000000000000000000000000..e449bbc26417523e8a0a2dc0ac0878d7f2f50811
--- /dev/null
+++ b/DummyClient/DummyClient.csproj
@@ -0,0 +1,15 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+    <PropertyGroup>
+        <OutputType>Exe</OutputType>
+        <TargetFramework>net6.0</TargetFramework>
+        <ImplicitUsings>enable</ImplicitUsings>
+        <Nullable>enable</Nullable>
+        <DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
+    </PropertyGroup>
+
+    <ItemGroup>
+        <ProjectReference Include="..\FitConnect\FitConnect.csproj"/>
+    </ItemGroup>
+
+</Project>
diff --git a/DummyClient/DummyClient.csproj.DotSettings b/DummyClient/DummyClient.csproj.DotSettings
new file mode 100644
index 0000000000000000000000000000000000000000..453288bf2b5f62addc7e0fb4b6705154705069ae
--- /dev/null
+++ b/DummyClient/DummyClient.csproj.DotSettings
@@ -0,0 +1,2 @@
+<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
+	<s:String x:Key="/Default/CodeInspection/Highlighting/UsageCheckingInspectionLevel/@EntryValue">Off</s:String></wpf:ResourceDictionary>
\ No newline at end of file
diff --git a/DummyClient/Program.cs b/DummyClient/Program.cs
new file mode 100644
index 0000000000000000000000000000000000000000..b5d49cb0fc4ae21f7144eeac2beedb70b2a60202
--- /dev/null
+++ b/DummyClient/Program.cs
@@ -0,0 +1,45 @@
+using System;
+using FitConnect;
+using FitConnect.Models;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Logging.Abstractions;
+
+Client client;
+
+
+void FluentSenderCall() {
+    client.Sender
+        .WithDestination("destinationId")
+        .WithAttachments(Array.Empty<Attachment>())
+        .WithData(@"{""data"":""content""}")
+        .Submit();
+
+    client.Sender
+        .WithDestination("destinationId")
+        .WithAttachments(Array.Empty<Attachment>())
+        .Submit();
+}
+
+void FluentSubscriberCall() {
+    var submissions = client.Subscriber
+        .GetAvailableSubmissions("destinationId");
+
+    client.Subscriber.RequestSubmission("submissionId")
+        .GetAttachments((attachments => {
+            // Check if the attachments are valid
+            return true;
+        }));
+}
+
+
+ILogger logger = new Logger<AppDomain>(new NullLoggerFactory());
+client = new Client(
+    FitConnectEnvironments.Create(FitConnectEnvironments.EndpointType.Development),
+    "clientId", "clientSecret",
+    logger);
+
+Console.WriteLine(
+    "This is a dummy client to demonstrate the usage of the FitConnect SDK for .NET");
+
+FluentSenderCall();
+FluentSubscriberCall();
diff --git a/EncryptionTests/assets/attachment.pdf b/EncryptionTests/assets/attachment.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..a24cb7fcc27b3f3269b6892336a149d145dcc2a6
Binary files /dev/null and b/EncryptionTests/assets/attachment.pdf differ
diff --git a/FitConnect.sln b/FitConnect.sln
index c5c0855687791447a470f8dedf8d42b4fa5b25e8..d5a5bcffde12205d47fcacd2dc4bfc6b02fc6927 100644
--- a/FitConnect.sln
+++ b/FitConnect.sln
@@ -2,9 +2,7 @@
 Microsoft Visual Studio Solution File, Format Version 12.00
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FitConnect", "FitConnect\FitConnect.csproj", "{DFF6A0D9-5AA1-4640-B26C-4A0A28E42FA1}"
 EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{D382641C-B027-411A-814C-C8C20A9505F3}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InitializationTests", "InitializationTests\InitializationTests.csproj", "{73CE5625-4C13-458E-B524-0DAA850F4041}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DummyClient", "DummyClient\DummyClient.csproj", "{DEF51494-6BCD-4441-8D76-6769BBA2C089}"
 EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -16,12 +14,11 @@ Global
 		{DFF6A0D9-5AA1-4640-B26C-4A0A28E42FA1}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{DFF6A0D9-5AA1-4640-B26C-4A0A28E42FA1}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{DFF6A0D9-5AA1-4640-B26C-4A0A28E42FA1}.Release|Any CPU.Build.0 = Release|Any CPU
-		{73CE5625-4C13-458E-B524-0DAA850F4041}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{73CE5625-4C13-458E-B524-0DAA850F4041}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{73CE5625-4C13-458E-B524-0DAA850F4041}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{73CE5625-4C13-458E-B524-0DAA850F4041}.Release|Any CPU.Build.0 = Release|Any CPU
+		{DEF51494-6BCD-4441-8D76-6769BBA2C089}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{DEF51494-6BCD-4441-8D76-6769BBA2C089}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{DEF51494-6BCD-4441-8D76-6769BBA2C089}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{DEF51494-6BCD-4441-8D76-6769BBA2C089}.Release|Any CPU.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(NestedProjects) = preSolution
-		{73CE5625-4C13-458E-B524-0DAA850F4041} = {D382641C-B027-411A-814C-C8C20A9505F3}
 	EndGlobalSection
 EndGlobal
diff --git a/FitConnect/Client.cs b/FitConnect/Client.cs
new file mode 100644
index 0000000000000000000000000000000000000000..3146b465a5595f130f35e76764bb7a5669d2467e
--- /dev/null
+++ b/FitConnect/Client.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Threading.Tasks;
+using Microsoft.Extensions.Logging;
+
+namespace FitConnect;
+
+/// <summary>
+///     The FitConnect API Client
+/// </summary>
+// ReSharper disable once UnusedType.Global
+public class Client {
+    internal string? ClientId;
+    internal string? ClientSecret;
+
+    public IFluentSender Sender { get; }
+
+    public IFluentSubscriber Subscriber { get; }
+    // private Routing Routing { get; }
+
+
+    /// <summary>
+    /// Constructor for the FitConnect API Client
+    /// </summary>
+    /// <param name="environments">Choose one endpoint or create your own one</param>
+    /// <param name="clientId">Your client id</param>
+    /// <param name="clientSecret">Your client secret</param>
+    /// <param name="logger">Optional logger</param>
+    public Client(
+        FitConnectEnvironments environments,
+        string clientId,
+        string clientSecret,
+        ILogger? logger = null) {
+        ClientId = clientId;
+        ClientSecret = clientSecret;
+    }
+}
diff --git a/FitConnect/FitConnect.csproj b/FitConnect/FitConnect.csproj
index e68ef46d3248e87d41a64e110a51b05c2fb89495..25b093e1c63712f8f48c97e92133e5d0f37be8f1 100644
--- a/FitConnect/FitConnect.csproj
+++ b/FitConnect/FitConnect.csproj
@@ -11,7 +11,20 @@
     </PropertyGroup>
 
     <ItemGroup>
+      <PackageReference Include="Autofac" Version="6.4.0" />
       <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.1" />
+      <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
+      <PackageReference Include="Newtonsoft.Json.Schema" Version="3.0.14" />
+      <PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.20.0" />
+    </ItemGroup>
+
+    <ItemGroup>
+      <None Remove="metadata.schema.json" />
+      <EmbeddedResource Include="metadata.schema.json" />
+    </ItemGroup>
+
+    <ItemGroup>
+      <ProjectReference Include="..\Services\Services.csproj" />
     </ItemGroup>
 
 </Project>
diff --git a/FitConnect/FitConnect.csproj.DotSettings b/FitConnect/FitConnect.csproj.DotSettings
new file mode 100644
index 0000000000000000000000000000000000000000..f82351d60d72e7de02dd6aab4adca153a75297f6
--- /dev/null
+++ b/FitConnect/FitConnect.csproj.DotSettings
@@ -0,0 +1,2 @@
+<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
+	<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=interfaces/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
\ No newline at end of file
diff --git a/FitConnect/FunctionalBaseClass.cs b/FitConnect/FunctionalBaseClass.cs
index 4c318964010911cfa6b51f277684993778297b46..e9cb4b2de5a4df239d7e6cb5f2f8cd839808f50e 100644
--- a/FitConnect/FunctionalBaseClass.cs
+++ b/FitConnect/FunctionalBaseClass.cs
@@ -1,20 +1,40 @@
+using System.Net.Http.Headers;
 using System.Net.Http.Json;
+using System.Security.Cryptography;
 using System.Text;
+using FitConnect.Models;
 using Microsoft.Extensions.Logging;
 
 namespace FitConnect;
 
-public class FitConnectEndpoints {
-    public FitConnectEndpoints(string tokenUrl, string submissionApi, string routingApi) {
+public class FitConnectEnvironments {
+    /// <summary>
+    /// Default constructor.
+    /// </summary>
+    /// <param name="tokenUrl">URL for receiving the OAuth token</param>
+    /// <param name="submissionApi">URL for the submission API</param>
+    /// <param name="routingApi">URL for the routing API</param>
+    public FitConnectEnvironments(string tokenUrl, string[] submissionApi, string routingApi) {
         TokenUrl = tokenUrl;
         SubmissionApi = submissionApi;
         RoutingApi = routingApi;
     }
 
-    public string TokenUrl { get; } 
-    public string SubmissionApi { get; }
+    /// <summary>
+    /// URL for receiving the OAuth token.
+    /// </summary>
+    public string TokenUrl { get; }
+
+    /// <summary>
+    /// URL for the submission API.
+    /// </summary>
+    public string[] SubmissionApi { get; }
+
+    /// <summary>
+    /// URL for the routing API.
+    /// </summary>
     public string RoutingApi { get; }
-    
+
 
     public enum EndpointType {
         Development,
@@ -22,46 +42,122 @@ public class FitConnectEndpoints {
         Production
     }
 
-    public static FitConnectEndpoints Create(EndpointType endpointType) {
+    /// <summary>
+    /// Creates the endpoints for the given environment.
+    /// </summary>
+    /// <param name="endpointType">Environment to get endpoints for</param>
+    /// <returns></returns>
+    /// <exception cref="ArgumentException">Not all environments are ready to use</exception>
+    public static FitConnectEnvironments Create(EndpointType endpointType) {
         return endpointType switch {
-            EndpointType.Development => DevEndpoints,
+            EndpointType.Development => DevEnvironments,
             EndpointType.Testing => throw new ArgumentException("Not approved for online testing"),
             EndpointType.Production => throw new ArgumentException("NOT PRODUCTION READY"),
             _ => throw new ArgumentOutOfRangeException(nameof(endpointType), endpointType, null)
         };
     }
 
-    private static readonly FitConnectEndpoints DevEndpoints = new(
-         "https://auth-testing.fit-connect.fitko.dev/token",
-         "https://submission-api-testing.fit-connect.fitko.dev",
-         "https://routing-api-testing.fit-connect.fitko.dev"
+    private static readonly FitConnectEnvironments DevEnvironments = new(
+        "https://auth-testing.fit-connect.fitko.dev/token",
+        new []{"https://submission-api-testing.fit-connect.fitko.dev"},
+        "https://routing-api-testing.fit-connect.fitko.dev"
     );
 
-    private static readonly FitConnectEndpoints TestEndpoints = new(
+    private static readonly FitConnectEnvironments TestEnvironments = new(
         "https://auth-testing.fit-connect.fitko.dev/token",
-        "https://submission-api-testing.fit-connect.fitko.dev",
+        new []{"https://submission-api-testing.fit-connect.fitko.dev"},
         "https://routing-api-testing.fit-connect.fitko.dev"
     );
 
-    private static readonly FitConnectEndpoints ProductionEndpoints = new(
+    private static readonly FitConnectEnvironments ProductionEnvironments = new(
         "https://auth-testing.fit-connect.fitko.dev/token",
-        "https://submission-api-testing.fit-connect.fitko.dev",
+        new []{"https://submission-api-testing.fit-connect.fitko.dev"},
         "https://routing-api-testing.fit-connect.fitko.dev"
     );
 }
 
-public class FunctionalBaseClass {
-    private readonly ILogger? logger;
-    public FitConnectEndpoints Endpoints { get; }
+public abstract class FunctionalBaseClass {
+    protected readonly ILogger? logger;
+    private RSA _rsa;
+    public FitConnectEnvironments Environments { get; }
 
-    protected FunctionalBaseClass(ILogger? logger, FitConnectEndpoints? endpoints) {
-        Endpoints = endpoints ??
-                    FitConnectEndpoints.Create(FitConnectEndpoints.EndpointType.Development);
+    protected FunctionalBaseClass(ILogger? logger, FitConnectEnvironments? endpoints) {
+        Environments = endpoints ??
+                    FitConnectEnvironments.Create(FitConnectEnvironments.EndpointType.Development);
 
         this.logger = logger;
     }
 
 
+    /// <summary>
+    /// Requesting an OAuth token from the FitConnect API.
+    /// 
+    /// You can get the Client ID and Client Secret from the FitConnect Self Service portal
+    /// under https://portal.auth-testing.fit-connect.fitko.dev
+    /// </summary>
+    /// <param name="clientId">Your client Id</param>
+    /// <param name="clientSecret">Your client Secret</param>
+    /// <param name="scope">Scope if needed</param>
+    /// <returns></returns>
+    public async Task<OAuthAccessToken?> GetTokenAsync(string clientId, string clientSecret,
+        string? scope = null) {
+        var client = new HttpClient();
+        client.DefaultRequestHeaders.Accept.Add(
+            MediaTypeWithQualityHeaderValue.Parse("application/json"));
+
+        var requestContent = new Dictionary<string, string> {
+            { "grant_type", "client_credentials" },
+            { "client_id", clientId },
+            { "client_secret", clientSecret }
+        };
+
+        if (scope != null)
+            requestContent["scope"] = scope;
+
+        var content = new FormUrlEncodedContent(requestContent);
+
+        var request = new HttpRequestMessage(HttpMethod.Post, Environments.TokenUrl) {
+            Content = content,
+            Method = HttpMethod.Post
+        };
+
+        var response = await client.SendAsync(request);
+
+        return await response.Content.ReadFromJsonAsync<OAuthAccessToken>();
+    }
+
+    public Task<SecurityEventToken> GetSetDataAsync() {
+        throw new NotImplementedException();
+    }
+
+    public byte[] EncryptDataAsync(byte[] data,
+        byte[]? publicKey,
+        string? password,
+        int numberOfIterations) {
+        _rsa = RSA.Create(2048);
+        // _rsa.ImportRSAPublicKey(publicKey, out var read);
+
+        logger?.LogInformation(
+            "Encrypting data with public key: {}",
+            Convert.ToBase64String(_rsa.ExportRSAPublicKey()));
+
+        // var keyParams = new PbeParameters(
+        //     PbeEncryptionAlgorithm.Aes256Cbc, HashAlgorithmName.SHA256, numberOfIterations);
+        //
+        // var privateKey =
+        //     rsa.ExportEncryptedPkcs8PrivateKey(Encoding.UTF8.GetBytes(password), keyParams);
+        //
+        // logger?.LogInformation(
+        //     "Private key: {}", privateKey);
+
+        return _rsa.Encrypt(data, RSAEncryptionPadding.OaepSHA256);
+    }
+
+    public byte[] DecryptDataAsync(byte[] data, byte[] privateKey) {
+        return _rsa.Decrypt(data, RSAEncryptionPadding.OaepSHA256);
+    }
+
+
     private async Task<T?> RestCall<T>(Uri uri, HttpMethod method, string body) {
         var client = new HttpClient();
         client.DefaultRequestHeaders.Add("Accept", "application/json");
diff --git a/FitConnect/Interfaces/IBaseFunctionality.cs b/FitConnect/Interfaces/IBaseFunctionality.cs
new file mode 100644
index 0000000000000000000000000000000000000000..14665ab9662ba3662f28bca67de41159ec4162c0
--- /dev/null
+++ b/FitConnect/Interfaces/IBaseFunctionality.cs
@@ -0,0 +1,13 @@
+using System.Threading.Tasks;
+using FitConnect.Models;
+
+namespace FitConnect;
+
+public interface IBaseFunctionality {
+    Task<OAuthAccessToken> GetTokenAsync(string clientId, string clientSecret,
+        string? scope = null);
+
+    Task<SecurityEventToken> GetSetDataAsync();
+
+    // Receive SecurityEventToken and check signature
+}
\ No newline at end of file
diff --git a/FitConnect/Interfaces/IFluentApi.cs b/FitConnect/Interfaces/IFluentApi.cs
new file mode 100644
index 0000000000000000000000000000000000000000..3205566d23fe10946a9741c7ecedf8b7ca5a6d32
--- /dev/null
+++ b/FitConnect/Interfaces/IFluentApi.cs
@@ -0,0 +1,78 @@
+using System;
+using System.Collections.Generic;
+using FitConnect.Models;
+
+namespace FitConnect;
+
+public interface IFluentSender {
+    /// <summary>
+    /// Configures the client for the given destination and loads the public key
+    /// </summary>
+    /// <param name="destinationId">unique identifier of the clients destination</param>
+    /// <returns>the upload step for attachments</returns>
+    public IFluentSenderWithDestination WithDestination(string destinationId);
+
+    public IFluentSenderWithData WithData(string data);
+
+    /// <summary>
+    /// Send submission to FIT-Connect API.
+    /// </summary>
+    /// <returns>submitted submission</returns>
+    public Submission Submit();
+}
+
+public interface IFluentSenderWithDestination {
+    /// <summary>
+    /// Sends the submission with a list of attachments
+    /// </summary>
+    /// <param name="attachments">that are sent with the submission</param>
+    /// <returns>the step where additional data can be added to the submission</returns>
+    public IFluentSenderWithAttachments WithAttachments(IEnumerable<Attachment> attachments);
+}
+
+public interface IFluentSenderWithAttachments : IFluentSenderReady {
+    /// <summary>
+    /// Data as string.
+    /// </summary>
+    /// <param name="data">json or xml as string</param>
+    /// <returns>next step to submit the data</returns>
+    public IFluentSenderWithData WithData(string data);
+}
+
+public interface IFluentSenderWithData : IFluentSenderReady {
+}
+
+public interface IFluentSenderReady {
+    /// <summary>
+    /// Send submission to FIT-Connect API.
+    /// </summary>
+    /// <returns>submitted submission</returns>
+    public IFluentSender Submit();
+}
+
+public interface IFluentSubscriber {
+    /// <summary>
+    /// Loads a list of available Submissions that were submitted to the subscriber.
+    /// </summary>
+    /// <returns>List of available submissions for pickup</returns>
+    public IEnumerable<string> GetAvailableSubmissions(string? destinationId = null);
+
+    /// <summary>
+    /// Loads a single Submission by id.
+    /// </summary>
+    /// <param name="submissionId">unique identifier of a <see cref="Submission"/></param>
+    /// <returns></returns>
+    public IFluentSubscriberWithSubmission RequestSubmission(string submissionId);
+}
+
+public interface IFluentSubscriberWithSubmission {
+    public Submission Submission { get; }
+
+    /// <summary>
+    /// Loads the <see cref="Attachment"/>s for the given <see cref="Submission"/>.
+    /// </summary>
+    /// <param name="canSubmitSubmission">Function that returns a boolean if the <see cref="Submission"/> can be confirmed</param>
+    /// <returns></returns>
+    public IFluentSenderWithAttachments GetAttachments(
+        Func<IEnumerable<Attachment>, bool> canSubmitSubmission);
+}
diff --git a/FitConnect/Interfaces/ISender.cs b/FitConnect/Interfaces/ISender.cs
new file mode 100644
index 0000000000000000000000000000000000000000..ed47036ac5e3501093bb6a180658c06e74e3ffe3
--- /dev/null
+++ b/FitConnect/Interfaces/ISender.cs
@@ -0,0 +1,17 @@
+using System.Threading.Tasks;
+
+namespace FitConnect;
+
+public interface ISender : IBaseFunctionality {
+    // Check public keys
+    Task<bool> CheckPublicKeyAsync(string publicKey);
+
+    // Encrypt Data (Fachdaten)
+    byte[] EncryptDataAsync(string data, string publicKey);
+
+    // Encrypt attachments (Anhänge)
+    Task<string> EncryptAttachmentAsync(string attachment, string publicKey);
+
+    // Create Metadata incl. Hash
+    Task<string> CreateMetadataAsync(string data, string attachment, string publicKey);
+}
\ No newline at end of file
diff --git a/FitConnect/Interfaces/ISubscriber.cs b/FitConnect/Interfaces/ISubscriber.cs
new file mode 100644
index 0000000000000000000000000000000000000000..6456dab3cceef9c0b81a6a15d5f0df22fab547b6
--- /dev/null
+++ b/FitConnect/Interfaces/ISubscriber.cs
@@ -0,0 +1,31 @@
+using System.Threading.Tasks;
+using FitConnect.Models;
+
+namespace FitConnect;
+
+public interface ISubscriber : IBaseFunctionality {
+    /// <summary>
+    /// Decrypt Data (Fachdaten)
+    /// </summary>
+    /// <param name="data">(Fachdaten)</param>
+    /// <param name="privateKey">Your private key for decryption</param>
+    /// <returns></returns>
+    Task<string> DecryptDataAsync(string data, string privateKey);
+
+    // Decrypt attachments (Anhänge)
+    Task<string> DecryptAttachmentAsync(string attachment, string privateKey);
+
+    /// <summary>
+    /// Checks the validity of the given metadata against the schema.
+    /// </summary>
+    /// <param name="jsonMetaData">JSON meta data</param>
+    /// <returns></returns>
+    Task<bool> CheckMetadataAsync(string jsonMetaData);
+
+    // Check Hash from Metadata
+    Task<bool> CheckHashAsync(string metadata);
+
+    // Create SecurityEventToken and signature
+    Task<SecurityEventToken> CreateSecurityEventTokenAsync(string data, string attachment,
+        string privateKey);
+}
\ No newline at end of file
diff --git a/FitConnect/Models/Area.cs b/FitConnect/Models/Area.cs
new file mode 100644
index 0000000000000000000000000000000000000000..71215cc66b6cdcad6252b9b5a102c0d93d836386
--- /dev/null
+++ b/FitConnect/Models/Area.cs
@@ -0,0 +1,3 @@
+namespace FitConnect.Models;
+
+public record Area(string Id, string Name, string Type);
diff --git a/FitConnect/Models/Attachment.cs b/FitConnect/Models/Attachment.cs
new file mode 100644
index 0000000000000000000000000000000000000000..2c1e5da5761e07a7d46931324df81c8fc778d1f0
--- /dev/null
+++ b/FitConnect/Models/Attachment.cs
@@ -0,0 +1,3 @@
+namespace FitConnect.Models;
+
+public record Attachment(string Id, byte[] Content, string Hash, string Filename);
diff --git a/FitConnect/Models/Callback.cs b/FitConnect/Models/Callback.cs
new file mode 100644
index 0000000000000000000000000000000000000000..cd99183d815dd08497737a0749127d1aee6e2a37
--- /dev/null
+++ b/FitConnect/Models/Callback.cs
@@ -0,0 +1,6 @@
+
+
+namespace FitConnect.Models;
+
+public record Callback(string? Url, string? Secret) {
+ }
diff --git a/FitConnect/Models/FitConnectException.cs b/FitConnect/Models/FitConnectException.cs
new file mode 100644
index 0000000000000000000000000000000000000000..fbd8c908b35a8e5fe7bdeb29912b2382866b61ce
--- /dev/null
+++ b/FitConnect/Models/FitConnectException.cs
@@ -0,0 +1,19 @@
+using System;
+
+namespace FitConnect.Models;
+
+/// <summary>
+///     Representation of FitConnect error responses
+/// </summary>
+public class FitConnectException : Exception {
+    public enum ErrorTypeEnum {
+        Unknown
+    }
+
+    public FitConnectException(string message, ErrorTypeEnum errorType = ErrorTypeEnum.Unknown,
+        Exception? innerException = null) : base(message, innerException) {
+        ErrorType = errorType;
+    }
+
+    public ErrorTypeEnum ErrorType { get; set; }
+}
diff --git a/FitConnect/Models/Metadata.cs b/FitConnect/Models/Metadata.cs
new file mode 100644
index 0000000000000000000000000000000000000000..e5268ab7532bf0baedcb5ea7832dd4039884641d
--- /dev/null
+++ b/FitConnect/Models/Metadata.cs
@@ -0,0 +1,9 @@
+using System.Security.Cryptography.X509Certificates;
+
+namespace FitConnect.Models;
+
+public class Metadata  {
+}
+
+public class Data {
+}
diff --git a/FitConnect/Models/OAuthAccessToken.cs b/FitConnect/Models/OAuthAccessToken.cs
new file mode 100644
index 0000000000000000000000000000000000000000..87ac3872e52a9a9e88e1df33eace09bb8fbd3ed1
--- /dev/null
+++ b/FitConnect/Models/OAuthAccessToken.cs
@@ -0,0 +1,17 @@
+using System.Text.Json.Serialization;
+
+namespace FitConnect.Models;
+
+public class OAuthAccessToken {
+    [JsonPropertyName("access_token")]
+    public string AccessToken { get; set; }
+
+    [JsonPropertyName("scope")]
+    public string Scope { get; set; }
+
+    [JsonPropertyName("token_type")]
+    public string TokenType { get; set; }
+
+    [JsonPropertyName("expires_in")]
+    public int ExpiresIn { get; set; }
+}
diff --git a/FitConnect/Models/Route.cs b/FitConnect/Models/Route.cs
new file mode 100644
index 0000000000000000000000000000000000000000..9c58fe8111327d6687f78168273113aecc19e3fb
--- /dev/null
+++ b/FitConnect/Models/Route.cs
@@ -0,0 +1,3 @@
+namespace FitConnect.Models;
+
+public record Route;
diff --git a/FitConnect/Models/SecurityEventToken.cs b/FitConnect/Models/SecurityEventToken.cs
new file mode 100644
index 0000000000000000000000000000000000000000..88a700524c1c8270c9d06685d8e0552cafb0345d
--- /dev/null
+++ b/FitConnect/Models/SecurityEventToken.cs
@@ -0,0 +1,3 @@
+namespace FitConnect.Models;
+
+public record SecurityEventToken;
diff --git a/FitConnect/Models/ServiceType.cs b/FitConnect/Models/ServiceType.cs
new file mode 100644
index 0000000000000000000000000000000000000000..1de00dd23cfbe49e8c1f9adeebef196b72a394ec
--- /dev/null
+++ b/FitConnect/Models/ServiceType.cs
@@ -0,0 +1,15 @@
+
+
+namespace FitConnect.Models;
+
+public class ServiceType {
+    public string? Name { get; set; }
+
+    public string? Description { get; set; }
+    public string? Identifier { get; set; }
+
+
+    public bool IsValid() {
+        return !string.IsNullOrWhiteSpace(Name) && !string.IsNullOrWhiteSpace(Identifier);
+    }
+}
diff --git a/FitConnect/Models/Submission.cs b/FitConnect/Models/Submission.cs
new file mode 100644
index 0000000000000000000000000000000000000000..a6f18fcb3aed374406c1df5a7833a71040b8635d
--- /dev/null
+++ b/FitConnect/Models/Submission.cs
@@ -0,0 +1,59 @@
+
+
+using System.Collections.Generic;
+
+namespace FitConnect.Models;
+
+public class Destination {
+    public string LeikaKey { get; set; }
+    public string? Ags { get; set; }
+    public string? Ars { get; set; }
+    public string? AreaId { get; set; }
+    public string DestinationId { get; set; }
+
+    public bool Valid => !((string.IsNullOrWhiteSpace(Ags)
+                            && string.IsNullOrWhiteSpace(Ars)
+                            && string.IsNullOrWhiteSpace(AreaId)) ||
+                           string.IsNullOrWhiteSpace(LeikaKey));
+}
+
+public class Submission {
+    public string Id { get; set; }
+    public string? CaseId { get; set; }
+    public Destination Destination { get; set; } = new Destination();
+
+    public string DestinationId {
+        get => Destination.DestinationId;
+        set => Destination.DestinationId = value;
+    }
+
+    public List<Attachment> Attachments { get; set; } = new();
+
+    public ServiceType ServiceType { get; init; }
+
+    public Callback? Callback { get; set; }
+    public Metadata? Metadata { get; set; }
+    public Data? Data { get; set; }
+    public string EncryptedMetadata { get; set; }
+    public string EncryptedData { get; set; }
+
+    public bool IsSubmissionReadyToAdd(out string? error) {
+        var innerError = "";
+        if (string.IsNullOrEmpty(DestinationId)) innerError += "DestinationId is required\r\n";
+
+        if (ServiceType.IsValid()) innerError += "ServiceType is invalid\r\n";
+
+        if (string.IsNullOrWhiteSpace(innerError)) {
+            error = null;
+            return true;
+        }
+
+        error = innerError.Trim();
+        return false;
+    }
+
+    public bool IsSubmissionReadyToSend() {
+        return true;
+    }
+
+}
diff --git a/FitConnect/Security/IEncryption.cs b/FitConnect/Security/IEncryption.cs
new file mode 100644
index 0000000000000000000000000000000000000000..92bf328814bab3acb703c1c0bc28d018a5d6302a
--- /dev/null
+++ b/FitConnect/Security/IEncryption.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Security.Cryptography.X509Certificates;
+
+namespace FitConnect.Security;
+
+public interface IEncryption {
+    /// <summary>
+    ///     Just for Proof of Concept
+    /// </summary>
+    /// <returns></returns>
+    string GetTestToken();
+
+    void ImportCertificate(X509Certificate2 cert);
+
+    /// <summary>
+    ///     Import a public key from a PEM file
+    /// </summary>
+    /// <param name="certificatePath"></param>
+    /// <param name="password">Password for the certificate</param>
+    /// <exception cref="ArgumentException"></exception>
+    /// <exception cref="Exception"></exception>
+    void ImportCertificate(string certificatePath, string password);
+
+    byte[] DecryptData(byte[] data);
+    string DecryptData(string data);
+    
+    byte[] ExportPublicKey();
+    byte[] ExportPrivateKey();
+    byte[] EncryptData(byte[] data);
+    byte[] EncryptData(byte[] data, byte[] publicKey);
+}
diff --git a/FitConnect/Security/RsaEncryption.cs b/FitConnect/Security/RsaEncryption.cs
new file mode 100644
index 0000000000000000000000000000000000000000..570622b28626b12b6e9b7a45e7f817a9265be2cc
--- /dev/null
+++ b/FitConnect/Security/RsaEncryption.cs
@@ -0,0 +1,167 @@
+using System;
+using System.IdentityModel.Tokens.Jwt;
+using System.IO;
+using System.Security.Claims;
+using System.Security.Cryptography;
+using System.Security.Cryptography.X509Certificates;
+using System.Text;
+using Microsoft.Extensions.Logging;
+using Microsoft.IdentityModel.Tokens;
+
+namespace FitConnect.Security;
+
+public class RsaEncryption : IEncryption {
+    private readonly X509Certificate2? _certificate;
+    private readonly ILogger? _logger;
+    private readonly RSA _rsa;
+    private RSA? _privateKey;
+    private RSA? _publicKey;
+
+
+    public RsaEncryption(X509Certificate2? certificate, ILogger? logger) {
+        _logger = logger;
+        _rsa = RSA.Create(4096);
+
+        if (certificate != null) {
+            _certificate = certificate;
+            ImportCertificate(certificate);
+        }
+    }
+
+
+    /// <summary>
+    ///     Just for Proof of Concept
+    /// </summary>
+    /// <returns></returns>
+    public string GetTestToken() {
+        var handler = new JwtSecurityTokenHandler();
+        var token = new SecurityTokenDescriptor {
+            Issuer = "FitConnect",
+            Audience = "FitConnect",
+            EncryptingCredentials =
+                new X509EncryptingCredentials(_certificate ??
+                                              new X509Certificate2(CreateSelfSignedCertificate())),
+            Subject = new ClaimsIdentity(new Claim[] {
+                new("Content", "Unencrypted content")
+            })
+        };
+        return handler.CreateEncodedJwt(token);
+    }
+
+
+    public void ImportCertificate(X509Certificate2 cert) {
+        if (!CheckCertificate(cert)) throw new Exception("Invalid certificate");
+
+        _publicKey = cert.GetRSAPublicKey();
+
+        if ((_publicKey?.KeySize ?? 0) == 0)
+            throw new Exception("Invalid certificate, no public key");
+
+        if (cert.HasPrivateKey) _privateKey = cert.GetRSAPrivateKey();
+
+        if (_privateKey != null)
+            _logger?.LogInformation("Certificate with private key imported");
+        else
+            _logger?.LogInformation("Certificate has no private key");
+    }
+
+    /// <summary>
+    ///     Import a public key from a PEM file
+    /// </summary>
+    /// <param name="certificatePath"></param>
+    /// <param name="password">Password for the certificate</param>
+    /// <exception cref="ArgumentException"></exception>
+    /// <exception cref="Exception"></exception>
+    public void ImportCertificate(string certificatePath, string password) {
+        _logger?.LogInformation("Importing certificate {CertPath}", certificatePath);
+        var cert =
+            new X509Certificate2(certificatePath, password, X509KeyStorageFlags.MachineKeySet);
+
+        if (!CheckCertificate(cert)) throw new ArgumentException("Certificate is not valid");
+
+        var parameters = cert.PublicKey.GetRSAPublicKey()?.ExportParameters(true);
+        if (parameters == null) throw new Exception("Could not get public key from certificate");
+
+        _rsa.ImportParameters(parameters.Value);
+    }
+
+    public byte[] DecryptData(byte[] data) {
+        return (_privateKey ?? _rsa).Decrypt(data, RSAEncryptionPadding.OaepSHA256);
+    }
+
+    public string DecryptData(string data) {
+        return Encoding.UTF8.GetString(DecryptData(Convert.FromBase64String(data)));
+    }
+
+    public byte[] ExportPublicKey() {
+        return _rsa.ExportRSAPublicKey();
+    }
+
+    public byte[] ExportPrivateKey() {
+        return _rsa.ExportRSAPrivateKey();
+    }
+
+    public byte[] EncryptData(byte[] data) {
+        return (_publicKey ?? _rsa).Encrypt(data, RSAEncryptionPadding.OaepSHA256);
+    }
+
+    public byte[] EncryptData(byte[] data, byte[] publicKey) {
+        _logger?.LogInformation(
+            "Encrypting data with public key: {}",
+            Convert.ToBase64String(_rsa.ExportRSAPublicKey()));
+
+        _rsa.ImportRSAPublicKey(publicKey, out var read);
+        return _rsa.Encrypt(data, RSAEncryptionPadding.OaepSHA256);
+    }
+
+    /// <summary>
+    ///     Creating a self signed certificate
+    /// </summary>
+    /// <param name="exportPath">Location for storing the certificate files</param>
+    /// <returns></returns>
+    /// <exception cref="Exception"></exception>
+    public static X509Certificate2 CreateSelfSignedCertificate(string? exportPath = null) {
+        var rsa = RSA.Create(4096);
+
+        var req = new CertificateRequest("c=DE, cn=fitconnect.de",
+            rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
+
+        var cert = req.CreateSelfSigned(DateTimeOffset.Now.AddSeconds(-5),
+            DateTimeOffset.Now.AddYears(5));
+
+        if (cert.GetRSAPublicKey() == null)
+            throw new Exception("Certificate does not contain a public key");
+
+        if (cert.GetRSAPrivateKey() == null)
+            throw new Exception("Certificate does not contain a private key");
+
+        // Export the certificate to a PEM file, just for
+        // additional external testing
+        if (exportPath != null) ExportCertificateToFile(exportPath, cert);
+
+        return cert;
+    }
+
+    private static void ExportCertificateToFile(string exportPath, X509Certificate cert) {
+        // Create PFX (PKCS #12) with private key
+        File.WriteAllBytes($"{exportPath}/certificate.pfx",
+            cert.Export(X509ContentType.Pfx, ""));
+
+        // Create Base 64 encoded CER (public key only)
+        File.WriteAllText($"{exportPath}/certificate.cer",
+            "-----BEGIN CERTIFICATE-----\r\n"
+            + Convert.ToBase64String(cert.Export(X509ContentType.Cert, ""),
+                Base64FormattingOptions.InsertLineBreaks)
+            + "\r\n-----END CERTIFICATE-----");
+    }
+
+
+    /// <summary>
+    ///     Checking the certificate for validity
+    /// </summary>
+    /// <param name="cert">Certificate to check</param>
+    /// <returns>true for a fully approved certificate</returns>
+    private bool CheckCertificate(X509Certificate2 cert) {
+        return true;
+    }
+}
diff --git a/FitConnect/Sender.cs b/FitConnect/Sender.cs
deleted file mode 100644
index 365bc2899fb05721d40a2500e10bb1ff6d64d687..0000000000000000000000000000000000000000
--- a/FitConnect/Sender.cs
+++ /dev/null
@@ -1,8 +0,0 @@
-using Microsoft.Extensions.Logging;
-
-namespace FitConnect;
-
-public class Sender : FunctionalBaseClass {
-    public Sender(ILogger? logger, FitConnectEndpoints endpoints) : base(logger,endpoints) {
-    }
-}
\ No newline at end of file
diff --git a/FitConnect/Subscriber.cs b/FitConnect/Subscriber.cs
deleted file mode 100644
index cde32d1fcc8c774f37b8983b0524d2dec89623c7..0000000000000000000000000000000000000000
--- a/FitConnect/Subscriber.cs
+++ /dev/null
@@ -1,8 +0,0 @@
-using Microsoft.Extensions.Logging;
-
-namespace FitConnect;
-
-public class Subscriber : FunctionalBaseClass {
-    public Subscriber(ILogger logger, FitConnectEndpoints endpoints) : base(logger, endpoints) {
-    }
-}
diff --git a/FitConnect/metadata.schema.json b/FitConnect/metadata.schema.json
new file mode 100644
index 0000000000000000000000000000000000000000..0f730cd32e5411cf4d8d898e589307102f9c40b5
--- /dev/null
+++ b/FitConnect/metadata.schema.json
@@ -0,0 +1,431 @@
+{
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
+  "$id": "https://schema.fitko.de/fit-connect/metadata/1.0.0/metadata.schema.json",
+  "type": "object",
+  "title": "Metadaten",
+  "description": "",
+  "required": [
+    "contentStructure"
+  ],
+  "properties": {
+    "contentStructure": {
+      "description": "Beschreibt die Struktur der zusätzlichen Inhalte der Einreichung, wie Anlagen oder Fachdaten.",
+      "type": "object",
+      "required": [
+        "attachments"
+      ],
+      "properties": {
+        "data": {
+          "description": "Definiert das Schema und die Signatur(-art), die für die Fachdaten verwendet werden.",
+          "type": "object",
+          "required": [
+            "hash",
+            "submissionSchema"
+          ],
+          "properties": {
+            "signature": {
+              "type": "object",
+              "description": "Beschreibt das Signaturformt und Profile",
+              "examples": [],
+              "properties": {
+                "signatureFormat": {
+                  "type": "string",
+                  "description": "Beschreibt, welches Signaturformat die genutzte Signatur / das genutzte Siegel nutzt. Aktuell wird die Hinterlegung folgender Signaturformate unterstützt: CMS = Cryptographic Message Syntax, Asic = Associated Signature Containers, PDF = PDF Signatur, XML = XML-Signature, JSON = JSON Web Signature. ",
+                  "enum": [
+                    "cms",
+                    "xml",
+                    "pdf",
+                    "asic",
+                    "json"
+                  ]
+                },
+                "eidasAdesProfile": {
+                  "type": "string",
+                  "description": "Referenziert ein eindeutiges Profil einer AdES (advanced electronic signature/seal) gemäß eIDAS-Verordnung über eine URI gemäß [ETSI TS 119 192](https://www.etsi.org/deliver/etsi_ts/119100_119199/119192/01.01.01_60/ts_119192v010101p.pdf).\n\nFür die Details zur Verwendung und Validierung von Profilen siehe auch https://ec.europa.eu/cefdigital/DSS/webapp-demo/doc/dss-documentation.html#_signatures_profile_simplification",
+                  "enum": [
+                    "http://uri.etsi.org/ades/191x2/level/baseline/B-B#",
+                    "http://uri.etsi.org/ades/191x2/level/baseline/B-T#",
+                    "http://uri.etsi.org/ades/191x2/level/baseline/B-LT#",
+                    "http://uri.etsi.org/ades/191x2/level/baseline/B-LTA#"
+                  ]
+                },
+                "detachedSignature": {
+                  "type": "boolean",
+                  "description": "Beschreibt, ob die Signatur als seperate (detached) Signatur (`true`) oder als Teil des Fachdatensatzes bzw. der Anlage  (`false`) übertragen wird. Wenn der Wert `true` ist, dann wird die Signatur Base64- oder Base64Url-kodiert im Feld `content` übertragen."
+                },
+                "content": {
+                  "type": "string",
+                  "description": "Hier wird die Signatur im Falle einer Detached-Signatur als Base64- oder Base64Url-kodierte Zeichenkette hinterlegt. Eine Base64Url-Kodierung kommt nur bei Einsatz von JSON Web Signatures (JWS / JAdES) zum Einsatz.",
+                  "pattern": "^[a-zA-Z0-9+/=]+|[a-zA-Z0-9_-]+$"
+                }
+              },
+              "required": [
+                "signatureFormat",
+                "detachedSignature"
+              ]
+            },
+            "hash": {
+              "title": "Hashwert",
+              "description": "Der Hashwert der unverschlüsselten Fachdaten. Die Angabe des Hashwertes dient der Integritätssicherung des Gesamtantrags und schützt vor einem Austausch der Fachdaten durch Systeme zwischen Sender und Subscriber (z.B. dem Zustelldienst).",
+              "type": "object",
+              "required": [
+                "type",
+                "content"
+              ],
+              "properties": {
+                "type": {
+                  "type": "string",
+                  "description": "Der verwendete Hash-Algorithmus. Derzeit ist nur `sha512` erlaubt.",
+                  "enum": [
+                    "sha512"
+                  ]
+                },
+                "content": {
+                  "type": "string",
+                  "description": "Der Hex-kodierte Hashwert gemäß des angegebenen Algorithmus.",
+                  "pattern": "^[a-f0-9]{128}$"
+                }
+              }
+            },
+            "submissionSchema": {
+              "title": "Fachdatenschema",
+              "description": "Referenz auf ein Schema, das die Struktur der Fachdaten einer Einreichung beschreibt.",
+              "type": "object",
+              "required": [
+                "schemaUri",
+                "mimeType"
+              ],
+              "properties": {
+                "schemaUri": {
+                  "type": "string",
+                  "format": "uri",
+                  "description": "URI des Fachschemas. Wird hier eine URL verwendet, sollte das Schema unter der angegebenen URL abrufbar sein. Eine Verfügbarkeit des Schemas unter der angegebenen URL darf jedoch nicht vorausgesetzt werden."
+                },
+                "mimeType": {
+                  "type": "string",
+                  "description": "Mimetype (z.B. application/json oder application/xml) des referenzierten Schemas (z.B. XSD- oder JSON-Schema).",
+                  "enum": [
+                    "application/json",
+                    "application/xml"
+                  ]
+                }
+              }
+            }
+          }
+        },
+        "attachments": {
+          "type": "array",
+          "items": {
+            "type": "object",
+            "description": "Eine in der Einreichung enthaltene Anlage.",
+            "required": [
+              "hash",
+              "purpose",
+              "mimeType",
+              "attachmentId"
+            ],
+            "properties": {
+              "hash": {
+                "title": "Hashwert",
+                "description": "Der Hashwert der unverschlüsselten Anlage. Die Angabe des Hashwertes dient der Integritätssicherung des Gesamtantrags und schützt vor einem Austausch der Anlage durch Systeme zwischen Sender und Subscriber (z.B. dem Zustelldienst).",
+                "type": "object",
+                "required": [
+                  "type",
+                  "content"
+                ],
+                "properties": {
+                  "type": {
+                    "type": "string",
+                    "description": "Der verwendete Hash-Algorithmus. Derzeit ist nur `sha512` erlaubt.",
+                    "enum": [
+                      "sha512"
+                    ]
+                  },
+                  "content": {
+                    "type": "string",
+                    "description": "Der Hex-kodierte Hashwert gemäß des angegebenen Algorithmus.",
+                    "pattern": "^[a-f0-9]{128}$"
+                  }
+                }
+              },
+              "signature": {
+                "$ref": "#/properties/contentStructure/properties/data/properties/signature"
+              },
+              "purpose": {
+                "description": "Zweck/Art der Anlage\n- form: Automatisch generierte PDF-Repräsentation des vollständigen Antragsformulars\n- attachment: Anlage, die von einem Bürger hochgeladen wurde\n- report: Vom Onlinedienst, nachträglich erzeugte Unterlage",
+                "type": "string",
+                "enum": [
+                  "form",
+                  "attachment",
+                  "report"
+                ]
+              },
+              "filename": {
+                "type": "string",
+                "description": "Ursprünglicher Dateiname bei Erzeugung oder Upload"
+              },
+              "description": {
+                "type": "string",
+                "description": "Optionale Beschreibung der Anlage"
+              },
+              "mimeType": {
+                "type": "string",
+                "title": "MIME Type",
+                "description": "Internet Media Type gemäß RFC 2045, z. B. application/pdf.",
+                "examples": [
+                  "application/xml"
+                ],
+                "pattern": "^[-\\w.]+/[-\\w.+]+$"
+              },
+              "attachmentId": {
+                "type": "string",
+                "description": "Innerhalb einer Einreichung eindeutige Id der Anlage im Format einer UUIDv4.",
+                "format": "uuid",
+                "minLength": 32,
+                "maxLength": 36
+              }
+            }
+          }
+        }
+      }
+    },
+    "publicServiceType": {
+      "type": "object",
+      "title": "Verwaltungsleistung",
+      "description": "Beschreibung der Art der Verwaltungsleistung. Eine Verwaltungsleistung sollte immer mit einer LeiKa-Id beschrieben werden. Ist für die gegebene Verwaltungsleistung keine LeiKa-Id vorhanden, kann die Verwaltungsleistung übergangsweise über die Angabe einer anderen eindeutigen Schema-URN beschrieben werden.",
+      "properties": {
+        "name": {
+          "type": "string",
+          "description": "Name/Bezeichnung der Verwaltungsleistung"
+        },
+        "description": {
+          "type": "string",
+          "description": "(Kurz-)Beschreibung der Verwaltungsleistung"
+        },
+        "identifier": {
+          "title": "Leistungs-Identifikator",
+          "description": "URN einer Leistung. Im Falle einer Leistung aus dem Leistungskatalog sollte hier `urn:de:fim:leika:leistung:` vorangestellt werden.\n",
+          "type": "string",
+          "minLength": 7,
+          "maxLength": 255,
+          "pattern": "^urn:[a-z0-9][a-z0-9-]{0,31}:[a-z0-9()+,.:=@;$_!*'%/?#-]+$"
+        }
+      },
+      "required": [
+        "identifier"
+      ]
+    },
+    "authenticationInformation": {
+      "description": "Eine Liste aller Identifikationsnachweise der Einreichung.",
+      "type": "array",
+      "minItems": 1,
+      "items": {
+        "type": "object",
+        "description": "Eine Struktur, die einen Identifikationsnachweis beschreibt.",
+        "properties": {
+          "type": {
+            "description": "Definiert die Art des Identifikationsnachweises.",
+            "type": "string",
+            "enum": [
+              "identificationReport"
+            ]
+          },
+          "version": {
+            "type": "string",
+            "pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)$",
+            "description": "semver kompatible Versionsangabe des genutzten Nachweistyps."
+          },
+          "content": {
+            "type": "string",
+            "description": "Der Nachweis wird als Base64Url-kodierte Zeichenkette angegeben.",
+            "pattern": "^[a-zA-Z0-9_\\-.]+$"
+          }
+        },
+        "required": [
+          "type",
+          "version",
+          "content"
+        ]
+      }
+    },
+    "paymentInformation": {
+      "description": "Dieses Objekt enthält die Informationen vom Bezahldienst.",
+      "type": "object",
+      "required": [
+        "transactionReference",
+        "transactionId",
+        "paymentMethod",
+        "status"
+      ],
+      "properties": {
+        "transactionUrl": {
+          "type": "string",
+          "format": "uri",
+          "minLength": 1,
+          "examples": [
+            "https://payment.bundesland.zzzz/api/v1/paymenttransaction/12002312/MELD-ANT-FORM-4711/9xxd-432x-6543-xfd6-gfdx-fd27"
+          ],
+          "description": "Die Rest-URL der Payment Transaction für die Statusabfrage."
+        },
+        "transactionId": {
+          "type": "string",
+          "minLength": 1,
+          "maxLength": 36,
+          "pattern": "^[\\w\\d-]+$",
+          "examples": [
+            "9xxd-432x-6543-xfd6-gfdx-fd27"
+          ],
+          "description": "Eine vom Bezahldienst vergebene Transaktions-Id."
+        },
+        "transactionReference": {
+          "type": "string",
+          "description": "Bezahlreferenz bzw. Verwendungszweck, wie z. B. ein Kassenzeichen."
+        },
+        "transactionTimestamp": {
+          "type": "string",
+          "format": "date-time",
+          "description": "Zeitstempel der erfolgreichen Durchführung der Bezahlung."
+        },
+        "paymentMethod": {
+          "type": "string",
+          "enum": [
+            "GIROPAY",
+            "PAYDIRECT",
+            "CREDITCARD",
+            "PAYPAL",
+            "INVOICE",
+            "OTHER"
+          ],
+          "examples": [
+            "CREDITCARD"
+          ],
+          "description": "Die vom Benutzer ausgewählte Zahlart. Das Feld ist nur bei einer erfolgreichen Zahlung vorhanden / befüllt."
+        },
+        "paymentMethodDetail": {
+          "type": "string",
+          "minLength": 1,
+          "maxLength": 36,
+          "pattern": "^[\\w\\d-]+$",
+          "examples": [
+            "Visa"
+          ],
+          "description": "Weitere Erläuterung zur gewählten Zahlart."
+        },
+        "status": {
+          "type": "string",
+          "enum": [
+            "INITIAL",
+            "BOOKED",
+            "FAILED",
+            "CANCELED"
+          ],
+          "description": "- INITIAL - der Einreichung hat einen Payment-Request ausgelöst und eine Payment-Transaction wurde angelegt. Der Nutzer hat aber im Bezahldienst noch keine Wirkung erzeugt.\n- BOOKED - der Nutzer hat die Bezahlung im Bezahldienst autorisiert.\n- FAILED - der Vorgang wurde vom Bezahldienst aufgrund der Nutzereingaben abgebrochen.\n- CANCELED - der Nutzer hat die Bezahlung im Bezahldienst abgebrochen."
+        },
+        "grossAmount": {
+          "type": "number",
+          "minimum": 0.01,
+          "multipleOf": 0.01,
+          "description": "Bruttobetrag"
+        }
+      }
+    },
+    "replyChannel": {
+      "type": "object",
+      "minProperties": 1,
+      "maxProperties": 1,
+      "properties": {
+        "eMail": {
+          "type": "object",
+          "properties": {
+            "address": {
+              "type": "string",
+              "format": "email"
+            },
+            "pgpPublicKey": {
+              "type": "string",
+              "description": "Hilfe zur Erstellung gibt es in der Dokumentation unter https://docs.fitko.de/fit-connect/details/pgp-export",
+              "pattern": "^-----BEGIN PGP PUBLIC KEY BLOCK-----\\n\\n"
+            }
+          },
+          "required": [
+            "address"
+          ]
+        },
+        "deMail": {
+          "type": "object",
+          "description": "Akkreditierte Anbieter siehe https://www.bsi.bund.de/DE/Themen/Oeffentliche-Verwaltung/Moderner-Staat/De-Mail/Akkreditierte-DMDA/akkreditierte-dmda_node.html",
+          "properties": {
+            "address": {
+              "type": "string",
+              "format": "email"
+            }
+          },
+          "required": [
+            "address"
+          ]
+        },
+        "fink": {
+          "type": "object",
+          "description": "Postfachadresse in einem interoperablen Servicekonto (FINK.PFISK)",
+          "properties": {
+            "finkPostfachRef": {
+              "type": "string",
+              "description": "FINK Postfachadresse",
+              "examples": [
+                "hh/by/12345"
+              ],
+              "maxLength": 150,
+              "pattern": "^[-._a-z0-9~/]*$"
+            },
+            "host": {
+              "type": "string",
+              "description": "URL des Servicekontos, in dem das Ziel-Postfach liegt",
+              "format": "uri",
+              "examples": [
+                "https://servicekonto1.example.com/"
+              ]
+            }
+          },
+          "required": [
+            "finkPostfachRef"
+          ]
+        },
+        "elster": {
+          "type": "object",
+          "description": "Siehe https://www.elster.de/elsterweb/infoseite/elstertransfer_hilfe_schnittstellen",
+          "properties": {
+            "accountId": {
+              "type": "string",
+              "pattern": "^\\d{10}$"
+            },
+            "lieferTicket": {
+              "type": "string"
+            },
+            "geschaeftszeichen": {
+              "type": "string",
+              "maxLength": 10
+            }
+          },
+          "required": [
+            "accountId"
+          ]
+        }
+      }
+    },
+    "additionalReferenceInfo": {
+      "type": "object",
+      "description": "Eine Struktur, um zusätzliche Informationen zu hinterlegen",
+      "properties": {
+        "senderReference": {
+          "type": "string",
+          "description": "Eine Referenz zum Vorgang im sendenden System, um bei Problemen und Rückfragen außerhalb von FIT-Connect den Vorgang im dortigen System schneller zu identifizieren."
+        },
+        "applicationDate": {
+          "type": "string",
+          "format": "date",
+          "description": "Das Datum der Antragstellung. Das Datum muss nicht zwingend identisch mit dem Datum der Einreichung des Antrags über FIT-Connect sein."
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/InitializationTests/BaseClassConstructorTests.cs b/InitializationTests/BaseClassConstructorTests.cs
deleted file mode 100644
index 0c8379673e7a10913e7ac97e9fe3867410c0928a..0000000000000000000000000000000000000000
--- a/InitializationTests/BaseClassConstructorTests.cs
+++ /dev/null
@@ -1,56 +0,0 @@
-using System;
-using FitConnect;
-using FluentAssertions;
-using Microsoft.Extensions.Logging;
-using Moq;
-using NUnit.Framework;
-
-namespace InitializationTests;
-
-public class BaseClassConstructorTests {
-    private ILogger? _logger;
-
-    [SetUp]
-    public void Setup() {
-        _logger = Mock.Of<ILogger>();
-    }
-
-    [Test]
-    public void CreateCustomEndpoints() {
-        var dut = new Sender(_logger, new FitConnectEndpoints(
-            "http://localhost:5050/token",
-            "http://localhost:5050/submission",
-            "http://localhost:5050/routing"));
-
-        dut.Endpoints.RoutingApi.Should().Be("http://localhost:5050/routing");
-        dut.Endpoints.SubmissionApi.Should().Be("http://localhost:5050/submission");
-        dut.Endpoints.TokenUrl.Should().Be("http://localhost:5050/token");
-    }
-
-    [Test]
-    public void CreateDevEndpoints() {
-        var dut = new Sender(_logger,
-            FitConnectEndpoints.Create(FitConnectEndpoints.EndpointType.Development));
-
-        dut.Endpoints.TokenUrl.Should().Be("https://auth-testing.fit-connect.fitko.dev/token");
-        dut.Endpoints.SubmissionApi.Should()
-            .Be("https://submission-api-testing.fit-connect.fitko.dev");
-        dut.Endpoints.RoutingApi.Should().Be("https://routing-api-testing.fit-connect.fitko.dev");
-    }
-
-    [Test]
-    public void CreateTestingEndpoints() {
-        Assert.Throws<ArgumentException>(() => {
-            var sender = new Subscriber(_logger,
-                FitConnectEndpoints.Create(FitConnectEndpoints.EndpointType.Testing));
-        });
-    }
-
-    [Test]
-    public void CreateProductionEndpoints() {
-        Assert.Throws<ArgumentException>(() => {
-            var sender = new Sender(_logger,
-                FitConnectEndpoints.Create(FitConnectEndpoints.EndpointType.Production));
-        });
-    }
-}
diff --git a/InitializationTests/InitializationTests.csproj b/InitializationTests/InitializationTests.csproj
deleted file mode 100644
index 43b1dc07278ee1dd87ce10971772ba841c4ece36..0000000000000000000000000000000000000000
--- a/InitializationTests/InitializationTests.csproj
+++ /dev/null
@@ -1,23 +0,0 @@
-<Project Sdk="Microsoft.NET.Sdk">
-
-    <PropertyGroup>
-        <TargetFramework>net6.0</TargetFramework>
-        <Nullable>enable</Nullable>
-
-        <IsPackable>false</IsPackable>
-    </PropertyGroup>
-
-    <ItemGroup>
-        <PackageReference Include="FluentAssertions" Version="6.7.0" />
-        <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
-        <PackageReference Include="Moq" Version="4.18.1" />
-        <PackageReference Include="NUnit" Version="3.13.2" />
-        <PackageReference Include="NUnit3TestAdapter" Version="4.0.0" />
-        <PackageReference Include="coverlet.collector" Version="3.1.0" />
-    </ItemGroup>
-
-    <ItemGroup>
-      <ProjectReference Include="..\FitConnect\FitConnect.csproj" />
-    </ItemGroup>
-
-</Project>
diff --git a/readme.md b/readme.md
index a23bafc08735c4ee46fa94ac451cc456f207a1de..901c707ae22453f6b40f4c80d75c515cd9f48a1d 100644
--- a/readme.md
+++ b/readme.md
@@ -4,14 +4,25 @@
 
 **IN DEVELOPMENT NOT FOR PRODUCTION USE**
 
+For an implementation example take a look at the [DummyClient](DummyClient/Program.cs)
 
-## Links
+## Ignored Files
 
-- [Project management](https://wiki.fit-connect.fitko.dev/de/PM_PUBLIC/Projektvorgehensmodell)
-- [Wiki SDK Description](https://wiki.fit-connect.fitko.dev/de/PM_PUBLIC/Epics/SDK_Initialisierung)
-- [Containing GitLab](https://git.fitko.de/)
-- [Board filtered for SDK](https://git.fitko.de/fit-connect/planning/-/boards/44?label_name%5B%5D=component%3A%3ASDK)
-- [Documentation](https://docs.fitko.de/fit-connect/docs/getting-started/first-steps/)
+You need a secret file for e2e test like:
+
+```json
+{
+  "sender": {
+    "id": "00000000-0000-0000-0000-000000000000",
+    "secret": "0000000000000000000000000000000000000000000",
+    "scope": "send:region:DE"
+  }
+}
+```
+
+[glossary](https://docs.fitko.de/fit-connect/docs/glossary/)
 
 ### Tickets
- - [Method signatures](https://git.fitko.de/fit-connect/planning/-/issues/438)
\ No newline at end of file
+
+- [Method signatures](https://git.fitko.de/fit-connect/planning/-/issues/438)
+- [Java SDK](https://git.fitko.de/fit-connect/planning/-/issues/413)
\ No newline at end of file
diff --git a/working_notes.md b/working_notes.md
new file mode 100644
index 0000000000000000000000000000000000000000..517d433b53dbfa873b286a70452895f17e60a3eb
--- /dev/null
+++ b/working_notes.md
@@ -0,0 +1,31 @@
+# Notes
+
+# TODOS
+
+| interface | implemented | tested | scope              | description                                                                                                                                   |
+|:---------:|:-----------:|:------:|:-------------------|-----------------------------------------------------------------------------------------------------------------------------------------------|
+|     X     |      X      |   X    | Sender,Subscriber  | Abruf von OAuth-Tokens                                                                                                                        |
+|     X     |             |        | Sender             | Prüfung von öffentlichen Schlüsseln und Zertifikatsketten + OCSP-Check (vgl. [#119](https://git.fitko.de/fit-connect/planning/-/issues/119))  |
+|     X     |             |        | Sender             | Verschlüsselung von Fachdaten (JSON, XML) mittels JWE                                                                                         |
+|     X     |             |        | Sender             | Verschlüsselung von Anhängen (Binärdaten) mittels JWE                                                                                         |
+|     X     |             |        | Sender             | Korrekte Erzeugung eines Metadatensatzes inkl. [Hashwerte](https://docs.fitko.de/fit-connect/docs/sending/metadata#integrity)                 |
+|     X     |             |        | Subscriber         | Entschlüsselung von Fachdaten (JSON oder XML) mittels JWE                                                                                     |
+|     X     |             |        | Subscriber         | Entschlüsselung von Anhängen (Binärdaten) mittels JWE                                                                                         |
+|     X     |      X      |        | Subscriber         | Prüfung der empfangenen Metadaten gegen das zugehörige JSON-Schema                                                                            |
+|     X     |             |        | Subscriber         | [Prüfung der Hashwerte](https://docs.fitko.de/fit-connect/docs/receiving/verification#integrity) aus dem Metadatensatz.                       |
+|     X     |             |        | Subscriber         | SET-Erstellung inkl. Signaturerzeugung                                                                                                        |
+|     X     |             |        | Sender, Subscriber | SET-Empfang inkl. Signaturprüfung                                                                                                             |
+|     X     |             |        | Sender, Subscriber | Unterstüzung / Abstraktion der API-Nutzung (`fitconnect.sendSubmission(metadata, destinationID, ...)` o.ä.) für die oben genannten Use-Cases  |
+|     X     |             |        | Sender, Subscriber | Logging (Logging-Modul muss von außen kommen)                                                                                                 |
+
+## Links
+
+- [SDK-Konzept im Wiki](https://wiki.fit-connect.fitko.dev/de/Konzeption/Konzeption_SDK)
+- [inoffizielles Python-SDK](https://github.com/codedust/fitconnect-sdk-python)
+- [Project management](https://wiki.fit-connect.fitko.dev/de/PM_PUBLIC/Projektvorgehensmodell)
+- [Wiki SDK Description](https://wiki.fit-connect.fitko.dev/de/PM_PUBLIC/Epics/SDK_Initialisierung)
+- [Containing GitLab](https://git.fitko.de/)
+- [Board filtered for SDK](https://git.fitko.de/fit-connect/planning/-/boards/44?label_name%5B%5D=component%3A%3ASDK)
+- [Documentation](https://docs.fitko.de/fit-connect/docs/getting-started/first-steps/)
+- [Security Event Token Requirements](https://wiki.fit-connect.fitko.dev/de/Konzeption/Security_Event_Token_Future)
+- [glossary](https://docs.fitko.de/fit-connect/docs/glossary/)