diff --git a/README.md b/README.md
index 1a39d053be8d8a5093f7e8b28f93e995f5aba772..a08a5ccfcc5c9ce42d415ab99e8e9882d0bec457 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,248 @@
-# XTA Client Bibliothek
+# XTA-Client
+
+Ein Client zum Senden und Empfangen von XTA Nachrichten.
+
+
+
+Der Client verwendet *XTA 2 Version 3.1* mit [XTA-Modul-Webservice-Version](https://www.xoev.de/osci-xta/standard-xta-2/xta-versionsuebersicht-23036) `2.1.1`.
+Er wird als Maven-Artefakt `xta-client-lib` bereitgestellt und kann in Java-Anwendungen eingebunden werden.
+
+## Senden einer Nachricht
+Zum Senden einer Nachricht konfiguriert die Nutzer*in einen neuen XTA-Client mit einem Client-Zertifikat, welches sie für das Senden mit einer Autor-Kennung autorisiert.
+
+Die Nutzer*in erstellt die zu sendende Nachricht mit entsprechender Autor- und Leser-Kennung. 
+Anschließend übergibt sie die Nachricht an den XTA-Server mit einem Aufruf von `XtaClient::sendMessage`.
+Wenn der zurückgegebene Transport-Report den Status `OPEN` meldet, steht die Nachricht dem Leser zur Abholung bereit.
+```mermaid
+%% Senden einer Nachricht
+  sequenceDiagram
+    participant A as Nutzer*in
+    participant B as XTA-Client
+    participant C as XTA-Server
+    Note left of A: (1) XTA-Client erzeugen
+    activate A
+    Note left of A: (2) Nachricht erzeugen
+    Note left of A: (3) Nachricht senden
+    A->>B: sendMessage
+    activate B
+    B->>C: checkAccountActive
+    activate C
+    C-->>B: 
+    deactivate C
+    B->>C: lookupService
+    activate C
+    C-->>B:  
+    deactivate C
+    B->>C: createMessageID
+    activate C
+    C-->>B: 
+    deactivate C
+    B->>C: sendMessage
+    activate C
+    C-->>B: 
+    deactivate C
+    B->>C: getTransportReport
+    activate C
+    C-->>B: 
+    deactivate C
+    B-->>A: 
+    deactivate B
+    Note left of A: (4) Nachrichtenstatus prüfen
+    deactivate A
+```
+
+<small>* Der XTA-Server wird oft als Nachrichtenbroker oder Nachrichtenvermittler bezeichnet.</small>
+
+**Beispielcode:**
+
+```java
+// (1) XTA-Client erzeugen
+var client = XtaClient.from(config);
+// (2) Nachricht erzeugen
+var zipFileName = "d5be7468-e620-4126-a40e-61a7f9b46345_Geschaeftsgang.Geschaeftsgang.0201.zip";
+var zipFileContentDataHandler = new DataHandler(new FileDataSource("/path/to/" + zipFileName));
+var xdomeaXtaFile = XtaFile.builder()
+        .name(zipFileName)
+        .content(zipFileContentDataHandler)
+        .contentType("application/zip")
+        .build();
+
+var message = XtaMessage.builder()
+        .metaData(XtaMessageMetaData.builder()
+                .service("urn:xoev-de:xdomea:schema:2.4.0/xdomea240Antrag.wsdl")
+                .businessScenarioCode("XDOMEAGAD_DATA")
+                .businessScenarioListUri("urn:de:dataport:codeliste:business.scenario")
+                .businessScenarioListVersionId("1.0")
+                .messageTypeCode("Geschaeftsgang.Geschaeftsgang.0201")
+                .messageTypePayloadSchema("urn:xoev-de:xdomea:schema:2.4.0")
+                .authorIdentifier(XtaIdentifier.builder()
+                        .category("Generischer Antragsdienst")
+                        .value("gad:010200100000")
+                        .build())
+                .readerIdentifier(XtaIdentifier.builder()
+                        .category("Generischer Antragsempfänger")
+                        .value("gae:test-environment@ozg-cloud.de")
+                        .build())
+                .build())
+        .messageFile(xdomeaXtaFile)
+        .attachmentFiles(emptyList())
+        .build();
+// (3) Nachricht senden
+var transportReport = client.sendMessage(message);
+// (4) Nachrichtenstatus prüfen
+assert transportReport.status() == XtaMessageStatus.OPEN;
+```
+
+Da eine Xdomea-Nachricht die Leser- und Autor-Kennung bereits enthält, ist es möglich aus der Xdomea-ZIP-Datei die Metadaten der XTA-Nachricht abzuleiten:
+
+```java
+// ...
+// (2) Nachricht erzeugen
+// ...
+var message = XdomeaXtaMessageCreator.createInstance().createMessage(xdomeaXtaFile);
+// (3) Nachricht senden
+var transportReport = client.sendMessage(message);
+// ...
+```
+
+Hierbei wird die Xta-Autor-Kennung aus dem *Xdomea-Absender-Kennung/Behoerdenschluessel* gelesen und die Xta-Leser-Kennung aus dem *Xdomea-Empfaenger-Kennung/Behoerdenschluessel*.
+
+### Validierung der Xdomea-ZIP-Datei
+Wenn eine `XtaMessage` für eine Xdomea-ZIP-Datei mit `XdomeaXtaMessageCreator::createMessage` erstellt wird, wird zudem geprüft, ob die Nachricht die ["Transportfestlegungen Generischer Antragsdienst"](doku/Transportfestlegungen%20Generischer%20Antragsdienst.pdf) einhält.
+
+Für eine erfolgreiche Validierung muss eine Xdomea-ZIP-Datei folgende Bedingungen erfüllen:
+- Der ZIP-Dateiname ist `<ProzessID>_<Nachrichtentyp>.zip` (z.B. `00000000-0000-0000-0000-_Geschaeftsgang.Geschaeftsgang.0201.zip`)
+    - Die ProzessID in der Xdomea-Nachricht entspricht der ProzessID im Dateinamen
+- Die Xdomea-Nachricht `<ProzessID>_<Nachrichtentyp>.xml` in der ZIP-Datei ist schema-konform.
+- Der Xdomea-Nachrichten-Typ ist zulässig:
+    - `Geschaeftsgang.Geschaeftsgang.0201` mit Xdomea 2.4.0
+    - `Abgabe.Abgabe.0401` mit Xdomea 3.0.0
+    - `Abgabe.ImportBestaetigen.0402` mit Xdomea 3.0.0
+- Alle Dateien, die die Xdomea-Nachricht referenziert, sind in der ZIP-Datei enthalten. 
+- Eine Absender-Kennung ist vorhanden mit dem Präfix `gad`
+- Eine Empfänger-Kennung ist vorhanden mit dem Präfix `gae`
+
+<small>Hinweis: Die Xdomea-Nachricht sollte mit UTF-8 kodiert sein.</small>
+
+## Empfangen von Nachrichten
+Zum Empfangen von Nachrichten konfiguriert die Nutzer*in einen neuen XTA-Client mit den gewünschten Leser-Kennungen.
+Zudem konfiguriert er das Client-Zertifikat, welches ihn zum Lesen mit den Leser-Kennungen autorisiert.
+
+Beim Aufruf von `fetchMessages` werden alle Nachrichten für die Leser-Kennungen abgeholt und verarbeitet.
+Die Nachrichten-Verarbeitung erfolgt durch die übergebene `processMessage`-Funktion.
+
+Nachdem alle Nachrichten verarbeitet sind, werden die Transport-Reports zurückgegeben.
+
+Eine erfolgreich abgeholte/geschlossene Nachricht hat den Status `RED`, `YELLOW` oder `GREEN`.
+Hierbei signalisiert `RED` einen kritischen Fehler, `YELLOW` einen Warnhinweis und `GREEN` eine fehlerfreie Verarbeitung.
+
+```mermaid
+%% Empfangen von Nachrichten
+  sequenceDiagram
+    participant A as Nutzer*in
+    participant B as XTA-Client
+    participant C as XTA-Server
+    Note left of A: (1) XTA-Client erzeugen
+    activate A
+    Note left of A: (2) Nachrichten abholen
+    A->>B: fetchMessages
+    
+    activate B
+    loop Für jede Leser-Kennung
+        B->>C: checkAccountActive 
+        activate C
+        C-->>B: 
+        deactivate C
+        B->>C: getStatusList
+        activate C
+        C-->>B: 
+        deactivate C
+        loop Für jede ungelesene Nachricht
+            B->>C: getMessage
+            activate C
+            Note left of B: Nachricht abholen
+            C-->>B: 
+            deactivate C
+            B->>A: processMessage
+            Note left of A: (3) Nachricht verarbeiten
+            A-->>B: 
+            B->>C: close
+            activate C
+            Note left of B: Nachricht schließen
+            C-->>B: 
+            deactivate C
+            B->>C: getTransportReport
+            activate C
+            C-->>B: 
+            deactivate C
+        end
+	end
+    B-->>A: 
+    deactivate B
+    Note left of A: (4) Nachrichtenstatus prüfen
+    deactivate A
+```
+<small>* Sollte `processMessage` bei der Verarbeitung eine *RuntimeException* werfen, wird `Nachricht schließen` übersprungen.</small>
+
+<small>Hinweis: Nicht geschlossene Nachrichten mit Status `OPEN` werden beim nächsten Aufruf von `fetchMessages` erneut bearbeitet.</small>
+
+**Beispielcode:**
+
+```java
+// (1) XTA-Client erzeugen
+var client = XtaClient.from(config);
+// (2) Nachrichten abholen
+var transportReports = client.fetchMessages(xtaMessage -> {
+    // (3) Nachricht verarbeiten
+});
+// (4) Nachrichtenstatus prüfen
+for (var transportReport : transportReports) {
+    assert transportReport.status() == XtaMessageStatus.GREEN;
+}
+```
+
+## Konfiguration
+
+Der XTA-Client wird mit einer `XtaClientConfig` konfiguriert:
+- XTA-Service-Port-URLs: `management`, `send` und `msgBox `
+- Client-Zertifikat der Autor-Kennung (für `sendMessage`) und der Leser-Kennungen (für `fetchMessages`)
+  - Leser-Client-Kennungen für `fetchMessages`.
+- ... siehe [XtaClientConfig](src/main/java/de/ozgcloud/xta/client/config/XtaClientConfig.java)
+
+**Beispielcode:**
+```java
+var config = XtaClientConfig.builder()
+        .managementServiceUrl("https://my-xta-server.de/MB_XTA-WS/XTA210managementPort.svc")
+        .sendServiceUrl("https://my-xta-server.de/MB_XTA-WS/XTA210sendPort.svc")
+        .msgBoxServiceUrl("https://my-xta-server.de/MB_XTA-WS/XTA210msgBoxPort.svc")
+        .clientCertKeystore(XtaClientConfig.KeyStore.builder()
+                .content(Files.toByteArray(new File("/path/to/client-cert.p12")))
+                .type("PKCS12")
+                .password("keystore-password")
+                .bulid())
+        .clientIdentifiers(List.of(
+                XtaIdentifier.builder()
+                        .category("Generischer Antragsempfänger")
+                        .value("gae:test-environment@ozg-cloud.de")
+                        .build(),
+                XtaIdentifier.builder()
+                        .category("Generischer Antragsempfänger")
+                        .value("gae:dev-environment@ozg-cloud.de")
+                        .build()
+        ))
+        .build();
+var client = XtaClient.from(config);
+```
+
+<small>Hinweis: Sollte die Root-CA des XTA-Servers nicht für das Ziel-System konfiguriert sein, muss zudem ein entsprechender `XtaClientConfig::trustStore` konfiguriert werden.</small> 
+
+### Filterung von Nachrichten vor der Abholung
+Um Nachrichten vor dem Abholen basierend auf `XtaMessageMetadata` zu filtern, sollte das optionale `Predicate<XtaMessageMetadata>` für `XtaClientConfig::isMessageSupported` konfiguriert werden. 
+Zum Beispiel kann auf diese Weise verhindert werden, dass nicht unterstützte Nachrichten, die unausweichlich zu einem Verarbeitungsfehler führen, vollständig heruntergeladen werden müssen. 
+
+
+## Referenzen
+- Dieser XTA-Client basiert auf dem [XTA-Client-Beispielcode für XTA 2 Version 3 vom 21.07.2021](https://www.xoev.de/sixcms/media.php/13/XTA_Client_Version_3_20210721.zip) auffindbar unter [Hilfsmittel](https://www.xoev.de/xta/hilfsmittel).
+- Die [XTA 2 Version 3.1 Spezifikation](https://www.xoev.de/sixcms/media.php/13/XTA_2_Version_3.1_Spezifikation_30112021.pdf) ist auffindbar unter [XTA 2 Version 3.1](https://www.xoev.de/xta/v3).
 
-Mit dieser Bibliothek soll anhand des Kosit Beispielprojektes eine einfache Anbindung an die XTA API ermöglicht werden.  
 
-das ist ein toller gitea push mirror test
\ No newline at end of file
diff --git a/doku/Transportfestlegungen Generischer Antragsdienst.pdf b/doku/Transportfestlegungen Generischer Antragsdienst.pdf
new file mode 100755
index 0000000000000000000000000000000000000000..3d0d632d76ab26beb10d662b86bec919a53d9603
Binary files /dev/null and b/doku/Transportfestlegungen Generischer Antragsdienst.pdf differ
diff --git a/pom.xml b/pom.xml
index a10e6b554ecaedaa58f9d6056c279432c30eee7a..aec12254cb40e53e45ac49a5a0bd4700211c79d8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -154,7 +154,6 @@
 						<id>log4j2-plugin-processor</id>
 						<goals>
 							<goal>compile</goal>
-							<goal>testCompile</goal>
 						</goals>
 						<phase>process-classes</phase>
 						<configuration>
diff --git a/src/main/java/de/ozgcloud/xta/client/XtaClient.java b/src/main/java/de/ozgcloud/xta/client/XtaClient.java
index 8d5d8b47a2af6bc8968e555b855185015b06d1e7..0ec945961695d4b0707093aa3d7556de9cf65ee7 100644
--- a/src/main/java/de/ozgcloud/xta/client/XtaClient.java
+++ b/src/main/java/de/ozgcloud/xta/client/XtaClient.java
@@ -13,9 +13,9 @@ import jakarta.validation.constraints.NotNull;
 import de.ozgcloud.xta.client.config.XtaClientConfig;
 import de.ozgcloud.xta.client.core.XtaClientService;
 import de.ozgcloud.xta.client.core.XtaExceptionHandler;
-import de.ozgcloud.xta.client.exception.XtaClientRuntimeException;
 import de.ozgcloud.xta.client.exception.XtaClientException;
 import de.ozgcloud.xta.client.exception.XtaClientInitializationException;
+import de.ozgcloud.xta.client.exception.XtaClientRuntimeException;
 import de.ozgcloud.xta.client.model.XtaIdentifier;
 import de.ozgcloud.xta.client.model.XtaMessage;
 import de.ozgcloud.xta.client.model.XtaMessageMetaData;
@@ -27,6 +27,22 @@ import lombok.Builder;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.log4j.Log4j2;
 
+/**
+ * A client for sending and receiving messages via the XTA 2 protocol (version 3).
+ *
+ * <p>
+ * The client may be initialized with an {@link XtaClientConfig} configuration by {@link #from(XtaClientConfig)}.
+ * </p>
+ *
+ * Example:
+ * <pre>
+ * var client = XtaClient.from(config);
+ * var transportReport = client.sendMessage(message);
+ * var transportReports = client.fetchMessages(message -> {
+ *   // process message
+ * });
+ * </pre>
+ */
 @RequiredArgsConstructor(access = AccessLevel.MODULE)
 @Builder(access = AccessLevel.MODULE)
 @Log4j2
@@ -38,10 +54,41 @@ public class XtaClient {
 
 	static final String NO_MESSAGE_CLOSED_WARNING = "No message has been closed although more are pending. Try increasing max list items.";
 
+	/**
+	 * Initialize a new {@link XtaClient} instance based on the given configuration.
+	 *
+	 * @param config The configuration for the client.
+	 * @return The initialized client.
+	 * @throws XtaClientInitializationException If the configuration is invalid or a configured keystore failed to initialize.
+	 */
 	public static XtaClient from(XtaClientConfig config) throws XtaClientInitializationException {
 		return XtaClientFactory.from(config).create();
 	}
 
+	/**
+	 * Fetches messages for all client identifiers.
+	 *
+	 * <p>
+	 * For each configured client identifier in {@link XtaClientConfig#getClientIdentifiers() clientIdentifiers}, checks if the client identifier is
+	 * an active account, then lists its pending/unread messages. Next, uses the {@link XtaClientConfig#getIsMessageSupported() isMessageSupported}
+	 * predicate to decide whether to fetch a listed message. Note that if no predicate is configured, all listed messages are fetched.
+	 * </p>
+	 * <p>
+	 * For each fetched message, calls the given {@code processMessage}. If {@code processMessage} does not throw a runtime exception, closes the
+	 * message, i.e., marks it as read. Then, fetches the transport report for the successfully or unsuccessfully processed message. Note that a
+	 * transport is always returned for each processed message, unless a technical problem prevents fetching the transport report.
+	 * </p>
+	 * <p>
+	 * A listing contains a maximum of {@link XtaClientConfig#getMaxListItems() maxListItems} messages. However, listing is repeated, as long as there
+	 * are more messages pending and some message is closed successfully during the latest listing.
+	 * </p>
+	 *
+	 * @param processMessage The consumer to process each fetched message.
+	 * @return The transport reports for all fetched/processed messages. A message which has not been closed has an {@link XtaMessageStatus#OPEN OPEN}
+	 * status. If a message has been closed, the status is either {@link XtaMessageStatus#GREEN GREEN}, {@link XtaMessageStatus#YELLOW YELLOW} or
+	 * {@link XtaMessageStatus#RED RED}.
+	 * @throws XtaClientException If a technical problem occurs while fetching messages.
+	 */
 	public List<XtaTransportReport> fetchMessages(@NotNull Consumer<XtaMessage> processMessage) throws XtaClientException {
 		try {
 			return fetchMessagesRaw(processMessage);
@@ -141,15 +188,37 @@ public class XtaClient {
 		log.error("Processing of message '%s' failed! Not closing message.".formatted(messageId), exception);
 	}
 
-	public XtaTransportReport sendMessage(@Valid XtaMessage message) throws XtaClientException {
+	/**
+	 * Sends the given message.
+	 *
+	 * <p>
+	 * Sends the message to the XTA server such that it may be asynchronously fetched by the reader. Author and reader of the message are given by the
+	 * message metadata.
+	 * </p>
+	 * <p>
+	 * First, checks whether the author refers to an active account. Then, checks that the service used by the message is available for the given
+	 * reader. If both checks pass, sends the message to the reader. Finally, returns the transport report for the sent message.
+	 * </p>
+	 * <p>
+	 * <b>Note:</b> message size and id are set by the server, and thus may initially be null. This also applies to the size of message and attachment
+	 * files.
+	 * </p>
+	 *
+	 * @param messageWithoutMessageId The XTA message to send without id and size.
+	 * @return The transport report for the sent message. As long as no critical error occurred, indicated by status {@link XtaMessageStatus#RED RED},
+	 * the message the status is {@link XtaMessageStatus#OPEN OPEN}, until the reader closes the message. Moreover, the report contains the message
+	 * metadata, including id and size values set by the server.
+	 * @throws XtaClientException If a check fails or a technical problem occurs while sending the message.
+	 */
+	public XtaTransportReport sendMessage(@NotNull @Valid XtaMessage messageWithoutMessageId) throws XtaClientException {
 		try {
-			return sendMessageRaw(message);
+			return sendMessageRaw(messageWithoutMessageId);
 		} catch (RuntimeException exception) {
 			throw exceptionHandler.deriveXtaClientException(exception);
 		}
 	}
 
-	XtaTransportReport sendMessageRaw(@Valid XtaMessage messageWithoutMessageId) {
+	XtaTransportReport sendMessageRaw(XtaMessage messageWithoutMessageId) {
 		var metaData = messageWithoutMessageId.metaData();
 		throwExceptionIfAccountInactive(metaData.authorIdentifier());
 		throwExceptionIfServiceNotAvailable(metaData);
diff --git a/src/main/java/de/ozgcloud/xta/client/config/XtaClientConfig.java b/src/main/java/de/ozgcloud/xta/client/config/XtaClientConfig.java
index 14bdf0499aa8265eb430f31a09c266200a26e64e..b51cb0007e2c641cbb1be57e9f9d0cf8c001a865 100644
--- a/src/main/java/de/ozgcloud/xta/client/config/XtaClientConfig.java
+++ b/src/main/java/de/ozgcloud/xta/client/config/XtaClientConfig.java
@@ -17,53 +17,140 @@ import lombok.Getter;
 import lombok.RequiredArgsConstructor;
 import lombok.ToString;
 
+/**
+ * Configuration of a {@link de.ozgcloud.xta.client.XtaClient}.
+ */
 @RequiredArgsConstructor
 @Getter
 @Builder
 @ToString
 public class XtaClientConfig {
 
+	/**
+	 * The reader client identifiers which are used to fetch messages.
+	 *
+	 * <p>
+	 * Usually, in order to use the client identifiers, an according client certificate needs to be configured.
+	 * </p>
+	 * <p>
+	 *     <b>Note:</b> The identifier type is assumed to be {@code xoev}.
+	 * </p>
+	 */
 	@Builder.Default
 	private final List<@Valid XtaIdentifier> clientIdentifiers = emptyList();
 
+	/**
+	 * This predicate may be used to filter listed messages before they are fetched. If null, all listed messages are fetched.
+	 *
+	 * <p>
+	 * Note that, usually, all messages for a client identifier should be read, i.e., fetched and processed. However, it may be useful to filter
+	 * messages before fetching them. For instance, to avoid downloading messages which would inevitably lead to a runtime exception during
+	 * processing.
+	 * </p>
+	 */
 	@Builder.Default
 	private final Predicate<XtaMessageMetaData> isMessageSupported = null;
 
+	/**
+	 * The URL of the management service.
+	 *
+	 * For instance: {@code https://my-xta-server.de/MB_XTA-WS/XTA210managementPort.svc}
+	 */
 	@NotBlank
 	private final String managementServiceUrl;
+	/**
+	 * The URL of the send service.
+	 *
+	 * For instance: {@code https://my-xta-server.de/MB_XTA-WS/XTA210sendPort.svc}
+	 */
 	@NotBlank
 	private final String sendServiceUrl;
+	/**
+	 * The URL of the message box service.
+	 *
+	 * For instance: {@code https://my-xta-server.de/MB_XTA-WS/XTA210msgBoxPort.svc}
+	 */
 	@NotBlank
 	private final String msgBoxServiceUrl;
 
+	/**
+	 * The number of message metadata items to request at a time. The default value is 50.
+	 *
+	 * <p>
+	 * Note that reducing this limit may result in more listing calls. Furthermore, listing all messages may not be possible if the number of
+	 * unprocessed messages reaches this limit, see {@linkplain de.ozgcloud.xta.client.XtaClient#fetchMessages fetchMessages}.
+	 * </p>
+	 */
 	@Positive
 	@Builder.Default
 	private final int maxListItems = 50;
 
+	/**
+	 * The keystore used to authenticate this client to the server.
+	 *
+	 * <p>
+	 * The keystore should contain a private key and a certificate chain which the server trusts.
+	 * </p>
+	 */
 	@Valid
 	@Builder.Default
 	private final KeyStore clientCertKeystore = null;
 
+	/**
+	 * The truststore to authenticate the server to the client.
+	 *
+	 * <p>
+	 * The truststore should contain a root certificate or a certificate chain of the server. May be null if the server certificate is trusted by the
+	 * JVM.
+	 * </p>
+	 */
 	@Valid
 	@Builder.Default
 	private final KeyStore trustStore = null;
 
+	/**
+	 * Whether to validate the XTA SOAP schema of the messages. Default is true.
+	 *
+	 * <p>
+	 * This option is intended for testing purposes and turning it off is not recommended.
+	 * </p>
+	 */
 	@Builder.Default
 	private final boolean schemaValidation = true;
+
+	/**
+	 * Whether to log SOAP requests. Default is false.
+	 */
 	@Builder.Default
 	private final boolean logSoapRequests = false;
+
+	/**
+	 * Whether to log SOAP responses. Default is false.
+	 */
 	@Builder.Default
 	private final boolean logSoapResponses = false;
 
+	/**
+	 * Configuration for a keystore. Either for a client certificate or a trust store.
+	 */
 	@RequiredArgsConstructor
 	@Getter
 	@Builder
 	@ToString
 	public static class KeyStore {
+		/**
+		 * File content of the keystore file.
+		 */
 		@NotNull
 		private final byte[] content;
+		/**
+		 * The type of the keystore. For instance, "PKCS12" or "JKS".
+		 */
 		@NotBlank
 		private final String type;
+		/**
+		 * The password of the keystore.
+		 */
 		@NotNull
 		private final char[] password;
 	}
diff --git a/src/main/java/de/ozgcloud/xta/client/model/XtaFile.java b/src/main/java/de/ozgcloud/xta/client/model/XtaFile.java
index 2561f45d22fcc92d3d4e729c78a40d741d470bc3..1617c7437c983d63d92bfe4abcffe90777af430a 100644
--- a/src/main/java/de/ozgcloud/xta/client/model/XtaFile.java
+++ b/src/main/java/de/ozgcloud/xta/client/model/XtaFile.java
@@ -10,6 +10,31 @@ import jakarta.validation.constraints.PositiveOrZero;
 
 import lombok.Builder;
 
+/**
+ * Represents a file in the XTA context.
+ *
+ * <p>
+ * <small>Parameter documentation strings translated from <i>XTA-Webservice-Datentypen.xsd</i>.</small>
+ * </p>
+ *
+ * @param content            A data handler of the file content. <p>This field is required.</p>
+ * @param contentType        This attribute specifies the MIME type of the contained content, so it includes entries like {@code text/xml},
+ *                           {@code text/plain}, {@code application/gzip}, or {@code application/pdf}. <p>This field is required as it is particularly
+ *                           important information (handled analogously in email).</p>
+ * @param contentDescription Description of the content, e.g., 'Offer' or 'Invoice'. <p>This field is optional.</p>
+ * @param encoding           Character set that was used for encoding the content. <p>This field is optional.</p>
+ * @param name               Filename of the data source, if the content was taken from a file. E.g.: For the transmission of xdomea messages,
+ *                           this attribute is mandatory. <p>This field is recommended as it is required for xdomea.</p>
+ * @param id                 Provides the ability to reference the content via, for example, a running number. <p>This field is optional and will be
+ *                           automatically set by the XTA server.</p>
+ * @param language           Language of the file content, for instance, {@code en-US} or {@code de-DE}, see <a
+ *                           href="http://www.ietf.org/rfc/rfc3066.txt">RFC 3066</a>. <p>This field is optional.</p>
+ * @param size               Size of the file content in bytes.
+ *
+ *                           <p>
+ *                           This field is optional and will be automatically set by the XTA server.
+ *                           </p>
+ */
 @Builder(toBuilder = true)
 public record XtaFile(
 		@NotNull DataHandler content,
@@ -19,6 +44,6 @@ public record XtaFile(
 		@NotBlank String name,
 		@Nullable String id,
 		@Nullable String language,
-		@PositiveOrZero BigInteger size
+		@Nullable @PositiveOrZero BigInteger size
 ) {
 }
diff --git a/src/main/java/de/ozgcloud/xta/client/model/XtaIdentifier.java b/src/main/java/de/ozgcloud/xta/client/model/XtaIdentifier.java
index 8ea86a7eeeaea8640df9f3a9a3fc623d6e98ffd9..30c50fda1f2c1e7232a4f62eb7a59ecb602c0753 100644
--- a/src/main/java/de/ozgcloud/xta/client/model/XtaIdentifier.java
+++ b/src/main/java/de/ozgcloud/xta/client/model/XtaIdentifier.java
@@ -5,6 +5,27 @@ import jakarta.validation.constraints.NotBlank;
 
 import lombok.Builder;
 
+/**
+ * An XTA party identifier which identifies XTA (reader/author) clients or (sender/receiver) server.
+ *
+ * <p>
+ * This client library only uses client identifiers and assumes an identifier type of {@code xoev}. The client certificate authorizes the use of an
+ * identifier value as reader/author. Note that name and category may be freely chosen and serve as documentation of the actual value.
+ * </p>
+ *
+ * Example:
+ * <pre>
+ * var clientIdentifier = XtaIdentifier.builder()
+ *  .value("gae:dev-environment@ozg-cloud.de")
+ *  .category("Generischer Antragsempfänger")
+ *  .name("OZG-Cloud Dev")
+ *  .build();
+ * </pre>
+ *
+ * @param name     Name of the identifier. <p>This field is optional.</p>
+ * @param category Category of the identifier. <p>This field is optional.</p>
+ * @param value    Value of the identifier. <p>This field is required.</p>
+ */
 @Builder
 public record XtaIdentifier(
 		@Nullable String name,
diff --git a/src/main/java/de/ozgcloud/xta/client/model/XtaMessage.java b/src/main/java/de/ozgcloud/xta/client/model/XtaMessage.java
index 10cf16eb90b271057680c386fde04af0956da777..bf636f23d196799bfcabcf14547db5a731e59616 100644
--- a/src/main/java/de/ozgcloud/xta/client/model/XtaMessage.java
+++ b/src/main/java/de/ozgcloud/xta/client/model/XtaMessage.java
@@ -7,6 +7,13 @@ import jakarta.validation.constraints.NotNull;
 
 import lombok.Builder;
 
+/**
+ * An XTA message consisting of metadata, a message file and optional attachment files.
+ *
+ * @param metaData Metadata of the message <p>This field is required.</p>
+ * @param messageFile Main message of the message <p>This field is required.</p>
+ * @param attachmentFiles Attachment files of the message <p>Note that this list should always be empty for xdomea messages.</p>
+ */
 @Builder(toBuilder = true)
 public record XtaMessage(
 		@NotNull @Valid XtaMessageMetaData metaData,
diff --git a/src/main/java/de/ozgcloud/xta/client/model/XtaMessageAndTransportReport.java b/src/main/java/de/ozgcloud/xta/client/model/XtaMessageAndTransportReport.java
deleted file mode 100644
index 6fed361806962dbb1f57c2a747ce65839cd79d4d..0000000000000000000000000000000000000000
--- a/src/main/java/de/ozgcloud/xta/client/model/XtaMessageAndTransportReport.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package de.ozgcloud.xta.client.model;
-
-import jakarta.validation.Valid;
-import jakarta.validation.constraints.NotNull;
-
-import lombok.Builder;
-
-@Builder
-public record XtaMessageAndTransportReport(
-		@NotNull @Valid XtaMessage message,
-		@NotNull @Valid XtaTransportReport transportReport
-) {
-}
diff --git a/src/main/java/de/ozgcloud/xta/client/model/XtaMessageMetaData.java b/src/main/java/de/ozgcloud/xta/client/model/XtaMessageMetaData.java
index 4ff59de99851b17542b682b0efe5b92b80b5ee67..a9b83320e520c6a718ebd7815662fc477eb3dc20 100644
--- a/src/main/java/de/ozgcloud/xta/client/model/XtaMessageMetaData.java
+++ b/src/main/java/de/ozgcloud/xta/client/model/XtaMessageMetaData.java
@@ -10,6 +10,24 @@ import jakarta.validation.constraints.PositiveOrZero;
 
 import lombok.Builder;
 
+/**
+ * Represents the metadata of an XTA message.
+ *
+ * <p>
+ * <small>Parameter documentation strings partially from <i>OSCI_MessageMetaData_V2.02.xsd</i>.</small>
+ * </p>
+ *
+ * @param service Distinct service in a certain business scenario context; in the XÖV context this is the "Dienste URI" (service URI). <p>This field is required.</p>
+ * @param businessScenarioCode Domain qualifier, e.g. Meldewesen, XVergabe... <p>This field is required.</p>
+ * @param businessScenarioListUri Code list URI of the business scenario. <p>If {@code null}, {@link XtaMessageMetaData#businessScenarioCode} refers to an undefined business scenario. Otherwise, it is a defined scenario which additionally requires {@link XtaMessageMetaData#businessScenarioListVersionId}.</p>
+ * @param businessScenarioListVersionId code list version ID of the business scenario. <p>Required if {@link XtaMessageMetaData#businessScenarioListUri} is not {@code null}.</p>
+ * @param messageTypeCode Code of the message type. <p>For instance, <i>Geschaeftsgang.Geschaeftsgang.0201</i> with business scenario <i>XDOMEAGAD_DATA</i>.</p> <p>This field is required.</p>
+ * @param messageTypePayloadSchema Payload schema of the message type. <p>For instance, <i>urn:xoev-de:xdomea:schema:2.4.0</i> with code <i>Geschaeftsgang.Geschaeftsgang.0201</i> and business scenario <i>XDOMEAGAD_DATA</i>.</p> <p>This field is required.</p>
+ * @param messageId Unique identifier of the message. <p>The ID is generated by the server and thus not required when sending.</p>
+ * @param authorIdentifier Identifier of the author of the message. <p>This field is required.</p>
+ * @param readerIdentifier Identifier of the reader of the message. <p>This field is required.</p>
+ * @param messageSize Size of the message in bytes. <p>The size is determined by the server an thus not required when sending.</p>
+ */
 @Builder(toBuilder = true)
 public record XtaMessageMetaData(
 		@NotBlank String service,
diff --git a/src/main/java/de/ozgcloud/xta/client/model/XtaMessageStatus.java b/src/main/java/de/ozgcloud/xta/client/model/XtaMessageStatus.java
index 4f43119f49063ff54013f81917ced31118d92655..ccf1baf22a48d48d4fd8d0a3427f67dabc4b204f 100644
--- a/src/main/java/de/ozgcloud/xta/client/model/XtaMessageStatus.java
+++ b/src/main/java/de/ozgcloud/xta/client/model/XtaMessageStatus.java
@@ -3,12 +3,27 @@ package de.ozgcloud.xta.client.model;
 import lombok.Getter;
 import lombok.RequiredArgsConstructor;
 
+/**
+ * Message status of a XTA message. The status is determined by the XTA sender/receiver server.
+ */
 @RequiredArgsConstructor
 @Getter
 public enum XtaMessageStatus {
+	/**
+	 * Status for a message that is open, i.e., has not been closed.
+	 */
 	OPEN(0),
+	/**
+	 * Status for a message that has been closed and has no errors or warnings.
+	 */
 	GREEN(1),
+	/**
+	 * Status for a message that has been closed and has warnings but no errors.
+	 */
 	YELLOW(2),
+	/**
+	 * Status for a message that has been closed and has errors.
+	 */
 	RED(3);
 
 	private final Integer code;
diff --git a/src/main/java/de/ozgcloud/xta/client/model/XtaTransportReport.java b/src/main/java/de/ozgcloud/xta/client/model/XtaTransportReport.java
index c768d2a3bf7e5fe1ef6c88ce46fc474b32829358..13dca75c777988fc90015225f78cb8384b96b137 100644
--- a/src/main/java/de/ozgcloud/xta/client/model/XtaTransportReport.java
+++ b/src/main/java/de/ozgcloud/xta/client/model/XtaTransportReport.java
@@ -7,6 +7,13 @@ import jakarta.validation.constraints.NotNull;
 
 import lombok.Builder;
 
+/**
+ * A transport report of a XTA message.
+ *
+ * @param metaData Metadata of the message.
+ * @param reportTime Time of the report.
+ * @param status Status of the message at the time of {@link XtaTransportReport#reportTime}.
+ */
 @Builder
 public record XtaTransportReport(
 		@NotNull @Valid XtaMessageMetaData metaData,
diff --git a/src/main/java/de/ozgcloud/xta/client/xdomea/XdomeaXtaMessageCreator.java b/src/main/java/de/ozgcloud/xta/client/xdomea/XdomeaXtaMessageCreator.java
index 05c1949899aef4596294624f72055859fd210620..13b5ec07e60a9d32a011ca18e90472f6a1fea461 100644
--- a/src/main/java/de/ozgcloud/xta/client/xdomea/XdomeaXtaMessageCreator.java
+++ b/src/main/java/de/ozgcloud/xta/client/xdomea/XdomeaXtaMessageCreator.java
@@ -10,8 +10,8 @@ import javax.xml.parsers.DocumentBuilder;
 import org.w3c.dom.Document;
 import org.xml.sax.SAXException;
 
-import de.ozgcloud.common.errorhandling.TechnicalException;
 import de.ozgcloud.xta.client.exception.XtaClientException;
+import de.ozgcloud.xta.client.exception.XtaClientRuntimeException;
 import de.ozgcloud.xta.client.model.XtaFile;
 import de.ozgcloud.xta.client.model.XtaMessage;
 import de.ozgcloud.xta.client.model.XtaMessageMetaData;
@@ -22,6 +22,30 @@ import de.ozgcloud.xta.client.xdomea.reader.ZipFileEntryReader;
 import lombok.Builder;
 import lombok.RequiredArgsConstructor;
 
+/**
+ * Creator of {@link XtaMessage}s for Xdomea.
+ *
+ * <p>
+ * The XdomeaXtaMessageCreator is used to create an {@link XtaMessage} for an Xdomea zip file. The resulting message may be send via the
+ * {@link de.ozgcloud.xta.client.XtaClient XtaClient}.
+ * </p>
+ *
+ *
+ * Example:
+ * <pre>
+ * var xtaMessageCreator = XdomeaXtaMessageCreator.createInstance();
+ * var zipFileName = "d5be7468-e620-4126-a40e-61a7f9b46345_Geschaeftsgang.Geschaeftsgang.0201.zip";
+ * var zipFileContentDataHandler = new DataHandler(new FileDataSource("/path/to/" + zipFileName));
+ * var xdomeaXtaFile = XtaFile.builder()
+ *   .name(zipFileName)
+ *   .content(zipFileContentDataHandler)
+ *   .contentType("application/zip")
+ *   .build();
+ * var xtaMessage = xtaMessageCreator.createMessage(xdomeaXtaFile);
+ *
+ * XtaClient.from(...).sendMessage(xtaMessage);
+ * </pre>
+ */
 @Builder
 @RequiredArgsConstructor
 public class XdomeaXtaMessageCreator {
@@ -36,6 +60,23 @@ public class XdomeaXtaMessageCreator {
 		return XdomeaXtaMessageCreatorFactory.createInstance().create();
 	}
 
+	/**
+	 * Creates an {@link XtaMessage} from the given xdomea zip file.
+	 *
+	 * <p>
+	 * The zip file has to follow the XTA/Xdomea generic transport specification. According to the specification, only the Xdomea messages of type
+	 * 0201, 0401 and 0402 are supported.
+	 * </p>
+	 *
+	 * <p>
+	 * <small>The XTA/Xdomea generic transport specification is unofficially available as <i>"Transportfestlegungen Generischer
+	 * Antragsdienst.pdf"</i>.</small>
+	 * </p>
+	 *
+	 * @param xdomeaZipFile the xdomea zip file
+	 * @return the xta message with metadata derived from the xdomea zip file
+	 * @throws XtaClientException if no valid metadata could be derived from the xdomea zip file.
+	 */
 	public XtaMessage createMessage(XtaFile xdomeaZipFile) throws XtaClientException {
 		return XtaMessage.builder()
 				.metaData(deriveValidMetaData(xdomeaZipFile))
@@ -50,7 +91,7 @@ public class XdomeaXtaMessageCreator {
 			var messageMetadataData = metadataMapper.mapXtaMessageMetadata(xdomeaXmlValues);
 			metaDataValidator.validate(xdomeaZipFile, xdomeaXmlValues, messageMetadataData);
 			return messageMetadataData;
-		} catch (TechnicalException e) {
+		} catch (XtaClientRuntimeException e) {
 			throw new XtaClientException("Failed to derive valid message metadata from xdomea document!", e);
 		}
 	}
@@ -72,7 +113,7 @@ public class XdomeaXtaMessageCreator {
 		try {
 			return documentBuilder.parse(inputStream);
 		} catch (SAXException | IOException e) {
-			throw new TechnicalException("Failed to parse xml document!", e);
+			throw new XtaClientRuntimeException("Failed to parse xml document!", e);
 		}
 	}
 
diff --git a/src/main/java/de/ozgcloud/xta/client/xdomea/XdomeaXtaMessageCreatorFactory.java b/src/main/java/de/ozgcloud/xta/client/xdomea/XdomeaXtaMessageCreatorFactory.java
index 3b6ff6aba506a706aa6c09cc66c6d9a87e1f66bb..914f9e3d1d9b9890de3a18c231b654fc7df065ab 100644
--- a/src/main/java/de/ozgcloud/xta/client/xdomea/XdomeaXtaMessageCreatorFactory.java
+++ b/src/main/java/de/ozgcloud/xta/client/xdomea/XdomeaXtaMessageCreatorFactory.java
@@ -22,7 +22,7 @@ import org.xml.sax.ErrorHandler;
 import org.xml.sax.SAXException;
 import org.xml.sax.SAXParseException;
 
-import de.ozgcloud.common.errorhandling.TechnicalException;
+import de.ozgcloud.xta.client.exception.XtaClientRuntimeException;
 import de.ozgcloud.xta.client.xdomea.mapper.MetadataMapper;
 import de.ozgcloud.xta.client.xdomea.reader.XdomeaValueReaderFactory;
 import de.ozgcloud.xta.client.xdomea.reader.ZipFileEntryReader;
@@ -82,7 +82,7 @@ public class XdomeaXtaMessageCreatorFactory {
 			xPathFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, Boolean.TRUE);
 			return xPathFactory;
 		} catch (XPathFactoryConfigurationException e) {
-			throw new TechnicalException("Failed to configure xpath factory!", e);
+			throw new XtaClientRuntimeException("Failed to configure xpath factory!", e);
 		}
 	}
 
@@ -126,7 +126,7 @@ public class XdomeaXtaMessageCreatorFactory {
 			schemaFactory.setResourceResolver(createResourceResolver());
 			return schemaFactory.newSchema(createSchemaStreamSources());
 		} catch (SAXException e) {
-			throw new TechnicalException("Failed to initialize schema", e);
+			throw new XtaClientRuntimeException("Failed to initialize schema", e);
 		}
 	}
 
@@ -140,7 +140,7 @@ public class XdomeaXtaMessageCreatorFactory {
 			documentBuilder.setErrorHandler(errorHandler);
 			return documentBuilder;
 		} catch (ParserConfigurationException e) {
-			throw new TechnicalException("Failed to configure document builder!", e);
+			throw new XtaClientRuntimeException("Failed to configure document builder!", e);
 		}
 	}
 
diff --git a/src/main/java/de/ozgcloud/xta/client/xdomea/mapper/MetadataMapper.java b/src/main/java/de/ozgcloud/xta/client/xdomea/mapper/MetadataMapper.java
index 94ccf0948d49d4fec6b3919310cba71a756a622c..5d02ec81a0186c44be01e8bbdc098d6bb4505630 100644
--- a/src/main/java/de/ozgcloud/xta/client/xdomea/mapper/MetadataMapper.java
+++ b/src/main/java/de/ozgcloud/xta/client/xdomea/mapper/MetadataMapper.java
@@ -5,7 +5,7 @@ import org.mapstruct.Mapping;
 import org.mapstruct.Named;
 import org.mapstruct.ReportingPolicy;
 
-import de.ozgcloud.common.errorhandling.TechnicalException;
+import de.ozgcloud.xta.client.exception.XtaClientRuntimeException;
 import de.ozgcloud.xta.client.model.XtaIdentifier;
 import de.ozgcloud.xta.client.model.XtaMessageMetaData;
 import de.ozgcloud.xta.client.xdomea.reader.XdomeaXmlValues;
@@ -16,8 +16,10 @@ import de.ozgcloud.xta.client.xdomea.reader.XdomeaXmlValues;
 public interface MetadataMapper {
 	String CODE_0201 = "0201";
 	String CODE_0401 = "0401";
+	String CODE_0402 = "0402";
 	String MESSAGE_TYPE_CODE_0201 = "Geschaeftsgang.Geschaeftsgang.0201";
 	String MESSAGE_TYPE_CODE_0401 = "Abgabe.Abgabe.0401";
+	String MESSAGE_TYPE_CODE_0402 = "Abgabe.ImportBestaetigen.0402";
 	String AUTHOR_ID_PREFIX = "gad";
 	String AUTHOR_ID_CATEGORY = "Generischer Antragsdienst";
 
@@ -49,8 +51,8 @@ public interface MetadataMapper {
 	default String getServiceByMessageTypeCode(String messageTypeCode) {
 		return switch (messageTypeCode) {
 			case CODE_0201 -> SERVICE_XDOMEA_240;
-			case CODE_0401 -> SERVICE_XDOMEA_300;
-			default -> throw new TechnicalException("Unknown messageTypeCode: " + messageTypeCode);
+			case CODE_0401, CODE_0402 -> SERVICE_XDOMEA_300;
+			default -> throw new XtaClientRuntimeException("Unknown messageTypeCode: " + messageTypeCode);
 		};
 	}
 
@@ -59,7 +61,8 @@ public interface MetadataMapper {
 		return switch (messageTypeCode) {
 			case CODE_0201 -> MESSAGE_TYPE_CODE_0201;
 			case CODE_0401 -> MESSAGE_TYPE_CODE_0401;
-			default -> throw new TechnicalException("Unknown messageTypeCode: " + messageTypeCode);
+			case CODE_0402 -> MESSAGE_TYPE_CODE_0402;
+			default -> throw new XtaClientRuntimeException("Unknown messageTypeCode: " + messageTypeCode);
 		};
 	}
 
@@ -67,8 +70,8 @@ public interface MetadataMapper {
 	default String getMessageTypePayloadSchemaByMessageTypeCode(String messageTypeCode) {
 		return switch (messageTypeCode) {
 			case CODE_0201 -> MESSAGE_TYPE_PAYLOAD_SCHEMA_XDOMEA_240;
-			case CODE_0401 -> MESSAGE_TYPE_PAYLOAD_SCHEMA_XDOMEA_300;
-			default -> throw new TechnicalException("Unknown messageTypeCode: " + messageTypeCode);
+			case CODE_0401, CODE_0402 -> MESSAGE_TYPE_PAYLOAD_SCHEMA_XDOMEA_300;
+			default -> throw new XtaClientRuntimeException("Unknown messageTypeCode: " + messageTypeCode);
 		};
 	}
 
diff --git a/src/main/java/de/ozgcloud/xta/client/xdomea/reader/XmlValueReader.java b/src/main/java/de/ozgcloud/xta/client/xdomea/reader/XmlValueReader.java
index 642bff51e49b4c7ff2b3c2d8f7cbefc362dc4b67..8019eef8967bf0b9a4eed21c6a9090e5e15bac4a 100644
--- a/src/main/java/de/ozgcloud/xta/client/xdomea/reader/XmlValueReader.java
+++ b/src/main/java/de/ozgcloud/xta/client/xdomea/reader/XmlValueReader.java
@@ -11,7 +11,7 @@ import org.w3c.dom.Document;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
 
-import de.ozgcloud.common.errorhandling.TechnicalException;
+import de.ozgcloud.xta.client.exception.XtaClientRuntimeException;
 import lombok.Builder;
 import lombok.RequiredArgsConstructor;
 
@@ -34,7 +34,7 @@ public class XmlValueReader {
 							XPathConstants.NODESET
 					);
 		} catch (XPathExpressionException e) {
-			throw new TechnicalException("Failed to execute xpath search!", e);
+			throw new XtaClientRuntimeException("Failed to execute xpath search!", e);
 		}
 	}
 
diff --git a/src/main/java/de/ozgcloud/xta/client/xdomea/reader/XmlValueReaderFactory.java b/src/main/java/de/ozgcloud/xta/client/xdomea/reader/XmlValueReaderFactory.java
index 5f28091a231a036a4dfefd2b6e9a08883199e0c4..24b7b95913a0190d6a1210c42b83ef641cd7d563 100644
--- a/src/main/java/de/ozgcloud/xta/client/xdomea/reader/XmlValueReaderFactory.java
+++ b/src/main/java/de/ozgcloud/xta/client/xdomea/reader/XmlValueReaderFactory.java
@@ -4,7 +4,7 @@ import javax.xml.xpath.XPathExpression;
 import javax.xml.xpath.XPathExpressionException;
 import javax.xml.xpath.XPathFactory;
 
-import de.ozgcloud.common.errorhandling.TechnicalException;
+import de.ozgcloud.xta.client.exception.XtaClientRuntimeException;
 import lombok.Builder;
 import lombok.RequiredArgsConstructor;
 
@@ -19,7 +19,7 @@ public class XmlValueReaderFactory {
 		try {
 			return xPathFactory.newXPath().compile(textXpathString);
 		} catch (XPathExpressionException e) {
-			throw new TechnicalException("Failed to compile xpath expression!", e);
+			throw new XtaClientRuntimeException("Failed to compile xpath expression!", e);
 		}
 	}
 
diff --git a/src/main/java/de/ozgcloud/xta/client/xdomea/reader/ZipFileEntryReader.java b/src/main/java/de/ozgcloud/xta/client/xdomea/reader/ZipFileEntryReader.java
index 8b0df0b9cc40098cd285e228fed1895c0a66e862..de117ea42d507b860d7d69f77d84f289289ed41f 100644
--- a/src/main/java/de/ozgcloud/xta/client/xdomea/reader/ZipFileEntryReader.java
+++ b/src/main/java/de/ozgcloud/xta/client/xdomea/reader/ZipFileEntryReader.java
@@ -10,7 +10,7 @@ import java.util.zip.ZipInputStream;
 
 import jakarta.activation.DataHandler;
 
-import de.ozgcloud.common.errorhandling.TechnicalException;
+import de.ozgcloud.xta.client.exception.XtaClientRuntimeException;
 import lombok.Builder;
 import lombok.RequiredArgsConstructor;
 
@@ -27,9 +27,9 @@ public class ZipFileEntryReader {
 				}
 				zipInputStream.closeEntry();
 			}
-			throw new TechnicalException("Failed to find zip entry '%s'!".formatted(entryName));
+			throw new XtaClientRuntimeException("Failed to find zip entry '%s'!".formatted(entryName));
 		} catch (IOException e) {
-			throw new TechnicalException("Failed reading zip file!", e);
+			throw new XtaClientRuntimeException("Failed reading zip file!", e);
 		}
 	}
 
@@ -43,7 +43,7 @@ public class ZipFileEntryReader {
 			}
 			return entryNames;
 		} catch (IOException e) {
-			throw new TechnicalException("Failed reading zip file!", e);
+			throw new XtaClientRuntimeException("Failed reading zip file!", e);
 		}
 	}
 }
diff --git a/src/test/java/de/ozgcloud/xta/client/XtaClientITCase.java b/src/test/java/de/ozgcloud/xta/client/XtaClientITCase.java
index 64681cfe9abead1d25b6f0d8626241b0f90244a7..0a244ea890e783196ba7be4f7c85ccbd06d93689 100644
--- a/src/test/java/de/ozgcloud/xta/client/XtaClientITCase.java
+++ b/src/test/java/de/ozgcloud/xta/client/XtaClientITCase.java
@@ -30,7 +30,7 @@ import lombok.SneakyThrows;
 class XtaClientITCase {
 
 	@RegisterExtension
-	static final XtaTestServerSetupExtension XTA_TEST_SERVER_SETUP_EXTENSION = new XtaTestServerSetupExtension();
+	private static final XtaTestServerSetupExtension XTA_TEST_SERVER_SETUP_EXTENSION = new XtaTestServerSetupExtension();
 	static final int TWO_MAX_LIST_ITEMS = 2;
 
 	private XtaClient silentTestClient;
diff --git a/src/test/java/de/ozgcloud/xta/client/XtaClientRemoteITCase.java b/src/test/java/de/ozgcloud/xta/client/XtaClientRemoteITCase.java
index 0ceac4857e86725204502ed1d2828a864c891ce7..8878a3f753dda96d394db1fc801f0462e33c3dad 100644
--- a/src/test/java/de/ozgcloud/xta/client/XtaClientRemoteITCase.java
+++ b/src/test/java/de/ozgcloud/xta/client/XtaClientRemoteITCase.java
@@ -11,7 +11,6 @@ import java.util.function.Consumer;
 import java.util.function.Predicate;
 import java.util.stream.Stream;
 
-import org.junit.Ignore;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.DisplayName;
@@ -44,11 +43,10 @@ import lombok.extern.slf4j.Slf4j;
 				"This test requires the path KOP_SH_KIEL_{DEV,TEST}_PATH and password KOP_SH_KIEL_{DEV,TEST}_PASSWORD of KOP_SH_KIEL_DEV.p12 and OZG-CLOUD_SH_KIEL_TEST.pfx. "
 						+ "Additionally, the endpoint of the DEV-xta-server at li33-0005.dp.dsecurecloud.de must be reachable."
 )
-@Ignore
 class XtaClientRemoteITCase {
 
 	@RegisterExtension
-	static final XtaRemoteServerSetupExtension XTA_REMOTE_SERVER_SETUP_EXTENSION = new XtaRemoteServerSetupExtension();
+	private static final XtaRemoteServerSetupExtension XTA_REMOTE_SERVER_SETUP_EXTENSION = new XtaRemoteServerSetupExtension();
 
 	private static final XdomeaXtaMessageCreator XDOMEA_XTA_MESSAGE_CREATOR = XdomeaXtaMessageCreator.createInstance();
 
@@ -62,6 +60,8 @@ class XtaClientRemoteITCase {
 	private Consumer<XtaMessage> processMessageDummy;
 	private Predicate<XtaMessageMetaData> isSupportedDummy;
 
+	private List<String> sendMessageIds;
+
 	@BeforeEach
 	@SneakyThrows
 	void setup() {
@@ -76,7 +76,6 @@ class XtaClientRemoteITCase {
 		devClient = XTA_REMOTE_SERVER_SETUP_EXTENSION.getDevClient();
 		silentDevClient = XTA_REMOTE_SERVER_SETUP_EXTENSION.getSilentDevClient();
 
-		// Fail if any message pending, to ensure that we do not clear existing messages in the DEV environment
 		failIfAnyMessagePending(XTA_REMOTE_SERVER_SETUP_EXTENSION.getSilentDevClientConfig(), DEV_READER_CLIENT_IDENTIFIER);
 		failIfAnyMessagePending(XTA_REMOTE_SERVER_SETUP_EXTENSION.getSilentTestClientConfig(), TEST_READER_CLIENT_IDENTIFIER);
 
@@ -89,8 +88,8 @@ class XtaClientRemoteITCase {
 	}
 
 	private void closeMessagesForAllReaders() {
-		closeAllMessages(XTA_REMOTE_SERVER_SETUP_EXTENSION.getSilentDevClientConfig(), DEV_READER_CLIENT_IDENTIFIER);
-		closeAllMessages(XTA_REMOTE_SERVER_SETUP_EXTENSION.getSilentTestClientConfig(), TEST_READER_CLIENT_IDENTIFIER);
+		closeMessagesById(XTA_REMOTE_SERVER_SETUP_EXTENSION.getSilentDevClientConfig(), DEV_READER_CLIENT_IDENTIFIER, sendMessageIds);
+		closeMessagesById(XTA_REMOTE_SERVER_SETUP_EXTENSION.getSilentTestClientConfig(), TEST_READER_CLIENT_IDENTIFIER, sendMessageIds);
 	}
 
 	@DisplayName("fetch messages")
@@ -98,7 +97,6 @@ class XtaClientRemoteITCase {
 	class TestFetchMessages {
 
 		private List<XtaMessage> sendMessages;
-		private List<String> sendMessageIds;
 
 		@BeforeEach
 		void setup() {
@@ -258,10 +256,23 @@ class XtaClientRemoteITCase {
 		void shouldReturn(String messageLabel) {
 			XtaMessage xtaMessage = createXdomeaMessage(loadMessage(messageLabel).messageFile());
 
-			var result = testClient.sendMessage(xtaMessage);
+			var result = sendMessage(xtaMessage);
 
 			assertThat(result.status()).isEqualTo(XtaMessageStatus.OPEN);
 		}
+
+		@SneakyThrows
+		private XtaTransportReport sendMessage(XtaMessage xtaMessage) {
+			var report = testClient.sendMessage(xtaMessage);
+			recordMessageIdForCleanup(report);
+			return report;
+		}
+
+		private void recordMessageIdForCleanup(XtaTransportReport report) {
+			var messageId = report.metaData().messageId();
+			assertThat(messageId).isNotNull();
+			sendMessageIds = List.of(messageId);
+		}
 	}
 
 	private XtaMessage createMessage(String messageLabel, XtaIdentifier author, XtaIdentifier reader) {
diff --git a/src/test/java/de/ozgcloud/xta/client/extension/Patch.java b/src/test/java/de/ozgcloud/xta/client/extension/Patch.java
index d527b0f0325b879aecc1d4fef0bb7067e6e42b8e..425cdfa9edf8333f59187e2df8d31861aaffe88a 100644
--- a/src/test/java/de/ozgcloud/xta/client/extension/Patch.java
+++ b/src/test/java/de/ozgcloud/xta/client/extension/Patch.java
@@ -4,7 +4,7 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Optional;
 
-import de.ozgcloud.common.errorhandling.TechnicalException;
+import de.ozgcloud.xta.client.exception.XtaClientRuntimeException;
 
 public record Patch(
 		String filePath,
@@ -30,8 +30,8 @@ public record Patch(
 				lineOffset = patchResult.lineOffset();
 			}
 			lines.forEachRemaining(patchedContent::append);
-		} catch (TechnicalException exception) {
-			throw new TechnicalException("Error applying patch! filePath=" + filePath, exception);
+		} catch (XtaClientRuntimeException exception) {
+			throw new XtaClientRuntimeException("Error applying patch! filePath=" + filePath, exception);
 		}
 		return patchedContent.toString();
 	}
diff --git a/src/test/java/de/ozgcloud/xta/client/extension/PatchHunk.java b/src/test/java/de/ozgcloud/xta/client/extension/PatchHunk.java
index 912c39baa0c9688d2797813cb95a4142af9c8b1f..4c3c4268a292a06cdff6b692cbb898d157cb2618 100644
--- a/src/test/java/de/ozgcloud/xta/client/extension/PatchHunk.java
+++ b/src/test/java/de/ozgcloud/xta/client/extension/PatchHunk.java
@@ -4,7 +4,7 @@ import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 
-import de.ozgcloud.common.errorhandling.TechnicalException;
+import de.ozgcloud.xta.client.exception.XtaClientRuntimeException;
 
 public record PatchHunk(
 		int contextStartLineNumber,
@@ -27,7 +27,7 @@ public record PatchHunk(
 					var contextLine = lines.next();
 					lineOffset++;
 					if (!hunkLine.line.equals(contextLine)) {
-						throw new TechnicalException(
+						throw new XtaClientRuntimeException(
 								"Unexpected context line! expected='" + hunkLine.line + "' actual='" + contextLine + "', lineOffset=" + lineOffset);
 					}
 					patchedLines.add(contextLine);
@@ -37,7 +37,7 @@ public record PatchHunk(
 					var removeLine = lines.next();
 					lineOffset++;
 					if (!hunkLine.line.equals(removeLine)) {
-						throw new TechnicalException(
+						throw new XtaClientRuntimeException(
 								"Unexpected remove line! expected='" + hunkLine.line + "' actual='" + removeLine + "', lineOffset=" + lineOffset);
 					}
 				}
@@ -49,7 +49,7 @@ public record PatchHunk(
 	private int skipToContextStart(Iterator<String> lines, int lineOffset, List<String> patchedLines) {
 		for (; lineOffset < contextStartLineNumber - 1; lineOffset++) {
 			if (!lines.hasNext()) {
-				throw new TechnicalException("Unexpected end of target file! lineOffset=" + lineOffset);
+				throw new XtaClientRuntimeException("Unexpected end of target file! lineOffset=" + lineOffset);
 			}
 			patchedLines.add(lines.next());
 		}
@@ -90,14 +90,14 @@ public record PatchHunk(
 		var sourceLineOffset = 0;
 		while (sourceLineOffset < header.sourceLineCount()) {
 			if (!lines.hasNext()) {
-				throw new TechnicalException("Unexpected end of patch hunk! sourceLineOffset=" + sourceLineOffset + ", header=" + header);
+				throw new XtaClientRuntimeException("Unexpected end of patch hunk! sourceLineOffset=" + sourceLineOffset + ", header=" + header);
 			}
 			var line = lines.next();
 			var operation = switch (line.substring(0, 1)) {
 				case " " -> PatchOperation.CONTEXT;
 				case "+" -> PatchOperation.ADD;
 				case "-" -> PatchOperation.REMOVE;
-				default -> throw new TechnicalException(
+				default -> throw new XtaClientRuntimeException(
 						"Unexpected line in patch hunk! line=" + line + "sourceLineOffset=" + sourceLineOffset + ", header=" + header);
 			};
 			sourceLineOffset += switch (operation) {
diff --git a/src/test/java/de/ozgcloud/xta/client/extension/XtaServerSetupExtensionTestUtil.java b/src/test/java/de/ozgcloud/xta/client/extension/XtaServerSetupExtensionTestUtil.java
index 0432d3445846171a7908c47377e0d1b32baa48be..cdd531f78bf541920f2d62089efe29bd83b62f36 100644
--- a/src/test/java/de/ozgcloud/xta/client/extension/XtaServerSetupExtensionTestUtil.java
+++ b/src/test/java/de/ozgcloud/xta/client/extension/XtaServerSetupExtensionTestUtil.java
@@ -119,6 +119,12 @@ public class XtaServerSetupExtensionTestUtil {
 		var messageIds = result.messages().stream()
 				.map(XtaMessageMetaData::messageId)
 				.toList();
+		closeMessagesById(config, clientId, messageIds);
+	}
+
+	@SneakyThrows
+	public static void closeMessagesById(XtaClientConfig config, XtaIdentifier clientId, List<String> messageIds) {
+		var wrappedService = createWrappedService(config);
 		for (var messageId : messageIds) {
 			wrappedService.close(messageId, clientId);
 		}
diff --git a/src/test/java/de/ozgcloud/xta/client/xdomea/XdomeaXtaMessageCreatorFactoryTest.java b/src/test/java/de/ozgcloud/xta/client/xdomea/XdomeaXtaMessageCreatorFactoryTest.java
index 723de052ef5cbc4d9796fe8179329e33b70045e7..2dac4c546741642d83ca57f968ef6b8362cb6a97 100644
--- a/src/test/java/de/ozgcloud/xta/client/xdomea/XdomeaXtaMessageCreatorFactoryTest.java
+++ b/src/test/java/de/ozgcloud/xta/client/xdomea/XdomeaXtaMessageCreatorFactoryTest.java
@@ -33,7 +33,7 @@ import org.w3c.dom.ls.LSResourceResolver;
 import org.xml.sax.ErrorHandler;
 import org.xml.sax.SAXException;
 
-import de.ozgcloud.common.errorhandling.TechnicalException;
+import de.ozgcloud.xta.client.exception.XtaClientRuntimeException;
 import de.ozgcloud.xta.client.xdomea.mapper.MetadataMapper;
 import de.ozgcloud.xta.client.xdomea.reader.XdomeaValueReader;
 import de.ozgcloud.xta.client.xdomea.reader.XdomeaValueReaderFactory;
@@ -164,7 +164,7 @@ class XdomeaXtaMessageCreatorFactoryTest {
 			doThrow(parserConfigurationException).when(documentBuilderFactory).setFeature(DISALLOW_DOCTYPE_DECL_FEATURE_URL, true);
 
 			assertThatThrownBy(() -> factory.create())
-					.isInstanceOf(TechnicalException.class)
+					.isInstanceOf(XtaClientRuntimeException.class)
 					.hasCause(parserConfigurationException);
 		}
 
@@ -222,14 +222,14 @@ class XdomeaXtaMessageCreatorFactoryTest {
 			verify(schemaFactory).setResourceResolver(resolver);
 		}
 
-		@DisplayName("should throw technical initialization exception")
+		@DisplayName("should throw runtime initialization exception")
 		@Test
 		@SneakyThrows
 		void shouldThrowTechnicalInitializationException() {
 			doThrow(new SAXException()).when(schemaFactory).newSchema(schemaSources);
 
 			assertThatThrownBy(() -> factory.createSchema())
-					.isInstanceOf(TechnicalException.class);
+					.isInstanceOf(XtaClientRuntimeException.class);
 		}
 	}
 
diff --git a/src/test/java/de/ozgcloud/xta/client/xdomea/XdomeaXtaMessageCreatorITCase.java b/src/test/java/de/ozgcloud/xta/client/xdomea/XdomeaXtaMessageCreatorITCase.java
index 7ff3ffd6754a4682db3cf3c660134f77127a6ee0..84c3eea862fd6197ddae096f5f2171cb61f31cd2 100644
--- a/src/test/java/de/ozgcloud/xta/client/xdomea/XdomeaXtaMessageCreatorITCase.java
+++ b/src/test/java/de/ozgcloud/xta/client/xdomea/XdomeaXtaMessageCreatorITCase.java
@@ -22,7 +22,7 @@ class XdomeaXtaMessageCreatorITCase {
 
 	@BeforeEach
 	void setup() {
-		creator = XdomeaXtaMessageCreatorFactory.createInstance().create();
+		creator = XdomeaXtaMessageCreator.createInstance();
 	}
 
 	@DisplayName("create message")
diff --git a/src/test/java/de/ozgcloud/xta/client/xdomea/XdomeaXtaMessageCreatorTest.java b/src/test/java/de/ozgcloud/xta/client/xdomea/XdomeaXtaMessageCreatorTest.java
index a183007f589a4083b82296c8c9331825a434c727..48864bcbe17e4277fb2ba5837284dc902c2eca2f 100644
--- a/src/test/java/de/ozgcloud/xta/client/xdomea/XdomeaXtaMessageCreatorTest.java
+++ b/src/test/java/de/ozgcloud/xta/client/xdomea/XdomeaXtaMessageCreatorTest.java
@@ -19,8 +19,8 @@ import org.mockito.Mock;
 import org.mockito.Spy;
 import org.w3c.dom.Document;
 
-import de.ozgcloud.common.errorhandling.TechnicalException;
 import de.ozgcloud.xta.client.exception.XtaClientException;
+import de.ozgcloud.xta.client.exception.XtaClientRuntimeException;
 import de.ozgcloud.xta.client.factory.XdomeaXmlValuesTestFactory;
 import de.ozgcloud.xta.client.factory.XtaFileTestFactory;
 import de.ozgcloud.xta.client.factory.XtaMessageMetaDataTestFactory;
@@ -111,7 +111,7 @@ class XdomeaXtaMessageCreatorTest {
 		private XtaMessageMetaData metaData;
 
 		@Mock
-		private TechnicalException technicalException;
+		private XtaClientRuntimeException runtimeException;
 
 		@BeforeEach
 		@SneakyThrows
@@ -153,7 +153,7 @@ class XdomeaXtaMessageCreatorTest {
 		@DisplayName("should throw client exception")
 		@Test
 		void shouldThrowClientException() {
-			doThrow(technicalException).when(metadataMapper).mapXtaMessageMetadata(xdomeaXmlValues);
+			doThrow(runtimeException).when(metadataMapper).mapXtaMessageMetadata(xdomeaXmlValues);
 
 			assertThatThrownBy(() -> creator.deriveValidMetaData(xdomeaZipFile))
 					.isInstanceOf(XtaClientException.class);
diff --git a/src/test/java/de/ozgcloud/xta/client/xdomea/mapper/MetadataMapperTest.java b/src/test/java/de/ozgcloud/xta/client/xdomea/mapper/MetadataMapperTest.java
index 46ed9f9fbfd4c6e95439562023ea9c723dc7e1d5..95529c12d0f7468a1ce02929b200af5769ecde59 100644
--- a/src/test/java/de/ozgcloud/xta/client/xdomea/mapper/MetadataMapperTest.java
+++ b/src/test/java/de/ozgcloud/xta/client/xdomea/mapper/MetadataMapperTest.java
@@ -11,7 +11,7 @@ import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.ValueSource;
 import org.mapstruct.factory.Mappers;
 
-import de.ozgcloud.common.errorhandling.TechnicalException;
+import de.ozgcloud.xta.client.exception.XtaClientRuntimeException;
 import de.ozgcloud.xta.client.factory.XdomeaXmlValuesTestFactory;
 import de.ozgcloud.xta.client.model.XtaMessageMetaData;
 
@@ -31,6 +31,14 @@ class MetadataMapperTest {
 			assertThat(metadata.service()).isEqualTo(SERVICE_XDOMEA_300);
 		}
 
+		@DisplayName("should map service 0402")
+		@Test
+		void shouldMapService0402() {
+			var metadata = doMapping(CODE_0402);
+
+			assertThat(metadata.service()).isEqualTo(SERVICE_XDOMEA_300);
+		}
+
 		@DisplayName("should map service 0201")
 		@Test
 		void shouldMapService0201() {
@@ -74,6 +82,14 @@ class MetadataMapperTest {
 			assertThat(metadata.messageTypeCode()).isEqualTo(MESSAGE_TYPE_CODE_0401);
 		}
 
+		@DisplayName("should map message type code 0402")
+		@Test
+		void shouldMapMessageTypeCode0402() {
+			var metadata = doMapping(CODE_0402);
+
+			assertThat(metadata.messageTypeCode()).isEqualTo(MESSAGE_TYPE_CODE_0402);
+		}
+
 		@DisplayName("should map message type code 0201")
 		@Test
 		void shouldMapMessageTypeCode0201() {
@@ -90,6 +106,14 @@ class MetadataMapperTest {
 			assertThat(metadata.messageTypePayloadSchema()).isEqualTo(MESSAGE_TYPE_PAYLOAD_SCHEMA_XDOMEA_300);
 		}
 
+		@DisplayName("should map message type payload schema 0402")
+		@Test
+		void shouldMapMessageTypePayloadSchema0402() {
+			var metadata = doMapping(CODE_0402);
+
+			assertThat(metadata.messageTypePayloadSchema()).isEqualTo(MESSAGE_TYPE_PAYLOAD_SCHEMA_XDOMEA_300);
+		}
+
 		@DisplayName("should map message type payload schema 0201")
 		@Test
 		void shouldMapMessageTypePayloadSchema0201() {
@@ -100,7 +124,7 @@ class MetadataMapperTest {
 
 		@DisplayName("should map author identifier value")
 		@ParameterizedTest
-		@ValueSource(strings = { CODE_0201, CODE_0401 })
+		@ValueSource(strings = { CODE_0201, CODE_0401, CODE_0402 })
 		void shouldMapAuthorIdentifierValue(String code) {
 			var metadata = doMapping(code);
 
@@ -109,7 +133,7 @@ class MetadataMapperTest {
 
 		@DisplayName("should map author identifier category")
 		@ParameterizedTest
-		@ValueSource(strings = { CODE_0201, CODE_0401 })
+		@ValueSource(strings = { CODE_0201, CODE_0401, CODE_0402 })
 		void shouldMapAuthorIdentifierCategory(String code) {
 			var metadata = doMapping(code);
 
@@ -118,7 +142,7 @@ class MetadataMapperTest {
 
 		@DisplayName("should map reader identifier value")
 		@ParameterizedTest
-		@ValueSource(strings = { CODE_0201, CODE_0401 })
+		@ValueSource(strings = { CODE_0201, CODE_0401, CODE_0402 })
 		void shouldMapReaderIdentifierValue(String code) {
 			var metadata = doMapping(code);
 
@@ -127,18 +151,18 @@ class MetadataMapperTest {
 
 		@DisplayName("should map reader identifier category")
 		@ParameterizedTest
-		@ValueSource(strings = { CODE_0201, CODE_0401 })
+		@ValueSource(strings = { CODE_0201, CODE_0401, CODE_0402 })
 		void shouldMapReaderIdentifierCategory(String code) {
 			var metadata = doMapping(code);
 
 			assertThat(metadata.readerIdentifier().category()).isEqualTo(READER_ID_CATEGORY);
 		}
 
-		@DisplayName("should throw technical exception with unknown message type code")
+		@DisplayName("should throw xta client runtime exception with unknown message type code")
 		@Test
-		void shouldThrowTechnicalExceptionWithUnknownMessageTypeCode() {
+		void shouldThrowXtaClientRuntimeExceptionWithUnknownMessageTypeCode() {
 			assertThatThrownBy(() -> doMapping("unknown"))
-					.isInstanceOf(TechnicalException.class);
+					.isInstanceOf(XtaClientRuntimeException.class);
 		}
 
 		private XtaMessageMetaData doMapping(String code) {
diff --git a/src/test/java/de/ozgcloud/xta/client/xdomea/reader/XmlValueReaderFactoryTest.java b/src/test/java/de/ozgcloud/xta/client/xdomea/reader/XmlValueReaderFactoryTest.java
index b848a3aea0f792d85c9676b501b53c6b7037eae9..ddce12f863c0685cb079da01129a459ab710a22e 100644
--- a/src/test/java/de/ozgcloud/xta/client/xdomea/reader/XmlValueReaderFactoryTest.java
+++ b/src/test/java/de/ozgcloud/xta/client/xdomea/reader/XmlValueReaderFactoryTest.java
@@ -14,7 +14,7 @@ import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.mockito.Mock;
 
-import de.ozgcloud.common.errorhandling.TechnicalException;
+import de.ozgcloud.xta.client.exception.XtaClientRuntimeException;
 import lombok.SneakyThrows;
 
 class XmlValueReaderFactoryTest {
@@ -66,14 +66,14 @@ class XmlValueReaderFactoryTest {
 					.build());
 		}
 
-		@DisplayName("should throw technical exception")
+		@DisplayName("should throw xta client runtime exception")
 		@Test
 		@SneakyThrows
-		void shouldThrowTechnicalException() {
+		void shouldThrowXtaClientRuntimeException() {
 			when(xpath.compile(textXpathString)).thenThrow(exception);
 
 			assertThatThrownBy(() -> factory.create())
-					.isInstanceOf(TechnicalException.class);
+					.isInstanceOf(XtaClientRuntimeException.class);
 		}
 	}
 
diff --git a/src/test/java/de/ozgcloud/xta/client/xdomea/reader/ZipFileEntryReaderTest.java b/src/test/java/de/ozgcloud/xta/client/xdomea/reader/ZipFileEntryReaderTest.java
index 37d1a0346e915cdb7f7ac542cafcbf1c74029470..038e663db92ccaad468fd31429ca5357933b6908 100644
--- a/src/test/java/de/ozgcloud/xta/client/xdomea/reader/ZipFileEntryReaderTest.java
+++ b/src/test/java/de/ozgcloud/xta/client/xdomea/reader/ZipFileEntryReaderTest.java
@@ -16,7 +16,7 @@ import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 
-import de.ozgcloud.common.errorhandling.TechnicalException;
+import de.ozgcloud.xta.client.exception.XtaClientRuntimeException;
 
 class ZipFileEntryReaderTest {
 	private static final DataHandler ZIP_FILE = EXAMPLE_ABGABE_MESSAGE.messageFile().content();
@@ -51,14 +51,14 @@ class ZipFileEntryReaderTest {
 		@Test
 		void shouldThrowExceptionIfEntryIsMissing() {
 			assertThatThrownBy(() -> reader.mapEntryData(ZIP_FILE, "?", inputStreamConsumer))
-					.isInstanceOf(TechnicalException.class);
+					.isInstanceOf(XtaClientRuntimeException.class);
 		}
 
 		@DisplayName("should throw exception on bad zip file")
 		@Test
 		void shouldThrowExceptionOnBadZipFile() {
 			assertThatThrownBy(() -> reader.mapEntryData(BAD_ZIP_FILE, ENTRY_NAME, inputStreamConsumer))
-					.isInstanceOf(TechnicalException.class);
+					.isInstanceOf(XtaClientRuntimeException.class);
 		}
 	}
 
@@ -83,7 +83,7 @@ class ZipFileEntryReaderTest {
 		@Test
 		void shouldThrowExceptionOnBadZipFile() {
 			assertThatThrownBy(() -> reader.getEntryNames(createMissingFileDataHandler()))
-					.isInstanceOf(TechnicalException.class);
+					.isInstanceOf(XtaClientRuntimeException.class);
 		}
 
 		private static DataHandler createMissingFileDataHandler() {