diff --git a/src/main/java/de/ozgcloud/xta/client/XtaClient.java b/src/main/java/de/ozgcloud/xta/client/XtaClient.java
index ddc83b23a771ff8bf3b0ac711ee9e14d2994e1a9..36075b3ae12624cc8a29c70c4c1a1ec7a0f4b44f 100644
--- a/src/main/java/de/ozgcloud/xta/client/XtaClient.java
+++ b/src/main/java/de/ozgcloud/xta/client/XtaClient.java
@@ -4,8 +4,8 @@ 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.XtaMessageId;
 import de.ozgcloud.xta.client.model.XtaMessageMetaDataAndHeader;
 import genv3.de.xoev.transport.xta.x211.PermissionDeniedException;
 import genv3.de.xoev.transport.xta.x211.XTAWSTechnicalProblemException;
@@ -24,24 +24,29 @@ public class XtaClient {
 
 	public XtaMessageMetaDataAndHeader getMessagesMetadata(String xtaIdentifier)
 			throws XTAWSTechnicalProblemException, PermissionDeniedException {
-		service.checkAccountActive(xtaIdentifier);
-		return getStatusList(xtaIdentifier);
+		var clientIdentifier = deriveIdentifier(xtaIdentifier);
+		service.checkAccountActive(clientIdentifier);
+		return getStatusList(clientIdentifier);
 	}
 
 	public XtaMessageMetaDataAndHeader getNextMessagesMetadata(String xtaIdentifier)
 			throws XTAWSTechnicalProblemException, PermissionDeniedException {
-		return getStatusList(xtaIdentifier);
+		return getStatusList(deriveIdentifier(xtaIdentifier));
 	}
 
-	private XtaMessageMetaDataAndHeader getStatusList(String xtaIdentifier) throws XTAWSTechnicalProblemException, PermissionDeniedException {
-		return service.getStatusList(xtaIdentifier, config.getMaxListItems());
+	private XtaMessageMetaDataAndHeader getStatusList(Identifier clientIdentifier) throws XTAWSTechnicalProblemException, PermissionDeniedException {
+		return service.getStatusList(clientIdentifier, config.getMaxListItems());
 	}
 
-	public XtaMessage getMessage(XtaMessageId messageId) {
+	Identifier deriveIdentifier(String xtaIdentifier) {
+		return Identifier.builder().value(xtaIdentifier).build();
+	}
+
+	public XtaMessage getMessage(String messageId) {
 		throw new NotImplementedException("");
 	}
 
-	public void close(XtaMessageId messageId) {
+	public void close(String messageId) {
 		throw new NotImplementedException("");
 	}
 }
diff --git a/src/main/java/de/ozgcloud/xta/client/core/WebServiceTypeMapper.java b/src/main/java/de/ozgcloud/xta/client/core/WebServiceTypeMapper.java
index 4c9659dd3d19af5216867393a9c9e97987cd9458..1421e3d07b017363b4e4f59ce2f9cacc18eb535e 100644
--- a/src/main/java/de/ozgcloud/xta/client/core/WebServiceTypeMapper.java
+++ b/src/main/java/de/ozgcloud/xta/client/core/WebServiceTypeMapper.java
@@ -8,6 +8,7 @@ import org.mapstruct.Mapping;
 import org.mapstruct.Named;
 import org.mapstruct.ReportingPolicy;
 
+import de.ozgcloud.xta.client.model.Identifier;
 import de.ozgcloud.xta.client.model.XtaMessageMetaData;
 import de.ozgcloud.xta.client.model.XtaMessageMetaDataAndHeader;
 import genv3.eu.osci.ws.x2008.x05.transport.MsgBoxResponseType;
@@ -22,15 +23,15 @@ import genv3.eu.osci.ws.x2014.x10.transport.PartyType;
 )
 public interface WebServiceTypeMapper {
 
-	String IDENTIFIER_CATEGORY = "xoev";
+	String IDENTIFIER_TYPE = "xoev";
 
 	@Mapping(target = "securityToken", ignore = true)
-	PartyType mapPartyTypeFromIdentifierString(String identifier);
+	PartyType mapPartyTypeFromIdentifier(Identifier identifier);
 
-	@Mapping(target = "type", ignore = true)
-	@Mapping(target = "name", ignore = true)
-	@Mapping(target = "category", constant = IDENTIFIER_CATEGORY)
-	PartyIdentifierType mapPartyIdentifierTypeFromIdentifierString(String value);
+	@Mapping(target = "type", constant = IDENTIFIER_TYPE)
+	PartyIdentifierType mapPartyIdentifierTypeFromIdentifier(Identifier value);
+
+	Identifier mapIdentifierFromPartyIdentifierType(PartyIdentifierType partyIdentifierType);
 
 	@Mapping(target = "maxListItems", source = "maxListItems")
 	@Mapping(target = "listForm", constant = "MessageMetaData")
@@ -41,8 +42,13 @@ public interface WebServiceTypeMapper {
 	@Mapping(target = "messages", source = "msgStatusListType.messageMetaData")
 	XtaMessageMetaDataAndHeader mapXtaMessageMetaDataAndHeader(MsgStatusListType msgStatusListType, MsgBoxResponseType response);
 
+	@Mapping(target = "service", source = "qualifier.service")
+	@Mapping(target = "businessScenarioCode", source = "qualifier.businessScenario.defined.code")
+	@Mapping(target = "messageTypeCode", source = "qualifier.messageType.code")
+	@Mapping(target = "messageTypePayloadSchema", source = "qualifier.messageType.payloadSchema")
 	@Mapping(target = "messageId", source = "msgIdentification.messageID.value")
-	@Mapping(target = "messageType", source = "qualifier.messageType.code")
+	@Mapping(target = "authorIdentifier", source = "originators.author.identifier")
+	@Mapping(target = "readerIdentifier", source = "destinations.reader.identifier")
 	XtaMessageMetaData mapXtaMessageMetaData(MessageMetaData messageMetaData);
 
 	@Named("mapMoreMessagesAvailable")
diff --git a/src/main/java/de/ozgcloud/xta/client/core/WrappedXtaService.java b/src/main/java/de/ozgcloud/xta/client/core/WrappedXtaService.java
index 09d82e45ae414f58c8d628d0e8482016c14c5872..cc9338aef26273ed5b8a601a67fb1864daeaa1d7 100644
--- a/src/main/java/de/ozgcloud/xta/client/core/WrappedXtaService.java
+++ b/src/main/java/de/ozgcloud/xta/client/core/WrappedXtaService.java
@@ -2,6 +2,8 @@ package de.ozgcloud.xta.client.core;
 
 import jakarta.xml.ws.Holder;
 
+import de.ozgcloud.xta.client.model.Identifier;
+import de.ozgcloud.xta.client.model.XtaMessage;
 import de.ozgcloud.xta.client.model.XtaMessageMetaDataAndHeader;
 import genv3.de.xoev.transport.xta.x211.PermissionDeniedException;
 import genv3.de.xoev.transport.xta.x211.XTAService;
@@ -19,19 +21,23 @@ public class WrappedXtaService {
 	private final XTAService service;
 	private final WebServiceTypeMapper typeMapper;
 
-	public void checkAccountActive(String clientIdentifier) throws XTAWSTechnicalProblemException, PermissionDeniedException {
-		service.getManagementPort().checkAccountActive(typeMapper.mapPartyTypeFromIdentifierString(clientIdentifier));
+	public void checkAccountActive(Identifier clientIdentifier) throws XTAWSTechnicalProblemException, PermissionDeniedException {
+		service.getManagementPort().checkAccountActive(typeMapper.mapPartyTypeFromIdentifier(clientIdentifier));
 	}
 
-	public XtaMessageMetaDataAndHeader getStatusList(String clientIdentifier, int maxListItems)
+	public XtaMessageMetaDataAndHeader getStatusList(Identifier clientIdentifier, int maxListItems)
 			throws XTAWSTechnicalProblemException, PermissionDeniedException {
 		final Holder<MsgBoxResponseType> fetchResponseHeader = new Holder<>();
 		var msgStatusListType = service.getMsgBoxPort().getStatusList(
 				typeMapper.mapMsgBoxStatusListRequestTypeFromMaxListItems(maxListItems),
-				typeMapper.mapPartyTypeFromIdentifierString(clientIdentifier),
+				typeMapper.mapPartyTypeFromIdentifier(clientIdentifier),
 				fetchResponseHeader
 		);
 		return typeMapper.mapXtaMessageMetaDataAndHeader(msgStatusListType, fetchResponseHeader.value);
 	}
 
+	public void sendMessage(XtaMessage message) {
+		// service.getSendXtaPort().sendMessage();
+	}
+
 }
diff --git a/src/main/java/de/ozgcloud/xta/client/model/Identifier.java b/src/main/java/de/ozgcloud/xta/client/model/Identifier.java
new file mode 100644
index 0000000000000000000000000000000000000000..3f7ac425df1182e248454093f6735548934f01be
--- /dev/null
+++ b/src/main/java/de/ozgcloud/xta/client/model/Identifier.java
@@ -0,0 +1,14 @@
+package de.ozgcloud.xta.client.model;
+
+import jakarta.annotation.Nullable;
+import jakarta.validation.constraints.NotEmpty;
+
+import lombok.Builder;
+
+@Builder
+public record Identifier(
+		@Nullable String name,
+		@Nullable String category,
+		@NotEmpty String value
+) {
+}
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 1469b74cb0f3ef6d6ca776081545e14e40ee11ae..8305627d69ffa3d48dd8cc3552680fd0c267cf43 100644
--- a/src/main/java/de/ozgcloud/xta/client/model/XtaFile.java
+++ b/src/main/java/de/ozgcloud/xta/client/model/XtaFile.java
@@ -1,14 +1,14 @@
 package de.ozgcloud.xta.client.model;
 
-import java.io.File;
 import java.math.BigInteger;
 
 import lombok.Builder;
 
 @Builder
-public record XtaFile(File file,
+public record XtaFile(
+		byte[] content,
 		String contentType,
 		String name,
-		BigInteger size) {
-
+		BigInteger size
+) {
 }
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 4d76aaccdc5934a4e58fc43e26f24f294245180a..5fa1865a05ab170ba873b79b4e5f4722913f1533 100644
--- a/src/main/java/de/ozgcloud/xta/client/model/XtaMessage.java
+++ b/src/main/java/de/ozgcloud/xta/client/model/XtaMessage.java
@@ -1,15 +1,13 @@
 package de.ozgcloud.xta.client.model;
 
-import java.util.Collection;
+import java.util.List;
 
 import lombok.Builder;
-import lombok.Getter;
-import lombok.Singular;
 
-@Builder(toBuilder = true)
-@Getter
-public class XtaMessage {
-	private XtaMessageMetaData metaData;
-	@Singular
-	private Collection<XtaFile> messageFiles;
+@Builder
+public record XtaMessage(
+		XtaMessageMetaData metaData,
+		XtaFile messageFile,
+		List<XtaFile> attachments
+) {
 }
diff --git a/src/main/java/de/ozgcloud/xta/client/model/XtaMessageId.java b/src/main/java/de/ozgcloud/xta/client/model/XtaMessageId.java
deleted file mode 100644
index 8c65706171d3a875517cb6161001aadd75b8d56d..0000000000000000000000000000000000000000
--- a/src/main/java/de/ozgcloud/xta/client/model/XtaMessageId.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package de.ozgcloud.xta.client.model;
-
-import de.ozgcloud.common.datatype.StringBasedValue;
-
-public class XtaMessageId extends StringBasedValue {
-
-	public XtaMessageId(String messageId) {
-		super(messageId);
-	}
-
-	public static XtaMessageId from(String messageId) {
-		return new XtaMessageId(messageId);
-	}
-}
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 80f87a24032c615b8e544de8495174f302086a13..47fd5b08f02106bbcd0713f73f43aa5466e482a7 100644
--- a/src/main/java/de/ozgcloud/xta/client/model/XtaMessageMetaData.java
+++ b/src/main/java/de/ozgcloud/xta/client/model/XtaMessageMetaData.java
@@ -4,7 +4,12 @@ import lombok.Builder;
 
 @Builder
 public record XtaMessageMetaData(
+		String service,
+		String businessScenarioCode,
+		String messageTypeCode,
+		String messageTypePayloadSchema,
 		String messageId,
-		String messageType
+		Identifier authorIdentifier,
+		Identifier readerIdentifier
 ) {
 }
diff --git a/src/test/java/de/ozgcloud/xta/client/XtaClientConfigTestFactory.java b/src/test/java/de/ozgcloud/xta/client/XtaClientConfigTestFactory.java
index 9be6dc7caad67fc601d097929cf6c50d5fab708c..1a9e69254eb08ecb70007692c00c43d13ac410dd 100644
--- a/src/test/java/de/ozgcloud/xta/client/XtaClientConfigTestFactory.java
+++ b/src/test/java/de/ozgcloud/xta/client/XtaClientConfigTestFactory.java
@@ -16,11 +16,17 @@ import org.bouncycastle.jce.provider.BouncyCastleProvider;
 import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
 
 import de.ozgcloud.xta.client.config.XtaClientConfig;
+import de.ozgcloud.xta.client.model.Identifier;
 import lombok.SneakyThrows;
 
 public class XtaClientConfigTestFactory {
 
-	public static final String SELF_IDENTIFIER = "selfIdentifier";
+	public static final String SELF_IDENTIFIER_VALUE = "selfIdentifier";
+	public static final Identifier SELF_IDENTIFIER = Identifier.builder()
+			.value(SELF_IDENTIFIER_VALUE)
+			.category("xoev")
+			.name("Generic Name")
+			.build();
 	public static final int MAX_LIST_ITEMS = 10;
 	static final String SELF_IDENTIFIER2 = "selfIdentifier2";
 
@@ -45,7 +51,7 @@ public class XtaClientConfigTestFactory {
 				.managementServiceUrl(MANAGEMENT_PORT_SVC)
 				.sendServiceUrl(SEND_PORT_SVC)
 				.msgBoxServiceUrl(MSG_BOX_PORT_SVC)
-				.clientIdentifiers(List.of(SELF_IDENTIFIER, SELF_IDENTIFIER2))
+				.clientIdentifiers(List.of(SELF_IDENTIFIER_VALUE, SELF_IDENTIFIER2))
 				.maxListItems(MAX_LIST_ITEMS)
 				.logSoapRequests(true)
 				.logSoapResponses(true)
diff --git a/src/test/java/de/ozgcloud/xta/client/XtaClientTest.java b/src/test/java/de/ozgcloud/xta/client/XtaClientTest.java
index 2afffd654ea3755052398571691c49601e6d5e75..9c96be14adc05ab998b98dd7d86bd4364e1a026f 100644
--- a/src/test/java/de/ozgcloud/xta/client/XtaClientTest.java
+++ b/src/test/java/de/ozgcloud/xta/client/XtaClientTest.java
@@ -11,6 +11,7 @@ import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
+import org.mockito.Spy;
 import org.mockito.junit.jupiter.MockitoExtension;
 
 import de.ozgcloud.xta.client.config.XtaClientConfig;
@@ -27,6 +28,7 @@ class XtaClientTest {
 	@Mock
 	private XtaClientConfig config;
 
+	@Spy
 	@InjectMocks
 	private XtaClient client;
 
@@ -40,6 +42,7 @@ class XtaClientTest {
 		@BeforeEach
 		@SneakyThrows
 		void mock() {
+			doReturn(SELF_IDENTIFIER).when(client).deriveIdentifier(SELF_IDENTIFIER_VALUE);
 			when(service.getStatusList(SELF_IDENTIFIER, MAX_LIST_ITEMS)).thenReturn(xtaMessageMetaDataAndHeader);
 			when(config.getMaxListItems()).thenReturn(MAX_LIST_ITEMS);
 		}
@@ -48,7 +51,7 @@ class XtaClientTest {
 		@Test
 		@SneakyThrows
 		void shouldCallCheckAccountActive() {
-			client.getMessagesMetadata(SELF_IDENTIFIER);
+			client.getMessagesMetadata(SELF_IDENTIFIER_VALUE);
 
 			verify(service).checkAccountActive(SELF_IDENTIFIER);
 		}
@@ -57,7 +60,7 @@ class XtaClientTest {
 		@Test
 		@SneakyThrows
 		void shouldReturnGetStatusListResponse() {
-			var result = client.getMessagesMetadata(SELF_IDENTIFIER);
+			var result = client.getMessagesMetadata(SELF_IDENTIFIER_VALUE);
 
 			assertThat(result).isEqualTo(xtaMessageMetaDataAndHeader);
 		}
@@ -74,6 +77,7 @@ class XtaClientTest {
 		@BeforeEach
 		@SneakyThrows
 		void mock() {
+			doReturn(SELF_IDENTIFIER).when(client).deriveIdentifier(SELF_IDENTIFIER_VALUE);
 			when(service.getStatusList(SELF_IDENTIFIER, MAX_LIST_ITEMS)).thenReturn(xtaMessageMetaDataAndHeader);
 			when(config.getMaxListItems()).thenReturn(MAX_LIST_ITEMS);
 		}
@@ -82,10 +86,23 @@ class XtaClientTest {
 		@Test
 		@SneakyThrows
 		void shouldReturnGetStatusListResponse() {
-			var result = client.getNextMessagesMetadata(SELF_IDENTIFIER);
+			var result = client.getNextMessagesMetadata(SELF_IDENTIFIER_VALUE);
 
 			assertThat(result).isEqualTo(xtaMessageMetaDataAndHeader);
 		}
 	}
 
+	@DisplayName("derive identifier")
+	@Nested
+	class TestDeriveIdentifier {
+
+		@DisplayName("should use value")
+		@Test
+		void shouldUseValue() {
+			var result = client.deriveIdentifier(SELF_IDENTIFIER_VALUE);
+
+			assertThat(result.value()).isEqualTo(SELF_IDENTIFIER_VALUE);
+		}
+	}
+
 }
\ No newline at end of file
diff --git a/src/test/java/de/ozgcloud/xta/client/core/WebServiceTypeMapperTest.java b/src/test/java/de/ozgcloud/xta/client/core/WebServiceTypeMapperTest.java
index b4187152d4f5170a8a0b150a13c8b6413ac1f7c9..fb2047fa6ab2382fc8bf40a7c0faf94798ce8ffa 100644
--- a/src/test/java/de/ozgcloud/xta/client/core/WebServiceTypeMapperTest.java
+++ b/src/test/java/de/ozgcloud/xta/client/core/WebServiceTypeMapperTest.java
@@ -16,6 +16,7 @@ import org.mockito.junit.jupiter.MockitoExtension;
 import de.ozgcloud.xta.client.model.XtaMessageMetaData;
 import genv3.eu.osci.ws.x2008.x05.transport.MsgBoxResponseType;
 import genv3.eu.osci.ws.x2008.x05.transport.MsgStatusListType;
+import genv3.eu.osci.ws.x2014.x10.transport.PartyIdentifierType;
 
 @ExtendWith(MockitoExtension.class)
 class WebServiceTypeMapperTest {
@@ -23,24 +24,46 @@ class WebServiceTypeMapperTest {
 	@InjectMocks
 	private WebServiceTypeMapperImpl mapper;
 
-	@DisplayName("map party type from identifier string")
+	@DisplayName("map party type from identifier")
 	@Nested
-	class TestMapPartyTypeFromIdentifierString {
+	class TestMapPartyTypeFromIdentifier {
 
-		@DisplayName("should use identifier")
+		@DisplayName("should use value")
 		@Test
-		void shouldUseIdentifier() {
-			var result = mapper.mapPartyTypeFromIdentifierString(SELF_IDENTIFIER);
+		void shouldUseValue() {
+			var result = mapPartyIdentifier();
 
-			assertThat(result.getIdentifier().getValue()).isEqualTo(SELF_IDENTIFIER);
+			assertThat(result.getValue()).isEqualTo(SELF_IDENTIFIER.value());
 		}
 
-		@DisplayName("should use xoev category")
+		@DisplayName("should use category")
 		@Test
-		void shouldUseXoevCategory() {
-			var result = mapper.mapPartyTypeFromIdentifierString(SELF_IDENTIFIER);
+		void shouldUseCategory() {
+			var result = mapPartyIdentifier();
 
-			assertThat(result.getIdentifier().getCategory()).isEqualTo(IDENTIFIER_CATEGORY);
+			assertThat(result.getCategory()).isEqualTo(SELF_IDENTIFIER.category());
+		}
+
+		@DisplayName("should use name")
+		@Test
+		void shouldUseName() {
+			var result = mapPartyIdentifier();
+
+			assertThat(result.getName()).isEqualTo(SELF_IDENTIFIER.name());
+		}
+
+		@DisplayName("should use type")
+		@Test
+		void shouldUseType() {
+			var result = mapPartyIdentifier();
+
+			assertThat(result.getType()).isEqualTo(IDENTIFIER_TYPE);
+		}
+
+		private PartyIdentifierType mapPartyIdentifier() {
+			var result = mapper.mapPartyTypeFromIdentifier(SELF_IDENTIFIER);
+
+			return result.getIdentifier();
 		}
 	}
 
@@ -111,7 +134,7 @@ class WebServiceTypeMapperTest {
 					msgStatusListType, msgBoxResponseTypeWithPendingMessages);
 
 			var messageTypes = result.messages().stream()
-					.map(XtaMessageMetaData::messageType)
+					.map(XtaMessageMetaData::messageTypeCode)
 					.toList();
 			assertThat(messageTypes).containsExactly(MESSAGE_TYPE, MESSAGE_TYPE2, MESSAGE_TYPE3);
 		}
diff --git a/src/test/java/de/ozgcloud/xta/client/core/WrappedXtaServiceTest.java b/src/test/java/de/ozgcloud/xta/client/core/WrappedXtaServiceTest.java
index 10e58ead107715e7742a80094fa7f1d317dabebd..0d5e8bfce824be55ec6901f7e1140a9e3c74d328 100644
--- a/src/test/java/de/ozgcloud/xta/client/core/WrappedXtaServiceTest.java
+++ b/src/test/java/de/ozgcloud/xta/client/core/WrappedXtaServiceTest.java
@@ -50,7 +50,7 @@ class WrappedXtaServiceTest {
 		@BeforeEach
 		void mock() {
 			when(rawService.getManagementPort()).thenReturn(managementPortType);
-			when(typeMapper.mapPartyTypeFromIdentifierString(SELF_IDENTIFIER)).thenReturn(partyType);
+			when(typeMapper.mapPartyTypeFromIdentifier(SELF_IDENTIFIER)).thenReturn(partyType);
 		}
 
 		@DisplayName("should call raw service method")
@@ -88,7 +88,7 @@ class WrappedXtaServiceTest {
 		@SneakyThrows
 		void mock() {
 			when(rawService.getMsgBoxPort()).thenReturn(msgBoxPortType);
-			when(typeMapper.mapPartyTypeFromIdentifierString(SELF_IDENTIFIER)).thenReturn(partyType);
+			when(typeMapper.mapPartyTypeFromIdentifier(SELF_IDENTIFIER)).thenReturn(partyType);
 			when(typeMapper.mapMsgBoxStatusListRequestTypeFromMaxListItems(MAX_LIST_ITEMS))
 					.thenReturn(msgBoxStatusListRequestType);
 			when(msgBoxPortType.getStatusList(eq(msgBoxStatusListRequestType), eq(partyType), any()))