diff --git a/api-lib-core/pom.xml b/api-lib-core/pom.xml
index 18560a62b52216ef90809ed4c2e5ed1e8bc04533..56ebb9a7ce8f9a42aa7974ce3b6bc9905578d7b8 100644
--- a/api-lib-core/pom.xml
+++ b/api-lib-core/pom.xml
@@ -31,6 +31,10 @@
 			<groupId>de.itvsh.ozg.pluto</groupId>
 			<artifactId>pluto-interface</artifactId>
 		</dependency>
+		<dependency>
+			<groupId>de.itvsh.ozg.pluto</groupId>
+			<artifactId>pluto-utils</artifactId>
+		</dependency>
 
 		<!--spring -->
 		<dependency>
diff --git a/api-lib-core/src/main/java/de/ozgcloud/apilib/common/command/OzgCloudCommand.java b/api-lib-core/src/main/java/de/ozgcloud/apilib/common/command/OzgCloudCommand.java
new file mode 100644
index 0000000000000000000000000000000000000000..367bd31068acc2d36a5de76805783a7ffa2c17ea
--- /dev/null
+++ b/api-lib-core/src/main/java/de/ozgcloud/apilib/common/command/OzgCloudCommand.java
@@ -0,0 +1,46 @@
+package de.ozgcloud.apilib.common.command;
+
+import java.time.ZonedDateTime;
+import java.util.Map;
+
+import de.itvsh.kop.common.datatype.StringBasedValue;
+import de.ozgcloud.apilib.user.OzgCloudUserId;
+import de.ozgcloud.apilib.vorgang.OzgCloudVorgangId;
+import lombok.Builder;
+import lombok.Getter;
+
+@Builder
+@Getter
+public class OzgCloudCommand {
+
+	private OzgCloudCommandId id;
+
+	private OzgCloudVorgangId vorgangId;
+	/**
+	 * Id of the entity, that is referenced by this command to be processed. That
+	 * can be any Id, for example vorgangId, fileId and so on.
+	 */
+	private StringBasedValue relationId;
+	/**
+	 * Version of the entity, to be processed by this command. Used for optimistic
+	 * locking.
+	 */
+	private Long relationVersion;
+
+	private String order;
+
+	private ZonedDateTime createdAt;
+	private ZonedDateTime finishedAt;
+
+	private OzgCloudUserId createdBy;
+	private OzgCloudCommandStatus status;
+
+	private Map<String, Object> bodyObject;
+	/**
+	 * @deprecated use {@link OzgCloudCommand#bodyObject}
+	 */
+	@Deprecated(since = "0.2.0", forRemoval = true)
+	private Map<String, String> body;
+
+	private String errorMessage;
+}
diff --git a/api-lib-core/src/main/java/de/ozgcloud/apilib/common/command/OzgCloudCommandId.java b/api-lib-core/src/main/java/de/ozgcloud/apilib/common/command/OzgCloudCommandId.java
new file mode 100644
index 0000000000000000000000000000000000000000..333a50bd0d55a2f72bf9ffc7249c00adda596b1e
--- /dev/null
+++ b/api-lib-core/src/main/java/de/ozgcloud/apilib/common/command/OzgCloudCommandId.java
@@ -0,0 +1,17 @@
+package de.ozgcloud.apilib.common.command;
+
+import org.mapstruct.ObjectFactory;
+
+import de.itvsh.kop.common.datatype.StringBasedValue;
+
+public class OzgCloudCommandId extends StringBasedValue {
+
+	OzgCloudCommandId(String commandId) {
+		super(commandId);
+	}
+
+	@ObjectFactory
+	public static OzgCloudCommandId from(String commandId) {
+		return new OzgCloudCommandId(commandId);
+	}
+}
diff --git a/api-lib-core/src/main/java/de/ozgcloud/apilib/common/command/OzgCloudCommandService.java b/api-lib-core/src/main/java/de/ozgcloud/apilib/common/command/OzgCloudCommandService.java
new file mode 100644
index 0000000000000000000000000000000000000000..a1bbbc1a19557818a624b29a38c207dbcf40f70e
--- /dev/null
+++ b/api-lib-core/src/main/java/de/ozgcloud/apilib/common/command/OzgCloudCommandService.java
@@ -0,0 +1,6 @@
+package de.ozgcloud.apilib.common.command;
+
+public interface OzgCloudCommandService {
+
+	public OzgCloudCommand createAndWaitUntilDone(OzgCloudCommand commandToCreate);
+}
diff --git a/api-lib-core/src/main/java/de/ozgcloud/apilib/common/command/OzgCloudCommandStatus.java b/api-lib-core/src/main/java/de/ozgcloud/apilib/common/command/OzgCloudCommandStatus.java
new file mode 100644
index 0000000000000000000000000000000000000000..b3538711109bb6e26756cba9a56a3cc59c4aed09
--- /dev/null
+++ b/api-lib-core/src/main/java/de/ozgcloud/apilib/common/command/OzgCloudCommandStatus.java
@@ -0,0 +1,20 @@
+package de.ozgcloud.apilib.common.command;
+
+import de.itvsh.kop.common.datatype.StringBasedValue;
+
+public class OzgCloudCommandStatus extends StringBasedValue {
+
+	public static final OzgCloudCommandStatus PENDING = from("PENDING");
+	public static final OzgCloudCommandStatus FINISHED = from("FINISHED");
+	public static final OzgCloudCommandStatus ERROR = from("ERROR");
+	public static final OzgCloudCommandStatus REVOKE_PENDING = from("REVOKE_PENDING");
+	public static final OzgCloudCommandStatus REVOKED = from("REVOKED");
+
+	OzgCloudCommandStatus(String status) {
+		super(status);
+	}
+
+	public static OzgCloudCommandStatus from(String status) {
+		return new OzgCloudCommandStatus(status);
+	}
+}
diff --git a/api-lib-core/src/main/java/de/ozgcloud/apilib/common/command/grpc/GrpcOzgCloudCommandService.java b/api-lib-core/src/main/java/de/ozgcloud/apilib/common/command/grpc/GrpcOzgCloudCommandService.java
new file mode 100644
index 0000000000000000000000000000000000000000..9c485e77d6e42eb06f2d8b0f4981cf2bc275d768
--- /dev/null
+++ b/api-lib-core/src/main/java/de/ozgcloud/apilib/common/command/grpc/GrpcOzgCloudCommandService.java
@@ -0,0 +1,37 @@
+package de.ozgcloud.apilib.common.command.grpc;
+
+import de.itvsh.kop.pluto.common.grpc.GrpcObjectMapper;
+import de.itvsh.ozg.pluto.grpc.command.CommandServiceGrpc.CommandServiceBlockingStub;
+import de.itvsh.ozg.pluto.grpc.command.GrpcCreateCommandRequest;
+import de.ozgcloud.apilib.common.command.OzgCloudCommand;
+import de.ozgcloud.apilib.common.command.OzgCloudCommandService;
+import lombok.RequiredArgsConstructor;
+import net.devh.boot.grpc.client.inject.GrpcClient;
+
+@RequiredArgsConstructor
+public class GrpcOzgCloudCommandService implements OzgCloudCommandService {
+
+	@GrpcClient("command-manager")
+	private final CommandServiceBlockingStub commandServiceStub;
+
+	private GrpcObjectMapper objectMapper;
+
+	@Override
+	public OzgCloudCommand createAndWaitUntilDone(OzgCloudCommand commandToCreate) {
+		var command = create(commandToCreate);
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	OzgCloudCommand create(OzgCloudCommand commandToCreate) {
+		commandServiceStub.createCommand(buildCreateCommandRequest(commandToCreate));
+		return null;
+	}
+
+	GrpcCreateCommandRequest buildCreateCommandRequest(OzgCloudCommand commandToCreate) {
+		return GrpcCreateCommandRequest.newBuilder()
+				.build();
+
+	}
+
+}
diff --git a/api-lib-core/src/main/java/de/ozgcloud/apilib/common/command/grpc/OzgCloudCommandMapper.java b/api-lib-core/src/main/java/de/ozgcloud/apilib/common/command/grpc/OzgCloudCommandMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..3cb2b4eebfc304379ce434df4baeea630118b201
--- /dev/null
+++ b/api-lib-core/src/main/java/de/ozgcloud/apilib/common/command/grpc/OzgCloudCommandMapper.java
@@ -0,0 +1,46 @@
+package de.ozgcloud.apilib.common.command.grpc;
+
+import java.util.Objects;
+import java.util.Optional;
+
+import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
+
+import de.itvsh.kop.common.datatype.StringBasedValue;
+import de.itvsh.kop.pluto.common.grpc.GrpcObjectMapper;
+import de.itvsh.ozg.pluto.grpc.command.GrpcCreateCommandRequest;
+import de.ozgcloud.apilib.common.command.OzgCloudCommand;
+
+@Mapper(uses = GrpcObjectMapper.class)
+public interface OzgCloudCommandMapper {
+
+	@Mapping(target = "mergeFrom", ignore = true)
+	@Mapping(target = "clearField", ignore = true)
+	@Mapping(target = "clearOneof", ignore = true)
+	@Mapping(target = "mergeBodyObj", ignore = true)
+	@Mapping(target = "mergeCallContext", ignore = true)
+	@Mapping(target = "mergeRedirectRequest", ignore = true)
+	@Mapping(target = "mergeUnknownFields", ignore = true)
+	@Mapping(target = "removeBody", ignore = true)
+	@Mapping(target = "callContext", ignore = true)
+
+	@Mapping(target = "orderStringBytes", ignore = true)
+	@Mapping(target = "order", ignore = true)
+	@Mapping(target = "orderValue", ignore = true)
+	@Mapping(target = "redirectRequest", ignore = true)
+	@Mapping(target = "relationIdBytes", ignore = true)
+	@Mapping(target = "unknownFields", ignore = true)
+	@Mapping(target = "vorgangIdBytes", ignore = true)
+	@Mapping(target = "allFields", ignore = true)
+	@Mapping(target = "bodyBuilderList", ignore = true)
+	@Mapping(target = "bodyList", ignore = true)
+	@Mapping(target = "bodyOrBuilderList", ignore = true)
+
+	@Mapping(target = "bodyObj", source = "bodyObject")
+	@Mapping(target = "orderString", source = "order")
+	GrpcCreateCommandRequest toCreateRequest(OzgCloudCommand command);
+
+	default String toString(StringBasedValue stringBasedValue) {
+		return Optional.ofNullable(stringBasedValue).map(Objects::toString).orElse(null);
+	}
+}
diff --git a/api-lib-core/src/main/java/de/ozgcloud/apilib/errorhandling/NotFoundException.java b/api-lib-core/src/main/java/de/ozgcloud/apilib/common/errorhandling/NotFoundException.java
similarity index 86%
rename from api-lib-core/src/main/java/de/ozgcloud/apilib/errorhandling/NotFoundException.java
rename to api-lib-core/src/main/java/de/ozgcloud/apilib/common/errorhandling/NotFoundException.java
index d95b83498f7a01bcaa2e1fb053bb87faeb86dc74..a9ab13cdbf4cea399d61e90e2ab8381d7579bbfb 100644
--- a/api-lib-core/src/main/java/de/ozgcloud/apilib/errorhandling/NotFoundException.java
+++ b/api-lib-core/src/main/java/de/ozgcloud/apilib/common/errorhandling/NotFoundException.java
@@ -1,4 +1,4 @@
-package de.ozgcloud.apilib.errorhandling;
+package de.ozgcloud.apilib.common.errorhandling;
 
 import de.itvsh.kop.common.datatype.StringBasedValue;
 
diff --git a/api-lib-core/src/main/java/de/ozgcloud/apilib/file/grpc/GrpcOzgCloudFileService.java b/api-lib-core/src/main/java/de/ozgcloud/apilib/file/grpc/GrpcOzgCloudFileService.java
index 5d6b8adda071fba5e9ace16e0da8751b87ac2815..b74ca3dbe7a7635c43b307e75726c8fa995338e2 100644
--- a/api-lib-core/src/main/java/de/ozgcloud/apilib/file/grpc/GrpcOzgCloudFileService.java
+++ b/api-lib-core/src/main/java/de/ozgcloud/apilib/file/grpc/GrpcOzgCloudFileService.java
@@ -19,7 +19,7 @@ import de.itvsh.ozg.pluto.grpc.binaryFile.GrpcBinaryFilesRequest;
 import de.itvsh.ozg.pluto.grpc.binaryFile.GrpcFindFilesResponse;
 import de.itvsh.ozg.pluto.grpc.binaryFile.GrpcGetBinaryFileDataRequest;
 import de.itvsh.ozg.pluto.grpc.file.GrpcOzgFile;
-import de.ozgcloud.apilib.errorhandling.NotFoundException;
+import de.ozgcloud.apilib.common.errorhandling.NotFoundException;
 import de.ozgcloud.apilib.file.OzgCloudFile;
 import de.ozgcloud.apilib.file.OzgCloudFileId;
 import de.ozgcloud.apilib.file.OzgCloudFileService;
diff --git a/api-lib-core/src/test/java/de/ozgcloud/apilib/common/command/grpc/GrpcCreateCommandRequestTestFactory.java b/api-lib-core/src/test/java/de/ozgcloud/apilib/common/command/grpc/GrpcCreateCommandRequestTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..b187ee71d31d5db0b7cef252a85d203bf29a4845
--- /dev/null
+++ b/api-lib-core/src/test/java/de/ozgcloud/apilib/common/command/grpc/GrpcCreateCommandRequestTestFactory.java
@@ -0,0 +1,25 @@
+package de.ozgcloud.apilib.common.command.grpc;
+
+import static de.ozgcloud.apilib.common.command.grpc.OzgCloudCommandTestFactory.*;
+
+import de.itvsh.ozg.pluto.common.GrpcObject;
+import de.itvsh.ozg.pluto.common.GrpcProperty;
+import de.itvsh.ozg.pluto.grpc.command.GrpcCreateCommandRequest;
+import de.ozgcloud.apilib.vorgang.OzgCloudVorgangTestFactory;
+
+public class GrpcCreateCommandRequestTestFactory {
+
+	public static GrpcCreateCommandRequest create() {
+		return createBuilder().build();
+	}
+
+	public static GrpcCreateCommandRequest.Builder createBuilder() {
+		return GrpcCreateCommandRequest.newBuilder()
+				.setVorgangId(OzgCloudVorgangTestFactory.ID.toString())
+				.setRelationId(RELATION_ID.toString())
+				.setRelationVersion(RELATION_VERSION)
+				.setOrderString(ORDER)
+				.setBodyObj(GrpcObject.newBuilder().addProperty(
+						GrpcProperty.newBuilder().setName(BODY_FIELD_NAME).addValue(BODY_FIELD_VALUE.toString()).build()));
+	}
+}
diff --git a/api-lib-core/src/test/java/de/ozgcloud/apilib/common/command/grpc/GrpcOzgCloudCommandServiceTest.java b/api-lib-core/src/test/java/de/ozgcloud/apilib/common/command/grpc/GrpcOzgCloudCommandServiceTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..1b0db3f057ce222f7b8f408d72e904e4e5a2f297
--- /dev/null
+++ b/api-lib-core/src/test/java/de/ozgcloud/apilib/common/command/grpc/GrpcOzgCloudCommandServiceTest.java
@@ -0,0 +1,60 @@
+package de.ozgcloud.apilib.common.command.grpc;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+
+import de.itvsh.ozg.pluto.grpc.command.CommandServiceGrpc.CommandServiceBlockingStub;
+import de.ozgcloud.apilib.common.command.OzgCloudCommand;
+
+class GrpcOzgCloudCommandServiceTest {
+
+	@Spy
+	@InjectMocks
+	private GrpcOzgCloudCommandService service;
+
+	@Mock
+	private CommandServiceBlockingStub serviceStub;
+
+	@Nested
+	class TestCreateAndWaitUntilDone {
+		@Test
+		void shouldCallCreate() {
+			OzgCloudCommand command = OzgCloudCommandTestFactory.create();
+
+			service.createAndWaitUntilDone(command);
+
+			verify(service).create(command);
+		}
+
+		@Nested
+		class BuildCreateCommandRequest {
+			@Test
+			void shouldBuildCommand() {
+				var request = service.buildCreateCommandRequest(OzgCloudCommandTestFactory.create());
+
+				assertThat(request).usingRecursiveComparison().isEqualTo(GrpcCreateCommandRequestTestFactory.create());
+			}
+		}
+
+		@Nested
+		class Create {
+			@Test
+			void shouldCallStub() {
+				var request = GrpcCreateCommandRequestTestFactory.create();
+				doReturn(request).when(service).buildCreateCommandRequest(any());
+
+				service.create(OzgCloudCommandTestFactory.create());
+
+				verify(serviceStub).createCommand(notNull());
+			}
+		}
+	}
+
+}
diff --git a/api-lib-core/src/test/java/de/ozgcloud/apilib/common/command/grpc/OzgCloudCommandMapperTest.java b/api-lib-core/src/test/java/de/ozgcloud/apilib/common/command/grpc/OzgCloudCommandMapperTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..9fc872594a49d17be32619be4ff1e1c21977b4d3
--- /dev/null
+++ b/api-lib-core/src/test/java/de/ozgcloud/apilib/common/command/grpc/OzgCloudCommandMapperTest.java
@@ -0,0 +1,23 @@
+package de.ozgcloud.apilib.common.command.grpc;
+
+import static org.assertj.core.api.Assertions.*;
+
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mapstruct.factory.Mappers;
+
+class OzgCloudCommandMapperTest {
+
+	private OzgCloudCommandMapper mapper = Mappers.getMapper(OzgCloudCommandMapper.class);
+
+	@Nested
+	class TestToCreateRequest {
+		@Test
+		void shouldMapFromCommand() {
+			var request = mapper.toCreateRequest(OzgCloudCommandTestFactory.create());
+
+			assertThat(request).usingRecursiveComparison().isEqualTo(GrpcCreateCommandRequestTestFactory.create());
+		}
+	}
+
+}
diff --git a/api-lib-core/src/test/java/de/ozgcloud/apilib/common/command/grpc/OzgCloudCommandTestFactory.java b/api-lib-core/src/test/java/de/ozgcloud/apilib/common/command/grpc/OzgCloudCommandTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..fdc28f82aa20897d154bec1d41fb221a186df9a0
--- /dev/null
+++ b/api-lib-core/src/test/java/de/ozgcloud/apilib/common/command/grpc/OzgCloudCommandTestFactory.java
@@ -0,0 +1,51 @@
+package de.ozgcloud.apilib.common.command.grpc;
+
+import java.time.ZonedDateTime;
+import java.util.Map;
+import java.util.UUID;
+
+import de.itvsh.kop.common.datatype.StringBasedValue;
+import de.ozgcloud.apilib.common.command.OzgCloudCommand;
+import de.ozgcloud.apilib.common.command.OzgCloudCommandId;
+import de.ozgcloud.apilib.common.command.OzgCloudCommandStatus;
+import de.ozgcloud.apilib.file.OzgCloudFileTestFactory;
+import de.ozgcloud.apilib.vorgang.OzgCloudVorgangId;
+import de.ozgcloud.apilib.vorgang.OzgCloudVorgangTestFactory;
+
+public class OzgCloudCommandTestFactory {
+
+	public static final OzgCloudCommandId ID = OzgCloudCommandId.from(UUID.randomUUID().toString());
+
+	public static final OzgCloudVorgangId VORGANG_ID = OzgCloudVorgangTestFactory.ID;
+	public static final StringBasedValue RELATION_ID = OzgCloudFileTestFactory.ID;
+	public static final long RELATION_VERSION = 42;
+
+	public static final String ORDER = "CREATE_NOTE";
+	public static final OzgCloudCommandStatus STATUS = OzgCloudCommandStatus.FINISHED;
+
+	private static final String CREATED_AT_STR = "2023-08-18T13:54:10Z";
+	private static final ZonedDateTime CREATED_AT = ZonedDateTime.parse(CREATED_AT_STR);
+	private static final String FINISHED_AT_STR = "2023-08-18T13:55:10Z";
+	private static final ZonedDateTime FINISHED_AT = ZonedDateTime.parse(FINISHED_AT_STR);
+
+	public static final String BODY_FIELD_NAME = "FIELD";
+	public static final Long BODY_FIELD_VALUE = 42L;
+	private static final Map<String, Object> BODY = Map.of(BODY_FIELD_NAME, BODY_FIELD_VALUE);
+
+	public static OzgCloudCommand create() {
+		return createBuilder().build();
+	}
+
+	public static OzgCloudCommand.OzgCloudCommandBuilder createBuilder() {
+		return OzgCloudCommand.builder()
+				.id(ID)
+				.vorgangId(VORGANG_ID)
+				.relationId(RELATION_ID)
+				.relationVersion(RELATION_VERSION)
+				.order(ORDER)
+				.status(STATUS)
+				.createdAt(CREATED_AT)
+				.finishedAt(FINISHED_AT)
+				.bodyObject(BODY);
+	}
+}
diff --git a/api-lib-core/src/test/java/de/ozgcloud/apilib/file/grpc/GrpcOzgCloudFileServiceTest.java b/api-lib-core/src/test/java/de/ozgcloud/apilib/file/grpc/GrpcOzgCloudFileServiceTest.java
index ddc2304030486d3a6d5bda8b08f6e9b8fa08aff5..68302989302c8094c1cab7ca7a222abd64ab64ef 100644
--- a/api-lib-core/src/test/java/de/ozgcloud/apilib/file/grpc/GrpcOzgCloudFileServiceTest.java
+++ b/api-lib-core/src/test/java/de/ozgcloud/apilib/file/grpc/GrpcOzgCloudFileServiceTest.java
@@ -14,7 +14,7 @@ import org.mockito.Spy;
 
 import de.itvsh.ozg.pluto.grpc.binaryFile.BinaryFileServiceGrpc.BinaryFileServiceBlockingStub;
 import de.itvsh.ozg.pluto.grpc.binaryFile.GrpcFindFilesResponse;
-import de.ozgcloud.apilib.errorhandling.NotFoundException;
+import de.ozgcloud.apilib.common.errorhandling.NotFoundException;
 import de.ozgcloud.apilib.file.OzgCloudFileTestFactory;
 
 class GrpcOzgCloudFileServiceTest {
diff --git a/pom.xml b/pom.xml
index d31fe02fad15f0650928daebf2a395762ddddd32..d27fbb956d0761e4614d96fbf85ff11dee6c59da 100644
--- a/pom.xml
+++ b/pom.xml
@@ -7,8 +7,7 @@
 	<parent>
 		<groupId>de.itvsh.kop.common</groupId>
 		<artifactId>kop-common-dependencies</artifactId>
-<!--		<version>2.3.0-SNAPSHOT</version>-->
-		<version>2.3.0-20230726.100032-5</version>
+		<version>2.3.0-SNAPSHOT</version>
 		<relativePath /> <!-- lookup parent from repository -->
 	</parent>