diff --git a/.gitignore b/.gitignore
index 8a5e7f13989c72b4b86131b33e8fe02c662b85ce..906aa3ecd39ffb7d3355cf89e2870a3736f3245c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,7 +20,6 @@ private_notes/
 
 **.nupkg
 
-
 ### JetBrains template
 # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
 # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
diff --git a/BasicUnitTest/FluentSenderTests.cs b/BasicUnitTest/SenderTests.cs
similarity index 98%
rename from BasicUnitTest/FluentSenderTests.cs
rename to BasicUnitTest/SenderTests.cs
index 0951d3b8279130ae2069fe2e2fcee6c7a3ec1c16..e815e8ff29f1a2d31bf333c193767cc96b8cacbb 100644
--- a/BasicUnitTest/FluentSenderTests.cs
+++ b/BasicUnitTest/SenderTests.cs
@@ -9,7 +9,7 @@ using NUnit.Framework;
 
 namespace FluentApiTest;
 
-public class FluentSenderTests {
+public class SenderTests {
     private IContainer _container = null!;
     protected string clientId = null!;
     protected string clientSecret = null!;
diff --git a/BasicUnitTest/FluentSubscriberReceiveTests.cs b/BasicUnitTest/SubscriberReceiveTests.cs
similarity index 96%
rename from BasicUnitTest/FluentSubscriberReceiveTests.cs
rename to BasicUnitTest/SubscriberReceiveTests.cs
index 6ab27366f830c539631570796c1088c38bc33373..88473285446ee3b3e862d6e269483393efbe320d 100644
--- a/BasicUnitTest/FluentSubscriberReceiveTests.cs
+++ b/BasicUnitTest/SubscriberReceiveTests.cs
@@ -7,7 +7,7 @@ using NUnit.Framework;
 
 namespace FluentApiTest;
 
-public class FluentSubscriberReceiveTests {
+public class SubscriberReceiveTests {
     private readonly string clientId = "clientId";
     private readonly string clientSecret = "clientSecret";
     private IContainer _container = null!;
diff --git a/FitConnect/FitConnect.csproj b/FitConnect/FitConnect.csproj
index 3827c420f787bd35cf4c8de00b4f830dda6be88e..844e93c8ef9d3947bda983a32b309a2ff8708a63 100644
--- a/FitConnect/FitConnect.csproj
+++ b/FitConnect/FitConnect.csproj
@@ -14,6 +14,7 @@
         <PackageReference Include="Autofac" Version="6.4.0" />
         <PackageReference Include="IdentityModel" Version="6.0.0" />
         <PackageReference Include="jose-jwt" Version="4.0.0" />
+        <PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" />
         <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.1" />
         <PackageReference Include="Microsoft.IdentityModel.JsonWebTokens" Version="6.21.0" />
         <PackageReference Include="Microsoft.IdentityModel.Tokens" Version="6.21.0" />
diff --git a/FitConnect/Subscriber.cs b/FitConnect/Subscriber.cs
index fcdd076df1df9e11f0efb0ec942da75d99b0a073..c0c6a3ae301153d7f0dd4cdf6816f5da4129240f 100644
--- a/FitConnect/Subscriber.cs
+++ b/FitConnect/Subscriber.cs
@@ -1,10 +1,16 @@
+using System.Net;
 using System.Reflection;
+using System.Security.Cryptography;
+using System.Text;
 using Autofac;
+using Autofac.Core.Activators.Reflection;
 using FitConnect.Encryption;
 using FitConnect.Interfaces.Subscriber;
 using FitConnect.Models;
 using FitConnect.Models.v1.Api;
 using FitConnect.Services.Models.v1.Submission;
+using IdentityModel;
+using Microsoft.AspNetCore.Http;
 using Microsoft.Extensions.Logging;
 using Newtonsoft.Json;
 using NJsonSchema;
@@ -199,6 +205,38 @@ public class Subscriber : FitConnectClient,
         var result = CasesService.FinishSubmission(submission.CaseId, token);
         Logger?.LogInformation("Submission completed {status}", result);
     }
+
+    public static string VerifyCallback(string callbackSecret,
+        long timestamp, string body) {
+        if (timestamp < DateTime.Now.AddMinutes(-5).ToEpochTime())
+            throw new ArgumentException("Request is too old");
+
+        var hmac = new HMACSHA512(Encoding.UTF8.GetBytes(callbackSecret))
+            .ComputeHash(Encoding.UTF8.GetBytes($"{timestamp}.{body}"));
+
+
+        return Convert.ToHexString(hmac).ToLower();
+    }
+
+    public static bool VerifyCallback(string callbackSecret, HttpRequest request) {
+        if (!request.Headers.ContainsKey("callback-timestamp"))
+            throw new ArgumentException("Missing callback-timestamp header");
+
+        var timeStampString = request.Headers["callback-timestamp"].ToString();
+        if (!long.TryParse(timeStampString, out var timestamp)) {
+            throw new ArgumentException("Invalid callback-timestamp header");
+        }
+
+
+        var authentication = request.Headers["callback-authentication"];
+        using var requestStream = request.Body;
+        var content = new StreamReader(requestStream).ReadToEnd().Trim();
+
+        var result = VerifyCallback(callbackSecret, timestamp, content);
+        if (result != authentication)
+            throw new ArgumentException("Verified request does not match authentication");
+        return true;
+    }
 }
 
 public enum FinishSubmissionStatus {
diff --git a/IntegrationTests/CallbackTest.cs b/IntegrationTests/CallbackTest.cs
new file mode 100644
index 0000000000000000000000000000000000000000..827eaebb9ec9f45cf127bcda279751fc553c5e5c
--- /dev/null
+++ b/IntegrationTests/CallbackTest.cs
@@ -0,0 +1,100 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Net;
+using System.Net.Http;
+using System.Text;
+using Autofac;
+using FluentAssertions;
+using IdentityModel;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.Primitives;
+using MockContainer;
+using Moq;
+using NUnit.Framework;
+
+namespace IntegrationTests;
+
+[TestFixture]
+public class CallbackTest {
+    private HttpRequest _request = null!;
+    private string _callbackSecret = "";
+
+    [SetUp]
+    public void Setup() {
+        var memoryStream = new MemoryStream();
+        var streamWriter = new StreamWriter(memoryStream);
+
+        streamWriter.WriteLine(
+            "{\"type\":\"https://schema.fitko.de/fit-connect/submission-api/callbacks/new-submissions\",\"submissionIds\":[\"f39ab143-d91a-474a-b69f-b00f1a1873c2\"]}");
+        streamWriter.Flush();
+        memoryStream.Position = 0;
+
+        var headers = new HeaderDictionary(new Dictionary<string, StringValues>() {
+            { "callback-timestamp", "1672527599" }, {
+                "callback-authentication",
+                "798cd0edb70c08e5b32aa8a18cbbc8ff6b3078c51af6d011ff4e32e470c746234fc4314821fe5185264b029e962bd37de33f3b9fc5f1a93c40ce6672845e90df"
+            }
+        });
+
+
+        var mock =
+            new Mock<HttpRequest>();
+        mock.Setup(w => w.ContentType).Returns("application/json");
+        mock.Setup(w => w.Headers).Returns(headers);
+        mock.Setup(w => w.Method).Returns("POST");
+        mock.Setup(w => w.Body).Returns(memoryStream);
+
+        _request = mock.Object;
+
+        _callbackSecret = MockContainer.Container.Create().Resolve<MockSettings>().CallbackSecret;
+    }
+
+    [Test]
+    public void ValidRequest_WithSingeValues() {
+        // Arrange
+
+        //Act
+        var authentication = FitConnect.Subscriber.VerifyCallback(_callbackSecret, 1672527599,
+            "{\"type\":\"https://schema.fitko.de/fit-connect/submission-api/callbacks/new-submissions\",\"submissionIds\":[\"f39ab143-d91a-474a-b69f-b00f1a1873c2\"]}"
+        );
+
+        // Assert
+        authentication.Should()
+            .Be(
+                "798cd0edb70c08e5b32aa8a18cbbc8ff6b3078c51af6d011ff4e32e470c746234fc4314821fe5185264b029e962bd37de33f3b9fc5f1a93c40ce6672845e90df");
+    }
+
+    [Test]
+    public void ValidRequest() {
+        // Assert
+        FitConnect.Subscriber.VerifyCallback(_callbackSecret, _request).Should().Be(true);
+    }
+
+    [Test]
+    public void RequestAge_Fails() {
+        // Arrange
+        _request.Headers["callback-timestamp"] = "1641066653";
+
+        // Atc
+        // Assert
+        Assert.Throws<ArgumentException>(() => {
+                FitConnect.Subscriber.VerifyCallback(_callbackSecret, _request);
+            })
+            .Message.Should().Be("Request is too old");
+    }
+
+    [Test]
+    public void RequestAuthentication_Fails() {
+        // Arrange
+        _request.Headers["callback-authentication"] =
+            "898cd0edb70c08e5b32aa8a18cbbc8ff6b3078c51af6d011ff4e32e470c746234fc4314821fe5185264b029e962bd37de33f3b9fc5f1a93c40ce6672845e90df";
+
+        // Atc
+        // Assert
+        Assert.Throws<ArgumentException>(() => {
+                FitConnect.Subscriber.VerifyCallback(_callbackSecret, _request);
+            })
+            .Message.Should().Be("Request is not authentic");
+    }
+}
diff --git a/IntegrationTests/IntegrationTests.csproj b/IntegrationTests/IntegrationTests.csproj
index d95a0c10813bbec26c5f71ac327cc1d9ab2f2030..436a6021978121275852cebc0475778fb12d8e4b 100644
--- a/IntegrationTests/IntegrationTests.csproj
+++ b/IntegrationTests/IntegrationTests.csproj
@@ -10,6 +10,8 @@
     <ItemGroup>
         <PackageReference Include="DotNet.Testcontainers" Version="1.6.0" />
         <PackageReference Include="FluentAssertions" Version="6.7.0" />
+        <PackageReference Include="Microsoft.AspNetCore.Http" Version="2.2.2" />
+        <PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" />
         <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="6.0.0" />
         <PackageReference Include="Microsoft.IdentityModel.JsonWebTokens" Version="6.21.0" />
         <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
diff --git a/MockContainer/MockContainer.cs b/MockContainer/MockContainer.cs
index 2bfa17bde88b8a27fb6ef0f67c70d0a278edcc30..5fd91d97126af1503d3d4699f2c2881d80b5342d 100644
--- a/MockContainer/MockContainer.cs
+++ b/MockContainer/MockContainer.cs
@@ -22,7 +22,7 @@ namespace MockContainer;
 public record MockSettings(string PrivateKeyDecryption, string PrivateKeySigning,
     string PublicKeyEncryption, string PublicKeySignatureVerification, string SenderClientId,
     string SenderClientSecret, string SubscriberClientId, string SubscriberClientSecret,
-    string DestinationId, string LeikaKey);
+    string DestinationId, string LeikaKey, string CallbackSecret);
 
 public class TestFile {
     public byte[] Content;
@@ -80,13 +80,14 @@ public static class Container {
         var subscriberClientSecret = (string)credentials.subscriber.clientSecret;
         var destinationId = (string)credentials.destinationId;
         var leikaKey = (string)credentials.leikaKey;
+        var callbackSecret = (string)credentials.callbackSecret;
 
         builder.Register(c => new MockSettings(
                 privateKeyDecryption, privateKeySigning,
                 publicKeyEncryption, publicKeySignature,
                 senderClientId, senderClientSecret,
                 subscriberClientId, subscriberClientSecret,
-                destinationId, leikaKey))
+                destinationId, leikaKey, callbackSecret))
             .As<MockSettings>();
         builder.Register(c => new KeySet {
             PrivateKeyDecryption = privateKeyDecryption,