diff --git a/spec/openapi.yaml b/spec/openapi.yaml
index ef79efff1ff3b892a2cbf5d7c409dadda2c1a3fd..a902e0a27c9a72d9c33a6b56efa51b9e67d0f7ef 100644
--- a/spec/openapi.yaml
+++ b/spec/openapi.yaml
@@ -93,6 +93,47 @@ paths:
         500:
           description: Error while processing data
 
+  /reports/gitlab/private-projects:
+    parameters:
+      - name: status
+        in: query
+        description: the project's current status - active/deleted
+        required: false
+        schema:
+          type: string
+      - name: since
+        in: query
+        description: Starting date range for project creation date - yyyy-MM-dd
+        required: false
+        schema:
+          type: string
+      - name: until
+        in: query
+        description: Ending date range for project creation date - yyyy-MM-dd
+        required: false
+        schema:
+          type: string
+    get:
+      tags:
+        - Private project event report
+      summary: Gitlab private project event report
+      description: Returns list of private project events using desired filters
+      responses:
+        200:
+          description: Success
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/PrivateProjectEvents"
+        400:
+          description: Bad Request - invalid non-null prams
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/Error"
+        500:
+          description: Error while processing request
+
 components:
   schemas:
     NullableString:
@@ -334,3 +375,55 @@ components:
             - 'null'
             - string
           description: The old path with namespace, only used in 'project_rename' hooks
+
+    PrivateProjectEvents:
+      type: array
+      items:  
+        $ref: "#/components/schemas/PrivateProjectEvent"
+
+    PrivateProjectEvent:
+      type: object
+      properties:
+        composite_id:
+          $ref: "#/components/schemas/EventCompositeId"
+        parent_project:
+          type: 
+            - integer
+            - "null"
+          description: the parent project if it exists. Indicates this project is a fork
+        creation_date:
+          type: string
+          description: The project creation date
+        deletion_date:
+          type: 
+            - string
+            - "null"
+          description: the project deletion date if it was deleted
+
+    EventCompositeId:
+      type: object
+      properties:
+        user_id:
+          type: integer
+          description: the project creator's GitLab id
+        project_id: 
+          type: integer
+          description: The project GitLab id
+        project_path:
+          type: string
+          description: the project's path with namespace
+
+    Error:
+      type: object
+      properties:
+        status_code:
+          type: integer
+          description: HTTP response code
+        message:
+          type: string
+          description: Message containing error information
+        url:
+          type:
+            - string
+            - "null"
+          description: The URL
diff --git a/src/main/java/org/eclipsefoundation/git/eca/config/LocalDateParamConverterProvider.java b/src/main/java/org/eclipsefoundation/git/eca/config/LocalDateParamConverterProvider.java
new file mode 100644
index 0000000000000000000000000000000000000000..0b80f951fb15b40c6212a3bf9d9f1cd523a8c40c
--- /dev/null
+++ b/src/main/java/org/eclipsefoundation/git/eca/config/LocalDateParamConverterProvider.java
@@ -0,0 +1,51 @@
+/*********************************************************************
+* Copyright (c) 2022 Eclipse Foundation.
+*
+* This program and the accompanying materials are made
+* available under the terms of the Eclipse Public License 2.0
+* which is available at https://www.eclipse.org/legal/epl-2.0/
+*
+* Author: Zachary Sabourin <zachary.sabourin@eclipse-foundation.org>
+*
+* SPDX-License-Identifier: EPL-2.0
+**********************************************************************/
+package org.eclipsefoundation.git.eca.config;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.time.LocalDate;
+
+import javax.ws.rs.BadRequestException;
+import javax.ws.rs.ext.ParamConverter;
+import javax.ws.rs.ext.ParamConverterProvider;
+import javax.ws.rs.ext.Provider;
+
+@Provider
+public class LocalDateParamConverterProvider implements ParamConverterProvider {
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T> ParamConverter<T> getConverter(Class<T> rawType, Type genericType, Annotation[] annotations) {
+        if (rawType.isAssignableFrom(LocalDate.class)) {
+            return (ParamConverter<T>) new LocalDateParamConverter();
+        }
+        return null;
+    }
+
+    public static class LocalDateParamConverter implements ParamConverter<LocalDate> {
+
+        @Override
+        public LocalDate fromString(String date) {
+            try {
+                return LocalDate.parse(date.trim());
+            } catch (Exception e) {
+                throw new BadRequestException(String.format("Invalid parameter: %s", date));
+            }
+        }
+
+        @Override
+        public String toString(LocalDate date) {
+            return date.toString();
+        }
+    }
+}
diff --git a/src/main/java/org/eclipsefoundation/git/eca/dto/PrivateProjectEvent.java b/src/main/java/org/eclipsefoundation/git/eca/dto/PrivateProjectEvent.java
index d9e1600ca95638b3b92393a9cf00218b855d8d61..58983fac27a96b28d273484405022f4abf51155e 100644
--- a/src/main/java/org/eclipsefoundation/git/eca/dto/PrivateProjectEvent.java
+++ b/src/main/java/org/eclipsefoundation/git/eca/dto/PrivateProjectEvent.java
@@ -12,7 +12,9 @@
 package org.eclipsefoundation.git.eca.dto;
 
 import java.io.Serializable;
+import java.time.LocalDate;
 import java.time.LocalDateTime;
+import java.time.LocalTime;
 import java.util.List;
 import java.util.stream.Collectors;
 
@@ -199,6 +201,39 @@ public class PrivateProjectEvent extends BareNode {
                                 new Object[] { Integer.valueOf(parentProject) }));
             }
 
+            String active = params.getFirst(GitEcaParameterNames.STATUS_ACTIVE.getName());
+            if (StringUtils.isNotBlank(active)) {
+                statement.addClause(
+                        new ParameterizedSQLStatement.Clause(TABLE.getAlias() + ".deletionDate IS NULL",
+                                new Object[] {}));
+            }
+
+            String deleted = params.getFirst(GitEcaParameterNames.STATUS_DELETED.getName());
+            if (StringUtils.isNotBlank(deleted)) {
+                statement.addClause(
+                        new ParameterizedSQLStatement.Clause(TABLE.getAlias() + ".deletionDate IS NOT NULL",
+                                new Object[] {}));
+            }
+
+            String since = params.getFirst(GitEcaParameterNames.SINCE.getName());
+            String until = params.getFirst(GitEcaParameterNames.UNTIL.getName());
+
+            // Get date range or only one time filter
+            if (StringUtils.isNotBlank(since) && StringUtils.isNotBlank(until)) {
+                statement.addClause(
+                        new ParameterizedSQLStatement.Clause(TABLE.getAlias() + ".creationDate BETWEEN ? AND ?",
+                                new Object[] { LocalDateTime.of(LocalDate.parse(since), LocalTime.of(0, 0)),
+                                        LocalDateTime.of(LocalDate.parse(until), LocalTime.of(23, 59)) }));
+            } else if (StringUtils.isNotBlank(since)) {
+                statement.addClause(
+                        new ParameterizedSQLStatement.Clause(TABLE.getAlias() + ".creationDate > ?",
+                                new Object[] { LocalDateTime.of(LocalDate.parse(since), LocalTime.of(0, 0)) }));
+            } else if (StringUtils.isNotBlank(until)) {
+                statement.addClause(
+                        new ParameterizedSQLStatement.Clause(TABLE.getAlias() + ".creationDate < ?",
+                                new Object[] { LocalDateTime.of(LocalDate.parse(until), LocalTime.of(23, 59)) }));
+            }
+
             return statement;
         }
 
diff --git a/src/main/java/org/eclipsefoundation/git/eca/namespace/GitEcaParameterNames.java b/src/main/java/org/eclipsefoundation/git/eca/namespace/GitEcaParameterNames.java
index 425b21b2cff007dfa7a37841472a992cfb8af5b6..e75ca1706576d3a16a2a60ce6fa950c393d65b8d 100644
--- a/src/main/java/org/eclipsefoundation/git/eca/namespace/GitEcaParameterNames.java
+++ b/src/main/java/org/eclipsefoundation/git/eca/namespace/GitEcaParameterNames.java
@@ -31,6 +31,10 @@ public final class GitEcaParameterNames implements UrlParameterNamespace {
     public static final String USER_ID_RAW = "user_id";
     public static final String PROJECT_PATH_RAW = "project_path";
     public static final String PARENT_PROJECT_RAW = "parent_project";
+    public static final String STATUS_ACTIVE_RAW = "active";
+    public static final String STATUS_DELETED_RAW = "deleted";
+    public static final String SINCE_RAW = "since";
+    public static final String UNTIL_RAW = "until";
     public static final UrlParameter COMMIT_ID = new UrlParameter(COMMIT_ID_RAW);
     public static final UrlParameter SHA = new UrlParameter(SHA_RAW);
     public static final UrlParameter SHAS = new UrlParameter(SHAS_RAW);
@@ -42,11 +46,15 @@ public final class GitEcaParameterNames implements UrlParameterNamespace {
     public static final UrlParameter USER_ID = new UrlParameter(USER_ID_RAW);
     public static final UrlParameter PROJECT_PATH = new UrlParameter(PROJECT_PATH_RAW);
     public static final UrlParameter PARENT_PROJECT = new UrlParameter(PARENT_PROJECT_RAW);
+    public static final UrlParameter STATUS_ACTIVE = new UrlParameter(STATUS_ACTIVE_RAW);
+    public static final UrlParameter STATUS_DELETED = new UrlParameter(STATUS_DELETED_RAW);
+    public static final UrlParameter SINCE = new UrlParameter(SINCE_RAW);
+    public static final UrlParameter UNTIL = new UrlParameter(UNTIL_RAW);
 
     @Override
     public List<UrlParameter> getParameters() {
         return Arrays.asList(COMMIT_ID, SHA, SHAS, PROJECT_ID, PROJECT_IDS, NOT_IN_PROJECT_IDS, REPO_URL,
-                FINGERPRINT, USER_ID, PROJECT_PATH, PARENT_PROJECT);
+                FINGERPRINT, USER_ID, PROJECT_PATH, PARENT_PROJECT, STATUS_ACTIVE, STATUS_DELETED, SINCE, UNTIL);
     }
 
 }
diff --git a/src/main/java/org/eclipsefoundation/git/eca/resource/ReportsResource.java b/src/main/java/org/eclipsefoundation/git/eca/resource/ReportsResource.java
new file mode 100644
index 0000000000000000000000000000000000000000..ad153d39b1e764b23101be97c218f586895349b3
--- /dev/null
+++ b/src/main/java/org/eclipsefoundation/git/eca/resource/ReportsResource.java
@@ -0,0 +1,58 @@
+/*********************************************************************
+* Copyright (c) 2022 Eclipse Foundation.
+*
+* This program and the accompanying materials are made
+* available under the terms of the Eclipse Public License 2.0
+* which is available at https://www.eclipse.org/legal/epl-2.0/
+*
+* Author: Zachary Sabourin <zachary.sabourin@eclipse-foundation.org>
+*
+* SPDX-License-Identifier: EPL-2.0
+**********************************************************************/
+package org.eclipsefoundation.git.eca.resource;
+
+import java.time.LocalDate;
+
+import javax.inject.Inject;
+import javax.ws.rs.BadRequestException;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Response;
+
+import org.apache.commons.lang3.StringUtils;
+import org.eclipsefoundation.core.model.RequestWrapper;
+import org.eclipsefoundation.git.eca.namespace.GitEcaParameterNames;
+import org.eclipsefoundation.git.eca.service.ReportsService;
+
+@Path("/reports")
+public class ReportsResource {
+
+    @Inject
+    RequestWrapper wrap;
+    @Inject
+    ReportsService reportsService;
+
+    @GET
+    @Path("/gitlab/private-projects")
+    public Response getPrivateProjectEvents(@QueryParam("status") String status, @QueryParam("since") LocalDate since,
+            @QueryParam("until") LocalDate until) {
+
+        if (StringUtils.isNotBlank(status) && !isValidStatus(status)) {
+            throw new BadRequestException(String.format("Invalid 'status' parameter: %s", status));
+        }
+
+        return Response.ok(reportsService.getPrivateProjectEvents(wrap, status, since, until)).build();
+    }
+
+    /**
+     * Validates the status as one of "active" or "deleted"
+     * 
+     * @param status the desired status
+     * @return true if valid, false if not
+     */
+    private boolean isValidStatus(String status) {
+        return status.equalsIgnoreCase(GitEcaParameterNames.STATUS_ACTIVE.getName())
+                || status.equalsIgnoreCase(GitEcaParameterNames.STATUS_DELETED.getName());
+    }
+}
diff --git a/src/main/java/org/eclipsefoundation/git/eca/resource/mapper/BadRequestMapper.java b/src/main/java/org/eclipsefoundation/git/eca/resource/mapper/BadRequestMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..7a276b81af1c1d94f3457ef9212f51180b2edd67
--- /dev/null
+++ b/src/main/java/org/eclipsefoundation/git/eca/resource/mapper/BadRequestMapper.java
@@ -0,0 +1,37 @@
+/*********************************************************************
+* Copyright (c) 2022 Eclipse Foundation.
+*
+* This program and the accompanying materials are made
+* available under the terms of the Eclipse Public License 2.0
+* which is available at https://www.eclipse.org/legal/epl-2.0/
+*
+* Author: Zachary Sabourin <zachary.sabourin@eclipse-foundation.org>
+*
+* SPDX-License-Identifier: EPL-2.0
+**********************************************************************/
+package org.eclipsefoundation.git.eca.resource.mapper;
+
+import javax.ws.rs.BadRequestException;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+
+import org.eclipsefoundation.core.model.Error;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Creates human legible error responses in the case of BadRequestExceptions.
+ */
+@Provider
+public class BadRequestMapper implements ExceptionMapper<BadRequestException> {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(BadRequestMapper.class);
+
+    @Override
+    public Response toResponse(BadRequestException exception) {
+        LOGGER.error(exception.getMessage());
+        return new Error(Status.BAD_REQUEST, exception.getMessage()).asResponse();
+    }
+}
diff --git a/src/main/java/org/eclipsefoundation/git/eca/service/ReportsService.java b/src/main/java/org/eclipsefoundation/git/eca/service/ReportsService.java
new file mode 100644
index 0000000000000000000000000000000000000000..97e7a68ba5d3fe2be9be9f036c8615c8706e2595
--- /dev/null
+++ b/src/main/java/org/eclipsefoundation/git/eca/service/ReportsService.java
@@ -0,0 +1,38 @@
+/*********************************************************************
+* Copyright (c) 2022 Eclipse Foundation.
+*
+* This program and the accompanying materials are made
+* available under the terms of the Eclipse Public License 2.0
+* which is available at https://www.eclipse.org/legal/epl-2.0/
+*
+* Author: Zachary Sabourin <zachary.sabourin@eclipse-foundation.org>
+*
+* SPDX-License-Identifier: EPL-2.0
+**********************************************************************/
+package org.eclipsefoundation.git.eca.service;
+
+import java.time.LocalDate;
+import java.util.List;
+
+import org.eclipsefoundation.core.model.RequestWrapper;
+import org.eclipsefoundation.git.eca.dto.PrivateProjectEvent;
+
+/**
+ * This interface provides the means to get list of desired entities from the DB
+ * using desired filters.
+ */
+public interface ReportsService {
+
+    /**
+     * Fetches a filtered list of PrivateProjectEvents from the DB using the desired
+     * parameters. Can be filtered by active/deleted status, and by date range
+     * 
+     * @param wrap   The request wrapper
+     * @param status The current project status
+     * @param since  The starting range
+     * @param until  The ending range
+     * @return A List of PrivateProjectEvent entities
+     */
+    public List<PrivateProjectEvent> getPrivateProjectEvents(RequestWrapper wrap, String status, LocalDate since,
+            LocalDate until);
+}
diff --git a/src/main/java/org/eclipsefoundation/git/eca/service/impl/DefaultReportsService.java b/src/main/java/org/eclipsefoundation/git/eca/service/impl/DefaultReportsService.java
new file mode 100644
index 0000000000000000000000000000000000000000..47a3434d710a393448055710af004fbaf958fcee
--- /dev/null
+++ b/src/main/java/org/eclipsefoundation/git/eca/service/impl/DefaultReportsService.java
@@ -0,0 +1,73 @@
+/*********************************************************************
+* Copyright (c) 2022 Eclipse Foundation.
+*
+* This program and the accompanying materials are made
+* available under the terms of the Eclipse Public License 2.0
+* which is available at https://www.eclipse.org/legal/epl-2.0/
+*
+* Author: Zachary Sabourin <zachary.sabourin@eclipse-foundation.org>
+*
+* SPDX-License-Identifier: EPL-2.0
+**********************************************************************/
+package org.eclipsefoundation.git.eca.service.impl;
+
+import java.time.LocalDate;
+import java.util.Collections;
+import java.util.List;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import javax.ws.rs.core.MultivaluedMap;
+
+import org.apache.commons.lang3.StringUtils;
+import org.eclipsefoundation.core.model.RequestWrapper;
+import org.eclipsefoundation.git.eca.dto.PrivateProjectEvent;
+import org.eclipsefoundation.git.eca.namespace.GitEcaParameterNames;
+import org.eclipsefoundation.git.eca.service.ReportsService;
+import org.eclipsefoundation.persistence.dao.PersistenceDao;
+import org.eclipsefoundation.persistence.model.RDBMSQuery;
+import org.eclipsefoundation.persistence.service.FilterService;
+import org.jboss.resteasy.specimpl.MultivaluedMapImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@ApplicationScoped
+public class DefaultReportsService implements ReportsService {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(DefaultReportsService.class);
+
+    @Inject
+    PersistenceDao dao;
+    @Inject
+    FilterService filters;
+
+    @Override
+    public List<PrivateProjectEvent> getPrivateProjectEvents(RequestWrapper wrap, String status, LocalDate since, LocalDate until) {
+
+        MultivaluedMap<String, String> params = new MultivaluedMapImpl<>();
+
+        if (StringUtils.isNotBlank(status)) {
+            if (status.equalsIgnoreCase(GitEcaParameterNames.STATUS_ACTIVE.getName())) {
+                params.add(GitEcaParameterNames.STATUS_ACTIVE.getName(), status);
+            } else {
+                params.add(GitEcaParameterNames.STATUS_DELETED.getName(), status);
+            }
+        }
+        if (since != null) {
+            params.add(GitEcaParameterNames.SINCE.getName(), since.toString());
+        }
+        if (until != null) {
+            params.add(GitEcaParameterNames.UNTIL.getName(), until.toString());
+        }
+
+        List<PrivateProjectEvent> results = dao
+                .get(new RDBMSQuery<>(wrap, filters.get(PrivateProjectEvent.class), params));
+        if (results == null) {
+            LOGGER.error("Error retrieving PrivateProjectEvents from the DB using params: {}", params);
+            return Collections.emptyList();
+        }
+
+        return results;
+    }
+
+}
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index 4c362c0043718c1185e6ae4845393406d7776d1e..7f1acfd66b080cc69610fbd6ae489cbbd7eb00d0 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -38,5 +38,7 @@ quarkus.cache.caffeine."record".expire-after-write=${quarkus.cache.caffeine."def
 eclipse.mail.allowlist=noreply@github.com,49699333+dependabot[bot]@users.noreply.github.com
 %dev.eclipse.cache.resource.enabled=true
 %dev.eclipse.optional-resources.enabled=true
+%dev.eclipse.scheduled.private-project.enabled=false
+
 #%dev.quarkus.log.level=DEBUG
 #quarkus.log.category."org.eclipsefoundation".level=DEBUG
\ No newline at end of file
diff --git a/src/test/java/org/eclipsefoundation/git/eca/resource/ReportsResourceTest.java b/src/test/java/org/eclipsefoundation/git/eca/resource/ReportsResourceTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..3e96bd0067cbd5fc03e02044ed93ed43ffecdac0
--- /dev/null
+++ b/src/test/java/org/eclipsefoundation/git/eca/resource/ReportsResourceTest.java
@@ -0,0 +1,209 @@
+/*********************************************************************
+* Copyright (c) 2022 Eclipse Foundation.
+*
+* This program and the accompanying materials are made
+* available under the terms of the Eclipse Public License 2.0
+* which is available at https://www.eclipse.org/legal/epl-2.0/
+*
+* Author: Zachary Sabourin <zachary.sabourin@eclipse-foundation.org>
+*
+* SPDX-License-Identifier: EPL-2.0
+**********************************************************************/
+package org.eclipsefoundation.git.eca.resource;
+
+import org.eclipsefoundation.git.eca.namespace.GitEcaParameterNames;
+import org.eclipsefoundation.git.eca.test.namespaces.SchemaNamespaceHelper;
+import org.eclipsefoundation.testing.helpers.TestCaseHelper;
+import org.eclipsefoundation.testing.templates.RestAssuredTemplates;
+import org.eclipsefoundation.testing.templates.RestAssuredTemplates.EndpointTestCase;
+import org.junit.jupiter.api.Test;
+
+import io.quarkus.test.junit.QuarkusTest;
+import io.restassured.http.ContentType;
+
+@QuarkusTest
+class ReportsResourceTest {
+    public static final String REPORTS_BASE_URL = "/reports";
+    public static final String REPORTS_PROJECTS_URL = REPORTS_BASE_URL + "/gitlab/private-projects";
+    public static final String REPORTS_PROJECTS_STATUS_URL = REPORTS_PROJECTS_URL + "?status={status}";
+    public static final String REPORTS_PROJECTS_UNTIL_URL = REPORTS_PROJECTS_URL + "?until={date}";
+    public static final String REPORTS_PROJECTS_SINCE_URL = REPORTS_PROJECTS_URL + "?since={date}";
+    public static final String REPORTS_PROJECTS_RANGE_URL = REPORTS_PROJECTS_URL + "?since={start}&until={end}";
+
+    public static final EndpointTestCase GET_REPORT_SUCCESS_CASE = TestCaseHelper
+            .buildSuccessCase(REPORTS_PROJECTS_URL, new String[] {},
+                    SchemaNamespaceHelper.PRIVATE_PROJECT_EVENTS_SCHEMA_PATH);
+
+    public static final EndpointTestCase GET_REPORT_ACTIVE_SUCCESS_CASE = TestCaseHelper.buildSuccessCase(
+            REPORTS_PROJECTS_STATUS_URL, new String[] { GitEcaParameterNames.STATUS_ACTIVE.getName() },
+            SchemaNamespaceHelper.PRIVATE_PROJECT_EVENTS_SCHEMA_PATH);
+
+    public static final EndpointTestCase GET_REPORT_DELETED_SUCCESS_CASE = TestCaseHelper.buildSuccessCase(
+            REPORTS_PROJECTS_STATUS_URL, new String[] { GitEcaParameterNames.STATUS_DELETED.getName() },
+            SchemaNamespaceHelper.PRIVATE_PROJECT_EVENTS_SCHEMA_PATH);
+
+    public static final EndpointTestCase GET_REPORT_SINCE_SUCCESS_CASE = TestCaseHelper.buildSuccessCase(
+            REPORTS_PROJECTS_SINCE_URL, new String[] { "2022-11-11" },
+            SchemaNamespaceHelper.PRIVATE_PROJECT_EVENTS_SCHEMA_PATH);
+
+    public static final EndpointTestCase GET_REPORT_UNTIL_SUCCESS_CASE = TestCaseHelper.buildSuccessCase(
+            REPORTS_PROJECTS_UNTIL_URL, new String[] { "2022-11-15" },
+            SchemaNamespaceHelper.PRIVATE_PROJECT_EVENTS_SCHEMA_PATH);
+
+    public static final EndpointTestCase GET_REPORT_RANGE_SUCCESS_CASE = TestCaseHelper.buildSuccessCase(
+            REPORTS_PROJECTS_RANGE_URL, new String[] { "2022-11-15", "2022-11-15" },
+            SchemaNamespaceHelper.PRIVATE_PROJECT_EVENTS_SCHEMA_PATH);
+
+    public static final EndpointTestCase GET_REPORT_BAD_STATUS_CASE = TestCaseHelper.buildBadRequestCase(
+            REPORTS_PROJECTS_STATUS_URL, new String[] { "nope" }, SchemaNamespaceHelper.ERROR_SCHEMA_PATH);
+
+    public static final EndpointTestCase GET_REPORT_BAD_UNTIL_CASE = TestCaseHelper.buildBadRequestCase(
+            REPORTS_PROJECTS_UNTIL_URL, new String[] { "nope" }, SchemaNamespaceHelper.ERROR_SCHEMA_PATH);
+
+    public static final EndpointTestCase GET_REPORT_BAD_SINCE_CASE = TestCaseHelper.buildBadRequestCase(
+            REPORTS_PROJECTS_SINCE_URL, new String[] { "nope" }, SchemaNamespaceHelper.ERROR_SCHEMA_PATH);
+
+    /*
+     * GET /reports/webhooks/gitlab/system
+     */
+    @Test
+    void getPrivProjReport_success() {
+        RestAssuredTemplates.testGet(GET_REPORT_SUCCESS_CASE);
+    }
+
+    @Test
+    void getPrivProjReport_success_validateSchema() {
+        RestAssuredTemplates.testGet_validateSchema(GET_REPORT_SUCCESS_CASE);
+    }
+
+    @Test
+    void getPrivProjReport_success_validateResponseFormat() {
+        RestAssuredTemplates.testGet_validateResponseFormat(GET_REPORT_SUCCESS_CASE);
+    }
+
+    @Test
+    void getPrivProjReport_failure_invalidRequestFormat() {
+        RestAssuredTemplates.testGet(
+                TestCaseHelper.buildInvalidFormatCase(REPORTS_PROJECTS_URL, new String[] {}, ContentType.TEXT));
+    }
+
+    /*
+     * GET /reports/webhooks/gitlab/system?status=active
+     */
+    @Test
+    void getPrivProjReportActive_success() {
+        RestAssuredTemplates.testGet(GET_REPORT_ACTIVE_SUCCESS_CASE);
+    }
+
+    @Test
+    void getPrivProjReportActive_success_validateSchema() {
+        RestAssuredTemplates.testGet_validateSchema(GET_REPORT_ACTIVE_SUCCESS_CASE);
+    }
+
+    @Test
+    void getPrivProjReportActive_success_validateResponseFormat() {
+        RestAssuredTemplates.testGet_validateResponseFormat(GET_REPORT_ACTIVE_SUCCESS_CASE);
+    }
+
+    @Test
+    void getPrivProjReportStatus_failure_invalidStatus() {
+        RestAssuredTemplates.testGet(GET_REPORT_BAD_STATUS_CASE);
+    }
+
+    @Test
+    void getPrivProjReportStatus_failure_invalidStatus_validate_schema() {
+        RestAssuredTemplates.testGet_validateSchema(GET_REPORT_BAD_STATUS_CASE);
+    }
+
+    /*
+     * GET /reports/webhooks/gitlab/system?status=deleted
+     */
+    @Test
+    void getPrivProjReportDeleted_success() {
+        RestAssuredTemplates.testGet(GET_REPORT_DELETED_SUCCESS_CASE);
+    }
+
+    @Test
+    void getPrivProjReportDeleted_success_validateSchema() {
+        RestAssuredTemplates.testGet_validateSchema(GET_REPORT_DELETED_SUCCESS_CASE);
+    }
+
+    @Test
+    void getPrivProjReportDeleted_success_validateResponseFormat() {
+        RestAssuredTemplates.testGet_validateResponseFormat(GET_REPORT_DELETED_SUCCESS_CASE);
+    }
+
+    /*
+     * GET /reports/webhooks/gitlab/system?since={date}
+     */
+    @Test
+    void getPrivProjReportSince_success() {
+        RestAssuredTemplates.testGet(GET_REPORT_SINCE_SUCCESS_CASE);
+    }
+
+    @Test
+    void getPrivProjReportSince_success_validateSchema() {
+        RestAssuredTemplates.testGet_validateSchema(GET_REPORT_SINCE_SUCCESS_CASE);
+    }
+
+    @Test
+    void getPrivProjReportSince_success_validateResponseFormat() {
+        RestAssuredTemplates.testGet_validateResponseFormat(GET_REPORT_SINCE_SUCCESS_CASE);
+    }
+
+    @Test
+    void getPrivProjReportSince_failure_invalidStatus() {
+        RestAssuredTemplates.testGet(GET_REPORT_BAD_SINCE_CASE);
+    }
+
+    @Test
+    void getPrivProjReportSince_failure_invalidStatus_validate_schema() {
+        RestAssuredTemplates.testGet_validateSchema(GET_REPORT_BAD_SINCE_CASE);
+    }
+
+    /*
+     * GET /reports/webhooks/gitlab/system?until={date}
+     */
+    @Test
+    void getPrivProjReportUntil_success() {
+        RestAssuredTemplates.testGet(GET_REPORT_UNTIL_SUCCESS_CASE);
+    }
+
+    @Test
+    void getPrivProjReportUntil_success_validateSchema() {
+        RestAssuredTemplates.testGet_validateSchema(GET_REPORT_UNTIL_SUCCESS_CASE);
+    }
+
+    @Test
+    void getPrivProjReportUntil_success_validateResponseFormat() {
+        RestAssuredTemplates.testGet_validateResponseFormat(GET_REPORT_UNTIL_SUCCESS_CASE);
+    }
+
+    @Test
+    void getPrivProjReportUntil_failure_invalidStatus() {
+        RestAssuredTemplates.testGet(GET_REPORT_BAD_UNTIL_CASE);
+    }
+
+    @Test
+    void getPrivProjReportSUntil_failure_invalidStatus_validate_schema() {
+        RestAssuredTemplates.testGet_validateSchema(GET_REPORT_BAD_UNTIL_CASE);
+    }
+
+    /*
+     * GET /reports/webhooks/gitlab/system?since={date}&until={date}
+     */
+    @Test
+    void getPrivProjReportRange_success() {
+        RestAssuredTemplates.testGet(GET_REPORT_RANGE_SUCCESS_CASE);
+    }
+
+    @Test
+    void getPrivProjReportRange_success_validateSchema() {
+        RestAssuredTemplates.testGet_validateSchema(GET_REPORT_RANGE_SUCCESS_CASE);
+    }
+
+    @Test
+    void getPrivProjReportRange_success_validateResponseFormat() {
+        RestAssuredTemplates.testGet_validateResponseFormat(GET_REPORT_RANGE_SUCCESS_CASE);
+    }
+}
diff --git a/src/test/java/org/eclipsefoundation/git/eca/test/namespaces/SchemaNamespaceHelper.java b/src/test/java/org/eclipsefoundation/git/eca/test/namespaces/SchemaNamespaceHelper.java
index 1b42e1e0b179e515c1b66dcc878d93e375e172ef..6bf874f9d757abd6baec2af53ecff7d31c05bf48 100644
--- a/src/test/java/org/eclipsefoundation/git/eca/test/namespaces/SchemaNamespaceHelper.java
+++ b/src/test/java/org/eclipsefoundation/git/eca/test/namespaces/SchemaNamespaceHelper.java
@@ -12,10 +12,18 @@
 package org.eclipsefoundation.git.eca.test.namespaces;
 
 public final class SchemaNamespaceHelper {
-    public static final String BASE_SCHEMAS_PATH = "schemas/";
-    public static final String BASE_SCHEMAS_PATH_SUFFIX = "-schema.json";
-    public static final String VALIDATION_REQUEST_SCHEMA_PATH = BASE_SCHEMAS_PATH + "validation-request"
-            + BASE_SCHEMAS_PATH_SUFFIX;
-    public static final String VALIDATION_RESPONSE_SCHEMA_PATH = BASE_SCHEMAS_PATH + "validation-response"
-            + BASE_SCHEMAS_PATH_SUFFIX;
+	public static final String BASE_SCHEMAS_PATH = "schemas/";
+	public static final String BASE_SCHEMAS_PATH_SUFFIX = "-schema.json";
+
+	public static final String VALIDATION_REQUEST_SCHEMA_PATH = BASE_SCHEMAS_PATH + "validation-request"
+			+ BASE_SCHEMAS_PATH_SUFFIX;
+	public static final String VALIDATION_RESPONSE_SCHEMA_PATH = BASE_SCHEMAS_PATH + "validation-response"
+			+ BASE_SCHEMAS_PATH_SUFFIX;
+
+	public static final String PRIVATE_PROJECT_EVENT_SCHEMA_PATH = BASE_SCHEMAS_PATH + "private-project-event"
+			+ BASE_SCHEMAS_PATH_SUFFIX;
+	public static final String PRIVATE_PROJECT_EVENTS_SCHEMA_PATH = BASE_SCHEMAS_PATH + "private-project-events"
+			+ BASE_SCHEMAS_PATH_SUFFIX;
+
+	public static final String ERROR_SCHEMA_PATH = BASE_SCHEMAS_PATH + "error" + BASE_SCHEMAS_PATH_SUFFIX;
 }
diff --git a/src/test/resources/database/default/V1.0.0__default.sql b/src/test/resources/database/default/V1.0.0__default.sql
index cf889fb32190e0fa52c008600b9d53290075e01b..398aa5159250311a7dd2f581cea3a38e052e7487 100644
--- a/src/test/resources/database/default/V1.0.0__default.sql
+++ b/src/test/resources/database/default/V1.0.0__default.sql
@@ -31,4 +31,16 @@ CREATE TABLE `CommitValidationStatusGrouping` (
   `commit_id` bigint NOT NULL,
   PRIMARY KEY (`commit_id`,`fingerprint`)
 );
-INSERT INTO CommitValidationStatusGrouping(fingerprint, commit_id) VALUES('957706b0f31e0ccfc5287c0ebc62dc79', 1);
\ No newline at end of file
+INSERT INTO CommitValidationStatusGrouping(fingerprint, commit_id) VALUES('957706b0f31e0ccfc5287c0ebc62dc79', 1);
+
+CREATE TABLE PrivateProjectEvent (
+  userId int NOT NULL,
+  projectId int NOT NULL,
+  projectPath varchar(255) NOT NULL,
+  parentProject int DEFAULT NULL,
+  creationDate datetime NOT NULL,
+  deletionDate datetime DEFAULT NULL,
+  PRIMARY KEY (userId, projectId, projectPath)
+);
+INSERT INTO PrivateProjectEvent(userId, projectId, projectPath, creationDate) VALUES(1, 133, 'eclipse/test/project', '2022-11-11T12:00:00.000');
+INSERT INTO PrivateProjectEvent(userId, projectId, projectPath, parentProject, creationDate, deletionDate) VALUES(1, 150, 'eclipse/test/project/fork', 133, '2022-11-15T12:00:00.000', '2022-11-20T12:00:00.000');
\ No newline at end of file