diff --git a/src/main/java/de/ozgcloud/xta/client/XtaClient.java b/src/main/java/de/ozgcloud/xta/client/XtaClient.java
index 53be82d1013dd48e8b6413dca6c7edae40fe281f..05e5ad8bd8cc80ccdbe86987d19381be55cf2dc3 100644
--- a/src/main/java/de/ozgcloud/xta/client/XtaClient.java
+++ b/src/main/java/de/ozgcloud/xta/client/XtaClient.java
@@ -2,13 +2,12 @@ package de.ozgcloud.xta.client;
 
 import jakarta.validation.constraints.NotBlank;
 
-import org.apache.commons.lang3.NotImplementedException;
-
 import de.ozgcloud.xta.client.config.XtaClientConfig;
 import de.ozgcloud.xta.client.core.WrappedXtaService;
 import de.ozgcloud.xta.client.model.Identifier;
 import de.ozgcloud.xta.client.model.XtaMessage;
 import de.ozgcloud.xta.client.model.XtaMessageMetaDataListing;
+import genv3.de.xoev.transport.xta.x211.InvalidMessageIDException;
 import genv3.de.xoev.transport.xta.x211.PermissionDeniedException;
 import genv3.de.xoev.transport.xta.x211.XTAWSTechnicalProblemException;
 import lombok.AccessLevel;
@@ -25,47 +24,49 @@ public class XtaClient {
 	private final XtaClientConfig config;
 
 	/**
-	 * Fetch metadata of pending messages sent to the {@code xtaIdentifier}.
-	 * The returned listing contains at most {@link de.ozgcloud.xta.client.config.XtaClientConfig#getMaxListItems() maxListItems} messages.
-	 * Use the {@code requestId} to {@link #close(String) close} pending messages.
-	 * To fetch the next messages, use {@link #getNextMessagesMetadata(String)}.
-	 * Note that {@code xtaIdentifier} has to be configured as a {@link de.ozgcloud.xta.client.config.XtaClientConfig#getClientIdentifiers() clientIdentifiers}.
+	 * Fetch metadata of pending messages sent to the {@code xtaIdentifier}. The returned listing contains at most
+	 * {@link de.ozgcloud.xta.client.config.XtaClientConfig#getMaxListItems() maxListItems} messages. Use the {@code requestId} to
+	 * {@link #close(String) close} pending messages. To fetch the next messages, use {@link #getNextMessagesMetadata(String)}. Note that
+	 * {@code xtaIdentifier} has to be configured as a
+	 * {@link de.ozgcloud.xta.client.config.XtaClientConfig#getClientIdentifiers() clientIdentifiers}.
 	 *
-	 * @param xtaIdentifier the client identifier value to fetch messages for
+	 * @param clientIdentifier the client identifier value to fetch messages for
 	 * @return the listing result with metadata of messages
 	 */
-	public XtaMessageMetaDataListing getMessagesMetadata(@NotBlank String xtaIdentifier)
+	public XtaMessageMetaDataListing getMessagesMetadata(@NotBlank String clientIdentifier)
 			throws XTAWSTechnicalProblemException, PermissionDeniedException {
-		var clientIdentifier = deriveIdentifier(xtaIdentifier);
-		service.checkAccountActive(clientIdentifier);
-		return getStatusList(clientIdentifier);
+		var identifier = deriveIdentifier(clientIdentifier);
+		service.checkAccountActive(identifier);
+		return getStatusList(identifier);
 	}
 
 	/**
-	 * Fetch metadata of pending messages sent to the {@code xtaIdentifier}.
-	 * This method skips checks but otherwise behaves exactly as {@link #getMessagesMetadata(String)}.
+	 * Fetch metadata of pending messages sent to the {@code xtaIdentifier}. This method skips checks but otherwise behaves exactly as
+	 * {@link #getMessagesMetadata(String)}.
 	 */
-	public XtaMessageMetaDataListing getNextMessagesMetadata(@NotBlank String xtaIdentifier)
+	public XtaMessageMetaDataListing getNextMessagesMetadata(@NotBlank String clientIdentifier)
 			throws XTAWSTechnicalProblemException, PermissionDeniedException {
-		return getStatusList(deriveIdentifier(xtaIdentifier));
+		return getStatusList(deriveIdentifier(clientIdentifier));
 	}
 
 	private XtaMessageMetaDataListing getStatusList(Identifier clientIdentifier) throws XTAWSTechnicalProblemException, PermissionDeniedException {
 		return service.getStatusList(clientIdentifier, config.getMaxListItems());
 	}
 
+	public XtaMessage getMessage(@NotBlank String clientIdentifier, @NotBlank String messageId)
+			throws XTAWSTechnicalProblemException, PermissionDeniedException, InvalidMessageIDException {
+		return service.getMessage(messageId, deriveIdentifier(clientIdentifier));
+	}
+
+	public void close(@NotBlank String clientIdentifier, @NotBlank String messageId)
+			throws XTAWSTechnicalProblemException, PermissionDeniedException, InvalidMessageIDException {
+		service.close(messageId, deriveIdentifier(clientIdentifier));
+	}
+
 	Identifier deriveIdentifier(String xtaIdentifier) {
 		return config.getClientIdentifiers().stream()
 				.filter(id -> id.value().equals(xtaIdentifier))
 				.findFirst()
 				.orElseThrow(() -> new IllegalArgumentException("Unknown identifier: " + xtaIdentifier));
 	}
-
-	public XtaMessage getMessage(String messageId) {
-		throw new NotImplementedException("");
-	}
-
-	public void close(@NotBlank String messageId) {
-		throw new NotImplementedException("");
-	}
 }
diff --git a/src/test/java/de/ozgcloud/xta/client/XtaClientTest.java b/src/test/java/de/ozgcloud/xta/client/XtaClientTest.java
index 1717aefea7e5f32c4288c01f8c8e304e858e0024..45e6a1ffd56d409b891e14555a3bb0f9fa7d586f 100644
--- a/src/test/java/de/ozgcloud/xta/client/XtaClientTest.java
+++ b/src/test/java/de/ozgcloud/xta/client/XtaClientTest.java
@@ -1,5 +1,6 @@
 package de.ozgcloud.xta.client;
 
+import static de.ozgcloud.xta.client.factory.MessageMetaDataTestFactory.*;
 import static de.ozgcloud.xta.client.factory.XtaClientConfigTestFactory.*;
 import static org.assertj.core.api.Assertions.*;
 import static org.mockito.Mockito.*;
@@ -18,6 +19,7 @@ import org.mockito.junit.jupiter.MockitoExtension;
 
 import de.ozgcloud.xta.client.config.XtaClientConfig;
 import de.ozgcloud.xta.client.core.WrappedXtaService;
+import de.ozgcloud.xta.client.model.XtaMessage;
 import de.ozgcloud.xta.client.model.XtaMessageMetaDataListing;
 import lombok.SneakyThrows;
 
@@ -119,4 +121,40 @@ class XtaClientTest {
 		}
 	}
 
+	@DisplayName("get message")
+	@Nested
+	class TestGetMessage {
+
+		@Mock
+		XtaMessage xtaMessage;
+
+		@DisplayName("should return")
+		@Test
+		@SneakyThrows
+		void shouldReturn() {
+			doReturn(SELF_IDENTIFIER).when(client).deriveIdentifier(SELF_IDENTIFIER_VALUE);
+			when(service.getMessage(MESSAGE_ID, SELF_IDENTIFIER)).thenReturn(xtaMessage);
+
+			var result = client.getMessage(SELF_IDENTIFIER_VALUE, MESSAGE_ID);
+
+			assertThat(result).isEqualTo(xtaMessage);
+		}
+	}
+
+	@DisplayName("close")
+	@Nested
+	class TestClose {
+
+		@DisplayName("should call close")
+		@Test
+		@SneakyThrows
+		void shouldCallClose() {
+			doReturn(SELF_IDENTIFIER).when(client).deriveIdentifier(SELF_IDENTIFIER_VALUE);
+
+			client.close(SELF_IDENTIFIER_VALUE, MESSAGE_ID);
+
+			verify(service).close(MESSAGE_ID, SELF_IDENTIFIER);
+		}
+	}
+
 }
\ No newline at end of file