diff --git a/.gitignore b/.gitignore
index dfef11fec1a6a560e16005d6dab3446ff596505d..7f63988e16bb81c61bdb52555d2c946b19cfacde 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,3 +19,4 @@ goofy-client/apps/coverage/
 
 .attach**
 .factorypath
+.vscode/
diff --git a/api-lib-core/src/main/java/de/ozgcloud/apilib/vorgang/OzgCloudVorgangQuery.java b/api-lib-core/src/main/java/de/ozgcloud/apilib/vorgang/OzgCloudVorgangQuery.java
index 2c405148d9e2e11e41fd75ee439f3ae7f3900013..56135494ebe6adc28d6a6296b5dcb6f1fa6e3eb5 100644
--- a/api-lib-core/src/main/java/de/ozgcloud/apilib/vorgang/OzgCloudVorgangQuery.java
+++ b/api-lib-core/src/main/java/de/ozgcloud/apilib/vorgang/OzgCloudVorgangQuery.java
@@ -1,10 +1,68 @@
 package de.ozgcloud.apilib.vorgang;
 
+import java.util.Collection;
+import java.util.Optional;
+
 import lombok.Builder;
 import lombok.Getter;
+import lombok.Singular;
 
 @Builder
 @Getter
 public class OzgCloudVorgangQuery {
+	@Builder.Default
+	private final Optional<String> organisationsEinheitId = Optional.empty();
+	@Builder.Default
+	private final Optional<FormIdentification> form = Optional.empty();
+	@Builder.Default
+	private final Optional<String> status = Optional.empty();
+	@Builder.Default
+	private final Optional<String> aktenzeichen = Optional.empty();
+
+	@Builder.Default
+	public final Optional<Query> query = Optional.empty();
+
+	@Builder
+	@Getter
+	public static class Query {
+		private final LogicalOperator logicalOperator;
+		@Singular
+		private final Collection<Expression> expressions;
+		private final Query nestedQuery;
+	}
+
+	@Builder
+	@Getter
+	public static class FormIdentification {
+		private String formId;
+		private String formEngineName;
+	}
+
+	public enum LogicalOperator {
+		AND, OR
+	}
+
+	@Builder
+	@Getter
+	public static class Expression {
+		private final String path;
+		private final ComparsionOperator operator;
+		private final Integer operandIntValue;
+		private final Boolean operandBoolValue;
+		private final String operandStringValue;
+
+		public enum ComparsionOperator {
+			GREATER_THEN, // >
+			GREATER_THEN_OR_EQUAL_TO, // >=
+			LESS_THEN, // <
+			LESS_THEN_OR_EQUAL_TO, // <=
+			EQUAL, // =
+			UNEQUAL, // <>
+			IS_NULL,
+			IS_EMPTY,
+			EXISTS,
+			NOT_EXIST;
+		}
 
-}
+	}
+}
\ No newline at end of file
diff --git a/api-lib-core/src/main/java/de/ozgcloud/apilib/vorgang/OzgCloudVorgangService.java b/api-lib-core/src/main/java/de/ozgcloud/apilib/vorgang/OzgCloudVorgangService.java
index d3f5d804237f6fac1226c1dec20533bf3002bcbb..0ee75e8a46671c3989a3e18bc9e7c35c53e9bb4b 100644
--- a/api-lib-core/src/main/java/de/ozgcloud/apilib/vorgang/OzgCloudVorgangService.java
+++ b/api-lib-core/src/main/java/de/ozgcloud/apilib/vorgang/OzgCloudVorgangService.java
@@ -6,6 +6,8 @@ public interface OzgCloudVorgangService {
 
 	public OzgCloudVorgang getById(OzgCloudVorgangId vorgangId);
 
+	public List<OzgCloudVorgangStub> find(OzgCloudVorgangQuery query, Page page);
+
 	public List<OzgCloudVorgangStub> search(String searchString);
 
 	public List<OzgCloudVorgangStub> search(String searchString, Page page);
diff --git a/api-lib-core/src/main/java/de/ozgcloud/apilib/vorgang/dummy/DummyVorgangService.java b/api-lib-core/src/main/java/de/ozgcloud/apilib/vorgang/dummy/DummyVorgangService.java
index fe8c6ffbe19298a823cd46d370a8fe0f98cc4beb..662eeac01d5cce5dd053f56eaff077b2c766f3af 100644
--- a/api-lib-core/src/main/java/de/ozgcloud/apilib/vorgang/dummy/DummyVorgangService.java
+++ b/api-lib-core/src/main/java/de/ozgcloud/apilib/vorgang/dummy/DummyVorgangService.java
@@ -13,6 +13,7 @@ import de.ozgcloud.apilib.vorgang.OzgCloudEingang;
 import de.ozgcloud.apilib.vorgang.OzgCloudVorgang;
 import de.ozgcloud.apilib.vorgang.OzgCloudVorgangHeader;
 import de.ozgcloud.apilib.vorgang.OzgCloudVorgangId;
+import de.ozgcloud.apilib.vorgang.OzgCloudVorgangQuery;
 import de.ozgcloud.apilib.vorgang.OzgCloudVorgangService;
 import de.ozgcloud.apilib.vorgang.OzgCloudVorgangStatus;
 import de.ozgcloud.apilib.vorgang.OzgCloudVorgangStub;
@@ -101,4 +102,9 @@ public class DummyVorgangService implements OzgCloudVorgangService {
 	public List<OzgCloudVorgangStub> search(String searchString, Page page) {
 		return vorgangs;
 	}
+
+	@Override
+	public List<OzgCloudVorgangStub> find(OzgCloudVorgangQuery query, Page page) {
+		return vorgangs;
+	}
 }
diff --git a/api-lib-core/src/main/java/de/ozgcloud/apilib/vorgang/grpc/GrpcOzgCloudVorgangService.java b/api-lib-core/src/main/java/de/ozgcloud/apilib/vorgang/grpc/GrpcOzgCloudVorgangService.java
index d9fbf534b526e5f81ef8148d809879021c2e1625..fb0421f5c3c497cc8580748fcd111a0932218dec 100644
--- a/api-lib-core/src/main/java/de/ozgcloud/apilib/vorgang/grpc/GrpcOzgCloudVorgangService.java
+++ b/api-lib-core/src/main/java/de/ozgcloud/apilib/vorgang/grpc/GrpcOzgCloudVorgangService.java
@@ -6,6 +6,7 @@ import de.ozgcloud.apilib.common.callcontext.OzgCloudCallContextAttachingInterce
 import de.ozgcloud.apilib.common.callcontext.OzgCloudCallContextProvider;
 import de.ozgcloud.apilib.vorgang.OzgCloudVorgang;
 import de.ozgcloud.apilib.vorgang.OzgCloudVorgangId;
+import de.ozgcloud.apilib.vorgang.OzgCloudVorgangQuery;
 import de.ozgcloud.apilib.vorgang.OzgCloudVorgangService;
 import de.ozgcloud.apilib.vorgang.OzgCloudVorgangStub;
 import de.ozgcloud.apilib.vorgang.Page;
@@ -26,6 +27,7 @@ public class GrpcOzgCloudVorgangService implements OzgCloudVorgangService {
 
 	private final OzgCloudVorgangMapper mapper;
 	private final OzgCloudVorgangStubMapper stubMapper;
+	private final OzgCloudVorgangQueryMapper queryMapper;
 
 	private final OzgCloudCallContextProvider contextProvider;
 
@@ -64,6 +66,22 @@ public class GrpcOzgCloudVorgangService implements OzgCloudVorgangService {
 				.build();
 	}
 
+	@Override
+	public List<OzgCloudVorgangStub> find(OzgCloudVorgangQuery query, Page page) {
+		var response = getVorgangServiceStub().findVorgang(buildFindRequest(query, page));
+
+		return response.getVorgangList().stream().map(stubMapper::fromGrpc).toList();
+	}
+
+	GrpcFindVorgangRequest buildFindRequest(OzgCloudVorgangQuery query, Page page) {
+		return GrpcFindVorgangRequest.newBuilder()
+				.setLimit(page.getLimit())
+				.setOffset(page.getOffset())
+				.setQuery(queryMapper.toGrpc(query))
+				.setOrderBy(GrpcOrderBy.CREATED_AT_DESC)
+				.build();
+	}
+
 	VorgangServiceBlockingStub getVorgangServiceStub() {
 		return vorgangServiceStub.withInterceptors(new OzgCloudCallContextAttachingInterceptor(contextProvider));
 	}
diff --git a/api-lib-core/src/main/java/de/ozgcloud/apilib/vorgang/grpc/OzgCloudVorgangQueryMapper.java b/api-lib-core/src/main/java/de/ozgcloud/apilib/vorgang/grpc/OzgCloudVorgangQueryMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..96a696ee9ce7847154863b1c39043a4d5a733440
--- /dev/null
+++ b/api-lib-core/src/main/java/de/ozgcloud/apilib/vorgang/grpc/OzgCloudVorgangQueryMapper.java
@@ -0,0 +1,120 @@
+package de.ozgcloud.apilib.vorgang.grpc;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Optional;
+import java.util.Set;
+
+import org.mapstruct.CollectionMappingStrategy;
+import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
+import org.mapstruct.NullValueCheckStrategy;
+import org.mapstruct.ReportingPolicy;
+
+import de.ozgcloud.apilib.vorgang.OzgCloudVorgangQuery;
+import de.ozgcloud.apilib.vorgang.OzgCloudVorgangQuery.FormIdentification;
+import de.ozgcloud.apilib.vorgang.OzgCloudVorgangQuery.Query;
+import de.ozgcloud.vorgang.common.GrpcQueryOperator;
+import de.ozgcloud.vorgang.vorgang.GrpcLogicalOperator;
+import de.ozgcloud.vorgang.vorgang.GrpcQuery;
+import de.ozgcloud.vorgang.vorgang.GrpcVorgangQueryExpression;
+import de.ozgcloud.vorgang.vorgang.GrpcVorgangQueryExpression.Builder;
+
+@Mapper(collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED, nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS, unmappedTargetPolicy = ReportingPolicy.WARN)
+public interface OzgCloudVorgangQueryMapper {
+
+	static final String FORM_ENGINE_NAME_PATH = "eingangs.header.formEngineName";
+	static final String STATUS_PATH = "status";
+	static final String ORGANISATIONS_EINHEIT_ID_PATH = "eingangs.zustaendigeStelle.organisationseinheitenId";
+	static final String AKTENZEICHEN_PATH = "aktenzeichen";
+	static final String FORM_ID_PATH = "eingangs.header.formId";
+
+	default GrpcQuery toGrpc(OzgCloudVorgangQuery ozgCloudVorgangQuery) {
+		var queryBuilder = mapPropertiesToQuery(ozgCloudVorgangQuery);
+
+		if (queryBuilder.getExpressionsList().isEmpty()) {
+			return ozgCloudVorgangQuery.getQuery().map(this::toQuery)
+					.orElseGet(GrpcQuery::getDefaultInstance);
+		}
+
+		ozgCloudVorgangQuery.getQuery().map(this::toQuery).ifPresent(queryBuilder::setNestedQuery);
+		return queryBuilder.build();
+	}
+
+	default GrpcQuery.Builder mapPropertiesToQuery(OzgCloudVorgangQuery query) {
+		var queryBuilder = GrpcQuery.newBuilder().setLogicalOperator(GrpcLogicalOperator.AND);
+		query.getAktenzeichen().map(this::toAktenzeichenExpression).ifPresent(queryBuilder::addExpressions);
+		query.getForm().map(this::toFormExpressions).ifPresent(queryBuilder::addAllExpressions);
+		query.getStatus().map(this::toStatusExpression).ifPresent(queryBuilder::addExpressions);
+		query.getOrganisationsEinheitId().map(this::toOrganisationsEinheitIdExpression).ifPresent(queryBuilder::addExpressions);
+		return queryBuilder;
+	}
+
+	default GrpcVorgangQueryExpression toAktenzeichenExpression(String aktenzeichen) {
+		return getEqualExpressionBuilder()
+				.setPath(AKTENZEICHEN_PATH)
+				.setOperandStringValue(aktenzeichen)
+				.build();
+	}
+
+	default GrpcVorgangQueryExpression toOrganisationsEinheitIdExpression(String organisationsEinheitId) {
+		return getEqualExpressionBuilder()
+				.setPath(ORGANISATIONS_EINHEIT_ID_PATH)
+				.setOperandStringValue(organisationsEinheitId)
+				.build();
+	}
+
+	default GrpcVorgangQueryExpression toStatusExpression(String status) {
+		return getEqualExpressionBuilder()
+				.setPath(STATUS_PATH)
+				.setOperandStringValue(status)
+				.build();
+	}
+
+	default Set<GrpcVorgangQueryExpression> toFormExpressions(FormIdentification formIdentification) {
+		var expressions = new HashSet<GrpcVorgangQueryExpression>(2);
+		Optional.ofNullable(formIdentification.getFormEngineName())
+				.map(this::toFormEngineNameExpression)
+				.ifPresent(expressions::add);
+		Optional.ofNullable(formIdentification.getFormId())
+				.map(this::toFormIdExpression)
+				.ifPresent(expressions::add);
+		return Collections.unmodifiableSet(expressions);
+	}
+
+	private GrpcVorgangQueryExpression toFormEngineNameExpression(String formEngineName) {
+		return getEqualExpressionBuilder()
+				.setPath(FORM_ENGINE_NAME_PATH)
+				.setOperandStringValue(formEngineName)
+				.build();
+	}
+
+	private GrpcVorgangQueryExpression toFormIdExpression(String formId) {
+		return getEqualExpressionBuilder()
+				.setPath(FORM_ID_PATH)
+				.setOperandStringValue(formId)
+				.build();
+	}
+
+	private Builder getEqualExpressionBuilder() {
+		return GrpcVorgangQueryExpression.newBuilder()
+				.setOperator(GrpcQueryOperator.EQUAL);
+	}
+
+	@Mapping(target = "mergeFrom", ignore = true)
+	@Mapping(target = "clearField", ignore = true)
+	@Mapping(target = "clearOneof", ignore = true)
+	@Mapping(target = "mergeNestedQuery", ignore = true)
+	@Mapping(target = "mergeUnknownFields", ignore = true)
+	@Mapping(target = "removeExpressions", ignore = true)
+	@Mapping(target = "logicalOperatorValue", ignore = true)
+	@Mapping(target = "unknownFields", ignore = true)
+	@Mapping(target = "allFields", ignore = true)
+	@Mapping(target = "expressionsBuilderList", ignore = true)
+	@Mapping(target = "expressionsOrBuilderList", ignore = true)
+	@Mapping(target = "nestedQueryOrBuilder", ignore = true)
+	@Mapping(target = "defaultInstanceForType", ignore = true)
+
+	@Mapping(target = "expressionsList", source = "expressions")
+	GrpcQuery toQuery(Query query);
+}
diff --git a/api-lib-core/src/test/java/de/ozgcloud/apilib/vorgang/ExpressionTestFactory.java b/api-lib-core/src/test/java/de/ozgcloud/apilib/vorgang/ExpressionTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..559af9309cc036548486570468cccddb0a2b75e7
--- /dev/null
+++ b/api-lib-core/src/test/java/de/ozgcloud/apilib/vorgang/ExpressionTestFactory.java
@@ -0,0 +1,26 @@
+package de.ozgcloud.apilib.vorgang;
+
+import com.thedeanda.lorem.LoremIpsum;
+
+import de.ozgcloud.apilib.vorgang.OzgCloudVorgangQuery.Expression;
+import de.ozgcloud.apilib.vorgang.OzgCloudVorgangQuery.Expression.ComparsionOperator;
+import de.ozgcloud.apilib.vorgang.OzgCloudVorgangQuery.Expression.ExpressionBuilder;
+
+public class ExpressionTestFactory {
+
+	public static final int OPERAND_INT_VALUE = (int) (Math.random() * 100);
+	public static final String PATH = LoremIpsum.getInstance().getWords(1);
+	public static final ComparsionOperator OPERATOR = ComparsionOperator.EQUAL;
+
+	public static Expression create() {
+		return createBuilder().build();
+	}
+
+	public static ExpressionBuilder createBuilder() {
+		return Expression.builder()
+				.operator(OPERATOR)
+				.path(PATH)
+				.operandIntValue(OPERAND_INT_VALUE);
+	}
+
+}
diff --git a/api-lib-core/src/test/java/de/ozgcloud/apilib/vorgang/FormIdentificationTestFactory.java b/api-lib-core/src/test/java/de/ozgcloud/apilib/vorgang/FormIdentificationTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..d0ae5abb07e28650a02eccb491b703f7903d8758
--- /dev/null
+++ b/api-lib-core/src/test/java/de/ozgcloud/apilib/vorgang/FormIdentificationTestFactory.java
@@ -0,0 +1,25 @@
+package de.ozgcloud.apilib.vorgang;
+
+import java.util.UUID;
+
+import com.thedeanda.lorem.LoremIpsum;
+
+import de.ozgcloud.apilib.vorgang.OzgCloudVorgangQuery.FormIdentification;
+import de.ozgcloud.apilib.vorgang.OzgCloudVorgangQuery.FormIdentification.FormIdentificationBuilder;
+
+public class FormIdentificationTestFactory {
+
+	public static final String FORM_ENGINE_NAME = LoremIpsum.getInstance().getWords(1);
+	public static final String FORM_ID = UUID.randomUUID().toString();
+
+	public static FormIdentification create() {
+		return createBuilder().build();
+	}
+
+	public static FormIdentificationBuilder createBuilder() {
+		return FormIdentification.builder()
+				.formId(FORM_ID)
+				.formEngineName(FORM_ENGINE_NAME);
+	}
+
+}
diff --git a/api-lib-core/src/test/java/de/ozgcloud/apilib/vorgang/OzgCloudVorgangQueryTestFactory.java b/api-lib-core/src/test/java/de/ozgcloud/apilib/vorgang/OzgCloudVorgangQueryTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..e9b036e0f7aa28841fb994fc8593cd3ce2ed2ec1
--- /dev/null
+++ b/api-lib-core/src/test/java/de/ozgcloud/apilib/vorgang/OzgCloudVorgangQueryTestFactory.java
@@ -0,0 +1,33 @@
+package de.ozgcloud.apilib.vorgang;
+
+import java.util.Optional;
+import java.util.UUID;
+
+import com.thedeanda.lorem.LoremIpsum;
+
+import de.ozgcloud.apilib.vorgang.OzgCloudVorgangQuery.FormIdentification;
+import de.ozgcloud.apilib.vorgang.OzgCloudVorgangQuery.OzgCloudVorgangQueryBuilder;
+import de.ozgcloud.apilib.vorgang.OzgCloudVorgangQuery.Query;
+
+public class OzgCloudVorgangQueryTestFactory {
+
+	public static final Query QUERY = QueryTestFactory.create();
+	public static final String STATUS = LoremIpsum.getInstance().getWords(1);
+	public static final FormIdentification FORM = FormIdentificationTestFactory.create();
+	public static final String AKTENZEICHEN = UUID.randomUUID().toString();
+	public static final String ORGANISATIONS_EINHEIT_ID = UUID.randomUUID().toString();
+
+	public static OzgCloudVorgangQuery create() {
+		return createBuilder()
+				.build();
+	}
+
+	public static OzgCloudVorgangQueryBuilder createBuilder() {
+		return OzgCloudVorgangQuery.builder()
+				.aktenzeichen(Optional.of(AKTENZEICHEN))
+				.form(Optional.of(FORM))
+				.organisationsEinheitId(Optional.of(ORGANISATIONS_EINHEIT_ID))
+				.status(Optional.of(STATUS))
+				.query(Optional.of(QUERY));
+	}
+}
diff --git a/api-lib-core/src/test/java/de/ozgcloud/apilib/vorgang/QueryTestFactory.java b/api-lib-core/src/test/java/de/ozgcloud/apilib/vorgang/QueryTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..113d68eb4c58e72613aba4456e213c8a595d0fdd
--- /dev/null
+++ b/api-lib-core/src/test/java/de/ozgcloud/apilib/vorgang/QueryTestFactory.java
@@ -0,0 +1,23 @@
+package de.ozgcloud.apilib.vorgang;
+
+import de.ozgcloud.apilib.vorgang.OzgCloudVorgangQuery.Expression;
+import de.ozgcloud.apilib.vorgang.OzgCloudVorgangQuery.LogicalOperator;
+import de.ozgcloud.apilib.vorgang.OzgCloudVorgangQuery.Query;
+import de.ozgcloud.apilib.vorgang.OzgCloudVorgangQuery.Query.QueryBuilder;
+
+public class QueryTestFactory {
+
+	public static final LogicalOperator LOGICAL_OPERATOR = LogicalOperator.OR;
+	public static final Expression EXPRESSION = ExpressionTestFactory.create();
+
+	public static Query create() {
+		return createBuilder().build();
+	}
+
+	public static QueryBuilder createBuilder() {
+		return Query.builder()
+				.expression(EXPRESSION)
+				.logicalOperator(LOGICAL_OPERATOR);
+	}
+
+}
diff --git a/api-lib-core/src/test/java/de/ozgcloud/apilib/vorgang/grpc/GrpcFindVorgangRequestTestFactory.java b/api-lib-core/src/test/java/de/ozgcloud/apilib/vorgang/grpc/GrpcFindVorgangRequestTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..eafaa75e0fe50a975aa2de27f093d390e3808b59
--- /dev/null
+++ b/api-lib-core/src/test/java/de/ozgcloud/apilib/vorgang/grpc/GrpcFindVorgangRequestTestFactory.java
@@ -0,0 +1,28 @@
+package de.ozgcloud.apilib.vorgang.grpc;
+
+import de.ozgcloud.vorgang.vorgang.GrpcFindVorgangRequest;
+import de.ozgcloud.vorgang.vorgang.GrpcFindVorgangRequest.Builder;
+import de.ozgcloud.vorgang.vorgang.GrpcFindVorgangRequest.GrpcOrderBy;
+import de.ozgcloud.vorgang.vorgang.GrpcQuery;
+
+public class GrpcFindVorgangRequestTestFactory {
+
+	private static final GrpcOrderBy ORDER_BY = GrpcOrderBy.CREATED_AT_DESC;
+	public static final GrpcQuery QUERY = GrpcQueryTestFactory.create();
+	public static final int LIMIT = 10;
+	public static final int OFFSET = 12;
+
+	public static GrpcFindVorgangRequest create() {
+		return createBuilder()
+				.build();
+	}
+
+	public static Builder createBuilder() {
+		return GrpcFindVorgangRequest.newBuilder()
+				.setLimit(LIMIT)
+				.setOffset(OFFSET)
+				.setQuery(QUERY)
+				.setOrderBy(ORDER_BY);
+	}
+
+}
diff --git a/api-lib-core/src/test/java/de/ozgcloud/apilib/vorgang/grpc/GrpcFindVorgangResponseTestFactory.java b/api-lib-core/src/test/java/de/ozgcloud/apilib/vorgang/grpc/GrpcFindVorgangResponseTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..92112f92c74e81dd4bfda55c01f51a774120be97
--- /dev/null
+++ b/api-lib-core/src/test/java/de/ozgcloud/apilib/vorgang/grpc/GrpcFindVorgangResponseTestFactory.java
@@ -0,0 +1,22 @@
+package de.ozgcloud.apilib.vorgang.grpc;
+
+import de.ozgcloud.vorgang.vorgang.GrpcFindVorgangResponse;
+import de.ozgcloud.vorgang.vorgang.GrpcFindVorgangResponse.Builder;
+import de.ozgcloud.vorgang.vorgang.GrpcVorgangHeader;
+
+public class GrpcFindVorgangResponseTestFactory {
+
+	public static final GrpcVorgangHeader VORGANG_HEADER = GrpcVorgangHeaderTestFactory.create();
+	public static final long TOTAL = 1;
+
+	public static GrpcFindVorgangResponse create() {
+		return createBuilder().build();
+	}
+
+	public static Builder createBuilder() {
+		return GrpcFindVorgangResponse.newBuilder()
+				.setTotal(TOTAL)
+				.addVorgang(VORGANG_HEADER);
+	}
+
+}
diff --git a/api-lib-core/src/test/java/de/ozgcloud/apilib/vorgang/grpc/GrpcOzgCloudVorgangServiceTest.java b/api-lib-core/src/test/java/de/ozgcloud/apilib/vorgang/grpc/GrpcOzgCloudVorgangServiceTest.java
index e93e6d54637aedffdbacb8ca12b010ceaa4253ab..6d6d5d47853cdb2c1b1bb2434eac30a129574004 100644
--- a/api-lib-core/src/test/java/de/ozgcloud/apilib/vorgang/grpc/GrpcOzgCloudVorgangServiceTest.java
+++ b/api-lib-core/src/test/java/de/ozgcloud/apilib/vorgang/grpc/GrpcOzgCloudVorgangServiceTest.java
@@ -4,6 +4,8 @@ import static org.assertj.core.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
 
+import java.util.List;
+
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
@@ -11,7 +13,11 @@ import org.mockito.ArgumentCaptor;
 import org.mockito.Captor;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
+import org.mockito.Spy;
 
+import de.ozgcloud.apilib.vorgang.OzgCloudVorgangQuery;
+import de.ozgcloud.apilib.vorgang.OzgCloudVorgangQueryTestFactory;
+import de.ozgcloud.apilib.vorgang.OzgCloudVorgangStub;
 import de.ozgcloud.apilib.vorgang.OzgCloudVorgangStubTestFactory;
 import de.ozgcloud.apilib.vorgang.OzgCloudVorgangTestFactory;
 import de.ozgcloud.apilib.vorgang.Page;
@@ -24,6 +30,7 @@ import de.ozgcloud.vorgang.vorgang.VorgangServiceGrpc.VorgangServiceBlockingStub
 class GrpcOzgCloudVorgangServiceTest {
 
 	@InjectMocks
+	@Spy
 	private GrpcOzgCloudVorgangService service;
 
 	@Mock
@@ -32,6 +39,8 @@ class GrpcOzgCloudVorgangServiceTest {
 	private OzgCloudVorgangMapper mapper;
 	@Mock
 	private OzgCloudVorgangStubMapper stubMapper;
+	@Mock
+	private OzgCloudVorgangQueryMapper queryMapper;
 
 	@Nested
 	class TestGetById {
@@ -150,4 +159,99 @@ class GrpcOzgCloudVorgangServiceTest {
 		}
 
 	}
+
+	@Nested
+	class TestFind {
+
+		private static final Page PAGE = Page.startPage();
+		private final OzgCloudVorgangQuery query = OzgCloudVorgangQueryTestFactory.create();
+		private final GrpcFindVorgangRequest request = GrpcFindVorgangRequestTestFactory.create();
+		private final GrpcFindVorgangResponse response = GrpcFindVorgangResponseTestFactory.create();
+
+		@Mock
+		private VorgangServiceBlockingStub stubWithInterceptor;
+
+		@BeforeEach
+		void mock() {
+			doReturn(stubWithInterceptor).when(service).getVorgangServiceStub();
+			doReturn(request).when(service).buildFindRequest(query, PAGE);
+			when(stubWithInterceptor.findVorgang(request)).thenReturn(response);
+		}
+
+		@Test
+		void shouldCallGetVorgangServiceStub() {
+			callFind();
+
+			verify(service).getVorgangServiceStub();
+		}
+
+		@Test
+		void shouldBuildFindRequest() {
+			callFind();
+
+			verify(service).buildFindRequest(query, PAGE);
+		}
+
+		@Test
+		void shouldFindVorgang() {
+			callFind();
+
+			verify(stubWithInterceptor).findVorgang(request);
+		}
+
+		@Test
+		void shouldMapResponse() {
+			callFind();
+
+			verify(stubMapper).fromGrpc(GrpcFindVorgangResponseTestFactory.VORGANG_HEADER);
+		}
+
+		@Test
+		void shouldReturnMappedVorgangStubs() {
+			var mappedVorgangStub = OzgCloudVorgangStubTestFactory.create();
+			when(stubMapper.fromGrpc(GrpcFindVorgangResponseTestFactory.VORGANG_HEADER)).thenReturn(mappedVorgangStub);
+
+			var vorgangStubs = callFind();
+
+			assertThat(vorgangStubs).containsExactly(mappedVorgangStub);
+		}
+
+		private List<OzgCloudVorgangStub> callFind() {
+			return service.find(query, PAGE);
+		}
+	}
+
+	@Nested
+	class TestBuildFindRequest {
+
+		private final Page page = Page.builder()
+				.limit(GrpcFindVorgangRequestTestFactory.LIMIT)
+				.offset(GrpcFindVorgangRequestTestFactory.OFFSET)
+				.build();
+
+		private final OzgCloudVorgangQuery ozgCloudVorgangQuery = OzgCloudVorgangQueryTestFactory.create();
+
+		@BeforeEach
+		void mockMapper() {
+			when(queryMapper.toGrpc(ozgCloudVorgangQuery)).thenReturn(GrpcFindVorgangRequestTestFactory.QUERY);
+		}
+
+		@Test
+		void shouldMapToGrpcQuery() {
+			callBuildFindRequest();
+
+			verify(queryMapper).toGrpc(ozgCloudVorgangQuery);
+		}
+
+		@Test
+		void shouldReturnRequest() {
+			var request = callBuildFindRequest();
+
+			assertThat(request).usingRecursiveComparison().isEqualTo(GrpcFindVorgangRequestTestFactory.create());
+		}
+
+		private GrpcFindVorgangRequest callBuildFindRequest() {
+			return service.buildFindRequest(ozgCloudVorgangQuery, page);
+		}
+	}
 }
diff --git a/api-lib-core/src/test/java/de/ozgcloud/apilib/vorgang/grpc/GrpcQueryTestFactory.java b/api-lib-core/src/test/java/de/ozgcloud/apilib/vorgang/grpc/GrpcQueryTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..18c3d1ee41f6539ed9c9c4c4cd415a2910c4bb15
--- /dev/null
+++ b/api-lib-core/src/test/java/de/ozgcloud/apilib/vorgang/grpc/GrpcQueryTestFactory.java
@@ -0,0 +1,23 @@
+package de.ozgcloud.apilib.vorgang.grpc;
+
+import de.ozgcloud.apilib.vorgang.QueryTestFactory;
+import de.ozgcloud.vorgang.vorgang.GrpcLogicalOperator;
+import de.ozgcloud.vorgang.vorgang.GrpcQuery;
+import de.ozgcloud.vorgang.vorgang.GrpcQuery.Builder;
+import de.ozgcloud.vorgang.vorgang.GrpcVorgangQueryExpression;
+
+class GrpcQueryTestFactory {
+
+	private static final GrpcLogicalOperator LOGICAL_OPERATOR = GrpcLogicalOperator.valueOf(QueryTestFactory.LOGICAL_OPERATOR.toString());
+	public static final GrpcVorgangQueryExpression EXPRESSION = GrpcVorgangQueryExpressionTestFactory.create();
+
+	public static GrpcQuery create() {
+		return createBuilder().build();
+	}
+
+	public static Builder createBuilder() {
+		return GrpcQuery.newBuilder()
+				.setLogicalOperator(LOGICAL_OPERATOR)
+				.addExpressions(EXPRESSION);
+	}
+}
diff --git a/api-lib-core/src/test/java/de/ozgcloud/apilib/vorgang/grpc/GrpcVorgangQueryExpressionTestFactory.java b/api-lib-core/src/test/java/de/ozgcloud/apilib/vorgang/grpc/GrpcVorgangQueryExpressionTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..e7e544b2b7b0605993b090a0705fa1f7b5fa8c81
--- /dev/null
+++ b/api-lib-core/src/test/java/de/ozgcloud/apilib/vorgang/grpc/GrpcVorgangQueryExpressionTestFactory.java
@@ -0,0 +1,26 @@
+package de.ozgcloud.apilib.vorgang.grpc;
+
+import de.ozgcloud.apilib.vorgang.ExpressionTestFactory;
+import de.ozgcloud.vorgang.common.GrpcQueryOperator;
+import de.ozgcloud.vorgang.vorgang.GrpcVorgangQueryExpression;
+import de.ozgcloud.vorgang.vorgang.GrpcVorgangQueryExpression.Builder;
+
+public class GrpcVorgangQueryExpressionTestFactory {
+
+	public static final int OPERAND_INT_VALUE = ExpressionTestFactory.OPERAND_INT_VALUE;
+	public static final String PATH = ExpressionTestFactory.PATH;
+	public static final GrpcQueryOperator OPERATOR = GrpcQueryOperator.valueOf(ExpressionTestFactory.OPERATOR.toString());
+
+	public static GrpcVorgangQueryExpression create() {
+		return createBuilder()
+				.build();
+	}
+
+	public static Builder createBuilder() {
+		return GrpcVorgangQueryExpression.newBuilder()
+				.setOperator(OPERATOR)
+				.setPath(PATH)
+				.setOperandIntValue(OPERAND_INT_VALUE);
+	}
+
+}
diff --git a/api-lib-core/src/test/java/de/ozgcloud/apilib/vorgang/grpc/OzgCloudVorgangQueryMapperTest.java b/api-lib-core/src/test/java/de/ozgcloud/apilib/vorgang/grpc/OzgCloudVorgangQueryMapperTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..bcdc22ee4286ea121954f3772080085a2d38279c
--- /dev/null
+++ b/api-lib-core/src/test/java/de/ozgcloud/apilib/vorgang/grpc/OzgCloudVorgangQueryMapperTest.java
@@ -0,0 +1,398 @@
+package de.ozgcloud.apilib.vorgang.grpc;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import java.util.Optional;
+import java.util.Set;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mapstruct.factory.Mappers;
+import org.mockito.Spy;
+
+import de.ozgcloud.apilib.vorgang.FormIdentificationTestFactory;
+import de.ozgcloud.apilib.vorgang.OzgCloudVorgangQuery;
+import de.ozgcloud.apilib.vorgang.OzgCloudVorgangQuery.Query;
+import de.ozgcloud.apilib.vorgang.OzgCloudVorgangQueryTestFactory;
+import de.ozgcloud.apilib.vorgang.QueryTestFactory;
+import de.ozgcloud.vorgang.common.GrpcQueryOperator;
+import de.ozgcloud.vorgang.vorgang.GrpcQuery;
+import de.ozgcloud.vorgang.vorgang.GrpcVorgangQueryExpression;
+
+class OzgCloudVorgangQueryMapperTest {
+
+	@Spy
+	private final OzgCloudVorgangQueryMapper mapper = Mappers.getMapper(OzgCloudVorgangQueryMapper.class);
+
+	@Nested
+	class TestToGrpc {
+
+		@Test
+		void shouldCallMapProperetiesToQuery() {
+			var query = OzgCloudVorgangQueryTestFactory.create();
+
+			mapper.toGrpc(query);
+
+			verify(mapper).mapPropertiesToQuery(query);
+		}
+
+		@Nested
+		class OnNoNestedQuery {
+
+			private final OzgCloudVorgangQuery query = OzgCloudVorgangQueryTestFactory.createBuilder()
+					.query(Optional.empty())
+					.build();
+
+			private final GrpcQuery.Builder queryBuilder = GrpcQueryTestFactory.createBuilder();
+
+			@BeforeEach
+			void mock() {
+				doReturn(queryBuilder).when(mapper).mapPropertiesToQuery(query);
+			}
+
+			@Test
+			void shouldReturnBuiltQuery() {
+				var grpcQuery = mapper.toGrpc(query);
+
+				assertThat(grpcQuery).usingRecursiveComparison().isEqualTo(GrpcQueryTestFactory.create());
+			}
+		}
+
+		@Nested
+		class OnNoProperties {
+			private final OzgCloudVorgangQuery query = OzgCloudVorgangQueryTestFactory.create();
+
+			@BeforeEach
+			void mock() {
+				doReturn(queryBuilder).when(mapper).mapPropertiesToQuery(query);
+			}
+
+			private final GrpcQuery.Builder queryBuilder = GrpcQueryTestFactory.createBuilder()
+					.clearExpressions();
+
+			@Test
+			void shouldMapQueryToGrpcQuery() {
+				mapper.toGrpc(query);
+
+				verify(mapper).toQuery(OzgCloudVorgangQueryTestFactory.QUERY);
+			}
+
+			@Test
+			void shouldReturnMappedQuery() {
+				var mappedQuery = GrpcQueryTestFactory.create();
+				doReturn(mappedQuery).when(mapper).toQuery(OzgCloudVorgangQueryTestFactory.QUERY);
+
+				var grpcQuery = mapper.toGrpc(query);
+
+				assertThat(grpcQuery).isEqualTo(mappedQuery);
+			}
+		}
+
+		@Nested
+		class OnNestedQueryAndProperties {
+
+			private final OzgCloudVorgangQuery query = OzgCloudVorgangQueryTestFactory.create();
+
+			private final GrpcQuery.Builder queryBuilder = GrpcQueryTestFactory.createBuilder();
+
+			@BeforeEach
+			void mock() {
+				doReturn(queryBuilder).when(mapper).mapPropertiesToQuery(query);
+			}
+
+			@Test
+			void shouldCallMapQuery() {
+				mapper.toGrpc(query);
+
+				verify(mapper).toQuery(OzgCloudVorgangQueryTestFactory.QUERY);
+			}
+
+			@Test
+			void shouldReturnGrpcQuery() {
+				var nestedQuery = GrpcQueryTestFactory.create();
+				var expectedQuery = GrpcQueryTestFactory.createBuilder()
+						.setNestedQuery(nestedQuery)
+						.build();
+				doReturn(nestedQuery).when(mapper).toQuery(OzgCloudVorgangQueryTestFactory.QUERY);
+
+				var grpcQuery = mapper.toGrpc(query);
+
+				assertThat(grpcQuery).usingRecursiveComparison().isEqualTo(expectedQuery);
+			}
+
+		}
+
+		@Nested
+		class OnEmptyQuery {
+
+			private final OzgCloudVorgangQuery query = OzgCloudVorgangQuery.builder().build();
+
+			@Test
+			void shouldMapToDefaultGrpcQuery() {
+				var grpcQuery = mapper.toGrpc(query);
+
+				assertThat(grpcQuery).usingRecursiveComparison().isEqualTo(GrpcQuery.getDefaultInstance());
+			}
+		}
+	}
+
+	@Nested
+	class TestMapPropertiesToQuery {
+
+		@Nested
+		class TestForAktenzeichen {
+
+			private final GrpcVorgangQueryExpression aktenzeichenExpression = GrpcVorgangQueryExpressionTestFactory.createBuilder()
+					.setPath(OzgCloudVorgangQueryMapper.AKTENZEICHEN_PATH)
+					.setOperator(GrpcQueryOperator.EQUAL)
+					.setOperandStringValue(OzgCloudVorgangQueryTestFactory.AKTENZEICHEN)
+					.build();
+
+			@Test
+			void shouldCallToAktenzeichenExpression() {
+				mapper.mapPropertiesToQuery(OzgCloudVorgangQueryTestFactory.create());
+
+				verify(mapper).toAktenzeichenExpression(OzgCloudVorgangQueryTestFactory.AKTENZEICHEN);
+			}
+
+			@Test
+			void shouldSetAktenzeichenExpression() {
+				doReturn(aktenzeichenExpression).when(mapper).toAktenzeichenExpression(OzgCloudVorgangQueryTestFactory.AKTENZEICHEN);
+
+				var queryBuidler = mapper.mapPropertiesToQuery(OzgCloudVorgangQueryTestFactory.create());
+
+				assertThat(queryBuidler.getExpressionsList()).contains(aktenzeichenExpression);
+			}
+
+			@Test
+			void shouldNotCallToAktenzeichenExpression() {
+				mapper.mapPropertiesToQuery(OzgCloudVorgangQueryTestFactory.createBuilder().aktenzeichen(Optional.empty()).build());
+
+				verify(mapper, never()).toAktenzeichenExpression(any());
+			}
+		}
+
+		@Nested
+		class TestForOrganisationsEinheitId {
+
+			private final GrpcVorgangQueryExpression organisationsEinheitIdExpression = GrpcVorgangQueryExpressionTestFactory.createBuilder()
+					.setPath(OzgCloudVorgangQueryMapper.ORGANISATIONS_EINHEIT_ID_PATH)
+					.setOperator(GrpcQueryOperator.EQUAL)
+					.setOperandStringValue(OzgCloudVorgangQueryTestFactory.ORGANISATIONS_EINHEIT_ID)
+					.build();
+
+			@Test
+			void shouldCallToOrganisationsEinheitIdExpression() {
+				mapper.mapPropertiesToQuery(OzgCloudVorgangQueryTestFactory.create());
+
+				verify(mapper).toOrganisationsEinheitIdExpression(OzgCloudVorgangQueryTestFactory.ORGANISATIONS_EINHEIT_ID);
+			}
+
+			@Test
+			void shouldSetOrganisationsEinheitIdExpression() {
+				doReturn(organisationsEinheitIdExpression).when(mapper)
+						.toOrganisationsEinheitIdExpression(OzgCloudVorgangQueryTestFactory.ORGANISATIONS_EINHEIT_ID);
+
+				var queryBuidler = mapper.mapPropertiesToQuery(OzgCloudVorgangQueryTestFactory.create());
+
+				assertThat(queryBuidler.getExpressionsList()).contains(organisationsEinheitIdExpression);
+			}
+
+			@Test
+			void shouldNotCallToOrganisationsEinheitIdExpression() {
+				mapper.mapPropertiesToQuery(OzgCloudVorgangQueryTestFactory.createBuilder().organisationsEinheitId(Optional.empty()).build());
+
+				verify(mapper, never()).toOrganisationsEinheitIdExpression(any());
+			}
+		}
+
+		@Nested
+		class TestForForm {
+
+			private final GrpcVorgangQueryExpression formEngineNameExpression = GrpcVorgangQueryExpressionTestFactory.createBuilder()
+					.setPath(OzgCloudVorgangQueryMapper.FORM_ENGINE_NAME_PATH)
+					.setOperator(GrpcQueryOperator.EQUAL)
+					.setOperandStringValue(FormIdentificationTestFactory.FORM_ENGINE_NAME)
+					.build();
+
+			private final Set<GrpcVorgangQueryExpression> formExpressions = Set.of(formEngineNameExpression);
+
+			@Test
+			void shouldCallToFormExpression() {
+				mapper.mapPropertiesToQuery(OzgCloudVorgangQueryTestFactory.create());
+
+				verify(mapper).toFormExpressions(OzgCloudVorgangQueryTestFactory.FORM);
+			}
+
+			@Test
+			void shouldSetFormExpression() {
+				doReturn(formExpressions).when(mapper).toFormExpressions(OzgCloudVorgangQueryTestFactory.FORM);
+
+				var queryBuidler = mapper.mapPropertiesToQuery(OzgCloudVorgangQueryTestFactory.create());
+
+				assertThat(queryBuidler.getExpressionsList()).containsAll(formExpressions);
+			}
+
+			@Test
+			void shouldNotCallToFormExpression() {
+				mapper.mapPropertiesToQuery(OzgCloudVorgangQueryTestFactory.createBuilder().form(Optional.empty()).build());
+
+				verify(mapper, never()).toFormExpressions(any());
+			}
+		}
+
+		@Nested
+		class TestForStatus {
+
+			private final GrpcVorgangQueryExpression statusExpression = GrpcVorgangQueryExpressionTestFactory.createBuilder()
+					.setPath(OzgCloudVorgangQueryMapper.STATUS_PATH)
+					.setOperator(GrpcQueryOperator.EQUAL)
+					.setOperandStringValue(OzgCloudVorgangQueryTestFactory.STATUS)
+					.build();
+
+			@Test
+			void shouldCallToStatusExpression() {
+				mapper.mapPropertiesToQuery(OzgCloudVorgangQueryTestFactory.create());
+
+				verify(mapper).toStatusExpression(OzgCloudVorgangQueryTestFactory.STATUS);
+			}
+
+			@Test
+			void shouldSetStatusExpression() {
+				doReturn(statusExpression).when(mapper)
+						.toStatusExpression(OzgCloudVorgangQueryTestFactory.STATUS);
+
+				var queryBuidler = mapper.mapPropertiesToQuery(OzgCloudVorgangQueryTestFactory.create());
+
+				assertThat(queryBuidler.getExpressionsList()).contains(statusExpression);
+			}
+
+			@Test
+			void shouldNotCallToStatusExpression() {
+				mapper.mapPropertiesToQuery(OzgCloudVorgangQueryTestFactory.createBuilder().status(Optional.empty()).build());
+
+				verify(mapper, never()).toStatusExpression(any());
+			}
+		}
+
+	}
+
+	@Nested
+	class TestToAktenzeichenExpression {
+
+		private final GrpcVorgangQueryExpression aktenzeichenExpression = GrpcVorgangQueryExpressionTestFactory.createBuilder()
+				.setPath(OzgCloudVorgangQueryMapper.AKTENZEICHEN_PATH)
+				.setOperator(GrpcQueryOperator.EQUAL)
+				.setOperandStringValue(OzgCloudVorgangQueryTestFactory.AKTENZEICHEN)
+				.build();
+
+		@Test
+		void shouldReturnAktenzeichenExpression() {
+			var expression = mapper.toAktenzeichenExpression(OzgCloudVorgangQueryTestFactory.AKTENZEICHEN);
+
+			assertThat(expression).usingRecursiveComparison().isEqualTo(aktenzeichenExpression);
+		}
+	}
+
+	@Nested
+	class TestToOrganisationsEinheitIdExpression {
+
+		private final GrpcVorgangQueryExpression organisationsEinheitIdExpression = GrpcVorgangQueryExpressionTestFactory.createBuilder()
+				.setPath(OzgCloudVorgangQueryMapper.ORGANISATIONS_EINHEIT_ID_PATH)
+				.setOperator(GrpcQueryOperator.EQUAL)
+				.setOperandStringValue(OzgCloudVorgangQueryTestFactory.ORGANISATIONS_EINHEIT_ID)
+				.build();
+
+		@Test
+		void shouldReturnOrganisationsEinheitIdExpression() {
+			var expression = mapper.toOrganisationsEinheitIdExpression(OzgCloudVorgangQueryTestFactory.ORGANISATIONS_EINHEIT_ID);
+
+			assertThat(expression).usingRecursiveComparison().isEqualTo(organisationsEinheitIdExpression);
+		}
+	}
+
+	@Nested
+	class TestToStatusExpression {
+
+		private final GrpcVorgangQueryExpression statusExpression = GrpcVorgangQueryExpressionTestFactory.createBuilder()
+				.setPath(OzgCloudVorgangQueryMapper.STATUS_PATH)
+				.setOperator(GrpcQueryOperator.EQUAL)
+				.setOperandStringValue(OzgCloudVorgangQueryTestFactory.STATUS)
+				.build();
+
+		@Test
+		void shouldReturnStatusExpression() {
+			var expression = mapper.toStatusExpression(OzgCloudVorgangQueryTestFactory.STATUS);
+
+			assertThat(expression).usingRecursiveComparison().isEqualTo(statusExpression);
+		}
+	}
+
+	@Nested
+	class TestToFormExpressions {
+
+		private final GrpcVorgangQueryExpression formEngineNameExpression = GrpcVorgangQueryExpressionTestFactory.createBuilder()
+				.setPath(OzgCloudVorgangQueryMapper.FORM_ENGINE_NAME_PATH)
+				.setOperator(GrpcQueryOperator.EQUAL)
+				.setOperandStringValue(FormIdentificationTestFactory.FORM_ENGINE_NAME)
+				.build();
+
+		private final GrpcVorgangQueryExpression formIdExpression = GrpcVorgangQueryExpressionTestFactory.createBuilder()
+				.setPath(OzgCloudVorgangQueryMapper.FORM_ID_PATH)
+				.setOperator(GrpcQueryOperator.EQUAL)
+				.setOperandStringValue(FormIdentificationTestFactory.FORM_ID)
+				.build();
+
+		@Test
+		void shouldReturnFormEngineNameExpression() {
+			var expressions = mapper.toFormExpressions(FormIdentificationTestFactory.createBuilder().formId(null).build());
+
+			assertThat(expressions).usingRecursiveFieldByFieldElementComparator().containsExactly(formEngineNameExpression);
+		}
+
+		@Test
+		void shouldReturnFormIdExpression() {
+			var expressions = mapper.toFormExpressions(FormIdentificationTestFactory.createBuilder().formEngineName(null).build());
+
+			assertThat(expressions).usingRecursiveFieldByFieldElementComparator().containsExactly(formIdExpression);
+		}
+
+		@Test
+		void shouldReturnBothExpressions() {
+			var expressions = mapper.toFormExpressions(FormIdentificationTestFactory.create());
+
+			assertThat(expressions).usingRecursiveFieldByFieldElementComparator().containsExactlyInAnyOrder(formEngineNameExpression,
+					formIdExpression);
+		}
+
+		@Test
+		void shouldReturnUnmodifiableSet() {
+			var newExpression = GrpcVorgangQueryExpressionTestFactory.create();
+
+			var expressions = mapper.toFormExpressions(FormIdentificationTestFactory.create());
+
+			assertThrows(UnsupportedOperationException.class, () -> expressions.add(newExpression));
+		}
+	}
+
+	@Nested
+	class TestToQuery {
+
+		private final Query nestedQuery = QueryTestFactory.create();
+		private final Query query = QueryTestFactory.createBuilder().nestedQuery(nestedQuery).build();
+
+		private final GrpcQuery nestedGrpcQuery = GrpcQueryTestFactory.create();
+		private final GrpcQuery expectedGrpcQuery = GrpcQueryTestFactory.createBuilder().setNestedQuery(nestedGrpcQuery).build();
+
+		@Test
+		void shouldMapQuery() {
+			var grpcQuery = mapper.toQuery(query);
+
+			assertThat(grpcQuery).usingRecursiveComparison().isEqualTo(expectedGrpcQuery);
+		}
+	}
+}
diff --git a/ozg-cloud-spring-boot-starter/src/main/java/de/ozgcloud/client/autoconfigure/OzgCloudClientAutoConfiguration.java b/ozg-cloud-spring-boot-starter/src/main/java/de/ozgcloud/client/autoconfigure/OzgCloudClientAutoConfiguration.java
index ac1567f71d53afe35b08a92504fa590bada70200..bf15fa70790994a26f3886f65701d80af4ab32cb 100644
--- a/ozg-cloud-spring-boot-starter/src/main/java/de/ozgcloud/client/autoconfigure/OzgCloudClientAutoConfiguration.java
+++ b/ozg-cloud-spring-boot-starter/src/main/java/de/ozgcloud/client/autoconfigure/OzgCloudClientAutoConfiguration.java
@@ -31,6 +31,7 @@ import de.ozgcloud.apilib.vorgang.OzgCloudVorgangService;
 import de.ozgcloud.apilib.vorgang.dummy.DummyVorgangService;
 import de.ozgcloud.apilib.vorgang.grpc.GrpcOzgCloudVorgangService;
 import de.ozgcloud.apilib.vorgang.grpc.OzgCloudVorgangMapper;
+import de.ozgcloud.apilib.vorgang.grpc.OzgCloudVorgangQueryMapper;
 import de.ozgcloud.apilib.vorgang.grpc.OzgCloudVorgangStubMapper;
 import de.ozgcloud.vorgang.grpc.command.CommandServiceGrpc;
 import de.ozgcloud.vorgang.vorgang.VorgangServiceGrpc.VorgangServiceBlockingStub;
@@ -136,10 +137,10 @@ public class OzgCloudClientAutoConfiguration {
 	@Bean("ozgCloudVorgangService")
 	@ConditionalOnProperty("ozgcloud.vorgang-manager.address")
 	OzgCloudVorgangService grpcOzgCloudVorgangService(VorgangServiceBlockingStub vorgangServiceStub,
-			OzgCloudVorgangMapper mapper,
-			OzgCloudVorgangStubMapper stubMapper, OzgCloudCallContextProvider contextProvider) {
+			OzgCloudVorgangMapper mapper, OzgCloudVorgangStubMapper stubMapper, OzgCloudVorgangQueryMapper queryMapper,
+			OzgCloudCallContextProvider contextProvider) {
 
-		return new GrpcOzgCloudVorgangService(vorgangServiceStub, mapper, stubMapper, contextProvider);
+		return new GrpcOzgCloudVorgangService(vorgangServiceStub, mapper, stubMapper, queryMapper, contextProvider);
 	}
 
 	@Bean
@@ -152,6 +153,11 @@ public class OzgCloudClientAutoConfiguration {
 		return Mappers.getMapper(OzgCloudVorgangStubMapper.class);
 	}
 
+	@Bean
+	OzgCloudVorgangQueryMapper ozgCloudVorgangQueryMapper() {
+		return Mappers.getMapper(OzgCloudVorgangQueryMapper.class);
+	}
+
 	@Bean("ozgCloudVorgangService")
 	@ConditionalOnMissingBean(OzgCloudVorgangService.class)
 	OzgCloudVorgangService dummyOzgCloudVorgangService() {
@@ -204,11 +210,13 @@ public class OzgCloudClientAutoConfiguration {
 		return Mappers.getMapper(OzgCloudFileMapper.class);
 	}
 
-//	@Bean
-//	@ConditionalOnProperty("ozgcloud.user-manager.address")
-//	OzgCloudUserProfileService grpcOzgCloudUserProfileService(@GrpcClient("ozgcloud-user-manager") UserProfileServiceBlockingStub grpcStub,
-//			UserProfileMapper mapper) {
-//		System.out.println("#### building UM-ProfileService");
-//		return new GrpcOzgCloudUserProfileService(grpcStub, mapper);
-//	}
+	// @Bean
+	// @ConditionalOnProperty("ozgcloud.user-manager.address")
+	// OzgCloudUserProfileService
+	// grpcOzgCloudUserProfileService(@GrpcClient("ozgcloud-user-manager")
+	// UserProfileServiceBlockingStub grpcStub,
+	// UserProfileMapper mapper) {
+	// System.out.println("#### building UM-ProfileService");
+	// return new GrpcOzgCloudUserProfileService(grpcStub, mapper);
+	// }
 }