diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 7ee16223b51d10a14ecbca9e862914d3c0cf1282..d56a3f62b853f83b233434aeaf2c70b72983a4f6 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -27,7 +27,8 @@ variables:
   # We exclude it here to speed up pipeline execution, and avoid having the image fail on our Maven builds
   # Maven jobs should be using semgrep instead
   SAST_EXCLUDED_ANALYZERS: "spotbugs"
-
+  
+  ACCEPTANCE_TEST_DIR: "legal-acceptance-test"
 include:
   - project: "osdu/platform/ci-cd-pipelines"
     file: "standard-setup.yml"
diff --git a/legal-acceptance-test/docs/README.md b/legal-acceptance-test/docs/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..e95c0f3efac711de1b87d23b56f73203ff5d6d7f
--- /dev/null
+++ b/legal-acceptance-test/docs/README.md
@@ -0,0 +1,61 @@
+### Running E2E Tests
+
+You will need to have the following environment variables defined.
+
+| name                                 | value                                            | description                                                                                                                                                                                                                    | sensitive?                              | source |
+|--------------------------------------|--------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------|--------|
+| `HOST_URL`                           | ex `https://osdu.core-dev.gcp.gnrg-osdu.projects.epam.com/api/legal/v1/`         | -                                                                                                                                                                                                                              | yes                                     | -      |
+| `MY_TENANT`                          | ex `osdu`                                        | OSDU tenant used for testing                                                                                                                                                                                                   | yes                                     | -      |
+| `SKIP_HTTP_TESTS`                    | ex `true`                                        | jetty server returns 403 when running locally when deployed jettyserver is not used and the app returns a 302 so just run against deployed version only when checking http -> https redirects. Use 'true' for Google Cloud Run | yes                                     | -      |
+
+
+
+Authentication can be provided as OIDC config:
+
+| name                                            | value                                   | description                   | sensitive? | source |
+|-------------------------------------------------|-----------------------------------------|-------------------------------|------------|--------|
+| `PRIVILEGED_USER_OPENID_PROVIDER_CLIENT_ID`     | `********`                              | PRIVILEGED_USER Client Id      | yes        | -      |
+| `PRIVILEGED_USER_OPENID_PROVIDER_CLIENT_SECRET` | `********`                              | PRIVILEGED_USER Client secret | yes        | -      |
+| `TEST_OPENID_PROVIDER_URL`                      | `https://keycloak.com/auth/realms/osdu` | OpenID provider url           | yes        | -      |
+
+Or tokens can be used directly from env variables:
+
+| name                    | value      | description           | sensitive? | source |
+|-------------------------|------------|-----------------------|------------|--------|
+| `PRIVILEGED_USER_TOKEN` | `********` | PRIVILEGED_USER_TOKEN Token | yes        | -      |
+
+
+**Entitlements configuration for integration accounts**
+
+| PRIVILEGED_USER                                                                                                                                   |
+|------------------------------------------------------------------------------------------------------------------------------------------------------|
+| users<br/>service.entitlements.user<br/>service.legal.admin<br/>service.legal.editor<br/>service.legal.user<br/>data.test1<br/>data.integration.test |
+
+Execute following command to build code and run all the integration tests:
+
+```bash
+# Note: this assumes that the environment variables for integration tests as outlined
+#       above are already exported in your environment.
+$ (cd legal-acceptance-test && mvn clean test)
+```
+
+
+## License
+
+Copyright © Google LLC
+
+Copyright © EPAM Systems
+
+Copyright © ExxonMobil
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+[http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/legal-acceptance-test/pom.xml b/legal-acceptance-test/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c409fdd6461316c03710cedcb195ae75d09aa51f
--- /dev/null
+++ b/legal-acceptance-test/pom.xml
@@ -0,0 +1,153 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<groupId>org.opengroup.osdu.legal</groupId>
+	<artifactId>legal-acceptance-test</artifactId>
+	<version>0.28.0-SNAPSHOT</version>
+	<packaging>jar</packaging>
+
+	<properties>
+		<maven.compiler.target>17</maven.compiler.target>
+		<maven.compiler.source>17</maven.compiler.source>
+		<java.version>17</java.version>
+		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+		<project.main.basedir>${project.basedir}</project.main.basedir>
+		<allure.version>2.29.0</allure.version>
+		<aspectj.version>1.9.22</aspectj.version>
+		<log4j.version>2.23.0</log4j.version>
+		<jackson.version>2.16.1</jackson.version>
+		<jackson-databind.version>2.16.1</jackson-databind.version>
+		<maven-surefire-plugin.version>3.2.5</maven-surefire-plugin.version>
+		<argLine>
+			--add-opens java.base/java.lang=ALL-UNNAMED
+		</argLine>
+	</properties>
+	<dependencies>
+		<dependency>
+			<groupId>com.sun.jersey</groupId>
+			<artifactId>jersey-client</artifactId>
+			<version>1.19.4</version>
+		</dependency>
+		<!-- https://mvnrepository.com/artifact/junit/junit -->
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<version>4.12</version>
+		</dependency>
+		<dependency>
+			<groupId>com.google.code.gson</groupId>
+			<artifactId>gson</artifactId>
+			<version>2.9.0</version>
+		</dependency>
+		<dependency>
+			<groupId>org.junit.jupiter</groupId>
+			<artifactId>junit-jupiter-engine</artifactId>
+			<version>5.10.4</version>
+		</dependency>
+		<dependency>
+			<groupId>org.junit.platform</groupId>
+			<artifactId>junit-platform-console</artifactId>
+			<version>1.10.4</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.commons</groupId>
+			<artifactId>commons-lang3</artifactId>
+			<version>3.12.0</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.httpcomponents</groupId>
+			<artifactId>httpcore</artifactId>
+			<version>4.4.15</version>
+		</dependency>
+		<dependency>
+			<groupId>com.google.guava</groupId>
+			<artifactId>guava</artifactId>
+			<version>31.1-jre</version>
+		</dependency>
+		<dependency>
+			<groupId>org.projectlombok</groupId>
+			<artifactId>lombok</artifactId>
+			<version>1.18.28</version>
+		</dependency>
+		<dependency>
+			<groupId>io.minio</groupId>
+			<artifactId>minio</artifactId>
+			<version>7.1.4</version>
+		</dependency>
+		<dependency>
+			<groupId>com.nimbusds</groupId>
+			<artifactId>oauth2-oidc-sdk</artifactId>
+			<version>9.15</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.logging.log4j</groupId>
+			<artifactId>log4j-to-slf4j</artifactId>
+			<version>2.11.2</version>
+		</dependency>
+		<dependency>
+			<groupId>org.slf4j</groupId>
+			<artifactId>slf4j-jdk14</artifactId>
+			<version>1.8.0-beta4</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.httpcomponents.client5</groupId>
+			<artifactId>httpclient5</artifactId>
+			<version>5.2.1</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.opengroup.osdu</groupId>
+			<artifactId>os-core-common</artifactId>
+			<version>0.25.0</version>
+		</dependency>
+	</dependencies>
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-surefire-plugin</artifactId>
+				<version>${maven-surefire-plugin.version}</version>
+			</plugin>
+		</plugins>
+	</build>
+	<repositories>
+		<repository>
+			<id>${repo.releases.id}</id>
+			<url>${repo.releases.url}</url>
+		</repository>
+	</repositories>
+
+	<distributionManagement>
+		<repository>
+			<id>${publish.releases.id}</id>
+			<url>${publish.releases.url}</url>
+		</repository>
+		<snapshotRepository>
+			<id>${publish.snapshots.id}</id>
+			<url>${publish.snapshots.url}</url>
+		</snapshotRepository>
+	</distributionManagement>
+	<profiles>
+		<profile>
+			<id>Default</id>
+			<activation>
+				<property>
+					<name>!repo.releases.id</name>
+				</property>
+			</activation>
+			<properties>
+				<repo.releases.id>community-maven-repo</repo.releases.id>
+				<publish.snapshots.id>community-maven-via-job-token</publish.snapshots.id>
+				<publish.releases.id>community-maven-via-job-token</publish.releases.id>
+				<repo.releases.url>
+					https://community.opengroup.org/api/v4/groups/17/-/packages/maven</repo.releases.url>
+				<publish.snapshots.url>
+					https://community.opengroup.org/api/v4/projects/44/packages/maven</publish.snapshots.url>
+				<publish.releases.url>
+					https://community.opengroup.org/api/v4/projects/44/packages/maven</publish.releases.url>
+			</properties>
+		</profile>
+	</profiles>
+</project>
\ No newline at end of file
diff --git a/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/acceptancetests/CreateLegalTagApiAcceptanceTests.java b/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/acceptancetests/CreateLegalTagApiAcceptanceTests.java
new file mode 100644
index 0000000000000000000000000000000000000000..540f5e4603ee605ac4b303afe524d1c4f5eee93c
--- /dev/null
+++ b/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/acceptancetests/CreateLegalTagApiAcceptanceTests.java
@@ -0,0 +1,222 @@
+package org.opengroup.osdu.legal.acceptancetests;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.opengroup.osdu.legal.util.AcceptanceBaseTest;
+import org.opengroup.osdu.legal.util.LegalTagUtils;
+import org.opengroup.osdu.legal.util.TestUtils;
+
+import com.sun.jersey.api.client.ClientResponse;
+
+public final class CreateLegalTagApiAcceptanceTests extends AcceptanceBaseTest {
+
+    private String name = LegalTagUtils.createRandomNameTenant();
+    private String COO = "";
+
+    @BeforeEach
+    @Override
+    public void setup() throws Exception {
+        this.legalTagUtils = new LegalTagUtils();
+        COO = "US";
+        super.setup();
+    }
+
+    @AfterEach
+    @Override
+    public void teardown() throws Exception {
+        legalTagUtils.delete(name);
+        super.teardown();
+        this.legalTagUtils = null;
+    }
+
+    @Test
+    public void should_returnCreated_when_userHasApiAccess() throws Exception{
+        validateAccess(201);
+    }
+
+    @Test
+    public void should_return400_when_userHasApiAccess_ButSendsEmbargoedCOO() throws Exception{
+        COO = "SD";
+        ClientResponse response = validateAccess(400);
+        String messageResponse = legalTagUtils.getResult(response, 400, String.class);
+        assertEquals("{\"code\":400,\"reason\":\"Validation error.\",\"message\":\"{\\\"errors\\\":[\\\"Invalid country of origin set. It should match one of the ISO alpha 2 codes and be a country with no restriction on data residency. Found: [SD].\\\"]}\"}" , messageResponse);
+    }
+
+    @Test
+    public void should_notAllowCreationOfLegalTag_when_countryOfOriginIsSetToARestrictedCountry() throws Exception {
+        COO = "BV";
+        ClientResponse response = validateAccess(400);
+        String messageResponse = legalTagUtils.getResult(response, 400, String.class);
+        assertEquals("{\"code\":400,\"reason\":\"Validation error.\",\"message\":\"{\\\"errors\\\":[\\\"Invalid country of origin set. It should match one of the ISO alpha 2 codes and be a country with no restriction on data residency. Found: [BV].\\\"]}\"}", messageResponse);
+    }
+
+    @Test
+    public void should_return400_when_givenEmptyBody() throws Exception{
+        ClientResponse response = legalTagUtils.send(this.getApi(), this.getHttpMethod(), legalTagUtils.accessToken(), "{}", getQuery());
+        assertEquals(400, response.getStatus());
+    }
+
+    @Test
+    public void should_allowCreationOfLegalTag_when_3rdPArtyDataHasAValidExpirationDate() throws Exception {
+        ClientResponse response = legalTagUtils.create("US", name, "", "Third Party Data");
+        String messageResponse = legalTagUtils.getResult(response, 400, String.class);
+        assertTrue(messageResponse.indexOf("You need to set an expiration date and contract ID") >= 0);
+        response = legalTagUtils.create("US", name, "2099-12-25", "Third Party Data");
+        legalTagUtils.getResult(response, 201, String.class);
+    }
+
+    @Test
+    public void should_createLegalTag_with_descriptionNotSupplied() throws Exception{
+        ClientResponse response = legalTagUtils.create("US", name, "2029-12-12", "Transferred Data", TestUtils.getMyDataPartition(), null);
+        legalTagUtils.getResult(response, 201, LegalTagUtils.ReadableLegalTag.class);
+    }
+
+    @Test
+    public void should_createLegalTag_when_expDateNotSupplied_and_dataTypeIsTranferred() throws Exception{
+        ClientResponse response = legalTagUtils.create("US", name, null, "Transferred Data", TestUtils.getMyDataPartition(), "my desc");
+        LegalTagUtils.ReadableLegalTag lt =legalTagUtils.getResult(response, 201, LegalTagUtils.ReadableLegalTag.class);
+        assertEquals(name, lt.name);
+        assertTrue(lt.name.contains(TestUtils.getMyDataPartition()));
+    }
+
+    @Test
+    public void should_allowCreationOfALegalTag_when_countryOfOriginIsSetToAnUnrestrictedCountry_andThen_notAllowCreationOfARecordWithTheSameKind() throws Exception {
+        ClientResponse response = legalTagUtils.create("US", name);
+        LegalTagUtils.ReadableLegalTag readableLegalTags = legalTagUtils.getResult(response, 201, LegalTagUtils.ReadableLegalTag.class);
+        assertEquals(name, readableLegalTags.name);
+
+        response = legalTagUtils.create("US", name);
+        String error = legalTagUtils.getResult(response, 409, String.class);
+        assertTrue(error.contains("\"message\":\"A LegalTag already exists for the given name"));
+    }
+
+    @Test
+    public void should_return400_CreationOfALegalTag_when_countryOfOriginIsSetToDefaultResidencyRiskCountry_andThen_None_ofThe_Datatype_is_exluded_from_Dataresidency() throws Exception {
+        ClientResponse response = legalTagUtils.create("MX", name);
+        String messageResponse = legalTagUtils.getResult(response, 400, String.class);
+        assertEquals("{\"code\":400,\"reason\":\"Validation error.\",\"message\":\"{\\\"errors\\\":[\\\"Invalid country of origin set. It should match one of the ISO alpha 2 codes and be a country with no restriction on data residency. Found: [MX].\\\"]}\"}", messageResponse);
+    }
+
+    @Test
+    public void should_allowCreationOfALegalTag_when_countryOfOriginIsSetToDefaultResidencyRiskCountry_andThen_input_Datatype_is_exluded_from_Dataresidency() throws Exception {
+        ClientResponse response = legalTagUtils.create("GG", name,"Transferred Data");
+        LegalTagUtils.ReadableLegalTag readableLegalTags = legalTagUtils.getResult(response, 201, LegalTagUtils.ReadableLegalTag.class);
+        assertEquals(name, readableLegalTags.name);
+        assertEquals("Transferred Data", readableLegalTags.properties.dataType);
+    }
+    @Test
+    public void should_allowCreationOfALegalTag_when_countryOfOriginIsSetToNoRestrictionCountry_andThen_input_Datatype_is_not_exluded_from_Dataresidency() throws Exception {
+        ClientResponse response = legalTagUtils.create("TH", name, "First Party Data");
+        LegalTagUtils.ReadableLegalTag readableLegalTags = legalTagUtils.getResult(response, 201, LegalTagUtils.ReadableLegalTag.class);
+        assertEquals(name, readableLegalTags.name);
+        assertEquals("First Party Data", readableLegalTags.properties.dataType);
+    }
+    @Test
+    public void should_allowCreationOfALegalTag_when_countryOfOriginIsSetToNoRestrictionCountry_andThen_input_Datatype_is_exluded_from_Dataresidency() throws Exception {
+        ClientResponse response = legalTagUtils.create("JP", name, "Transferred Data");
+        LegalTagUtils.ReadableLegalTag readableLegalTags = legalTagUtils.getResult(response, 201, LegalTagUtils.ReadableLegalTag.class);
+        assertEquals(name, readableLegalTags.name);
+        assertEquals("Transferred Data", readableLegalTags.properties.dataType);
+    }
+    @Test
+    public void should_allowCreationOfALegalTag_when_countryOfOriginIsSetToNotAssignedCountry_andThen_input_Datatype_is_not_exluded_from_Dataresidency() throws Exception {
+        ClientResponse response = legalTagUtils.create("JP", name, "First Party Data");
+        LegalTagUtils.ReadableLegalTag readableLegalTags = legalTagUtils.getResult(response, 201, LegalTagUtils.ReadableLegalTag.class);
+        assertEquals(name, readableLegalTags.name);
+        assertEquals("First Party Data", readableLegalTags.properties.dataType);
+    }
+    @Test
+    public void should_allowCreationOfALegalTag_when_countryOfOriginIsSetToNotAssignedCountry_andThen_input__is_exluded_from_Dataresidency() throws Exception {
+        ClientResponse response = legalTagUtils.create("TH", name, "Transferred Data");
+        LegalTagUtils.ReadableLegalTag readableLegalTags = legalTagUtils.getResult(response, 201, LegalTagUtils.ReadableLegalTag.class);
+        assertEquals(name, readableLegalTags.name);
+        assertEquals("Transferred Data", readableLegalTags.properties.dataType);
+    }
+
+    // following two tests prove the older version config file in tenant would also work
+    @Test
+    public void should_allowCreationOfALegalTag_When_countryOfOriginIsSetToClientConsentRequiredInTenant_andDataTypeIsTransferredData() throws Exception{
+        //legalTagUtils.uploadTenantTestingConfigFile();
+        ClientResponse response = legalTagUtils.create("MY", name, "Transferred Data");
+        LegalTagUtils.ReadableLegalTag readableLegalTags = legalTagUtils.getResult(response, 201, LegalTagUtils.ReadableLegalTag.class);
+        assertEquals(name, readableLegalTags.name);
+        assertEquals("Transferred Data", readableLegalTags.properties.dataType);
+    }
+
+    @Test
+    public void should_allowCreationOfALegalTag_When_countryOfOriginIsSetToClientConsentRequiredInTenant_andDataTypeIsFirstPartyData() throws Exception{
+        //legalTagUtils.uploadTenantTestingConfigFile();
+        ClientResponse response = legalTagUtils.create("MY", name, "First Party Data");
+        LegalTagUtils.ReadableLegalTag readableLegalTags = legalTagUtils.getResult(response, 201, LegalTagUtils.ReadableLegalTag.class);
+        
+        System.out.println(">>>" + readableLegalTags.name);
+        System.out.println(">>>" + readableLegalTags.properties.dataType);
+        
+        assertEquals(name, readableLegalTags.name);
+        assertEquals("First Party Data", readableLegalTags.properties.dataType);
+    }
+
+    @Test
+    public void should_return400_CreationOfALegalTag_when_countryOfOriginIsSetToEmbargoCountry_andThen_input_Datatype_is_exluded_from_Dataresidency() throws Exception {
+        ClientResponse response = legalTagUtils.create("IR", name, "Transferred Data");
+        String messageResponse = legalTagUtils.getResult(response, 400, String.class);
+        assertEquals("{\"code\":400,\"reason\":\"Validation error.\",\"message\":\"{\\\"errors\\\":[\\\"Invalid country of origin set. It should match one of the ISO alpha 2 codes and be a country with no restriction on data residency. Found: [IR].\\\"]}\"}", messageResponse);
+    }
+    @Test
+    public void should_onlyLetAMaximumOf1LegaltagBeCreated_when_tryingToCreateMultipleVersionsOfTheSameContractAtTheSameTime() throws Exception {
+        ExecutorService executor = Executors.newFixedThreadPool(10);
+        List<Callable<ClientResponse>> tasks = new ArrayList<>();
+
+        for (int i = 0; i < 10; i++) {
+            Callable<ClientResponse> task = () -> {
+                try {
+                    return legalTagUtils.create(name);
+                } catch (Exception ex) {
+                    return null;
+                }
+            };
+            tasks.add(task);
+        }
+
+        List<Future<ClientResponse>> responses = executor.invokeAll(tasks);
+        executor.shutdown();
+        executor.awaitTermination(20, TimeUnit.SECONDS);
+
+        int sucessResponseCount = 0;
+        int non409ErrorResponseCount = 0;
+        for (Future<ClientResponse> future : responses) {
+            if (future.get().getStatus() == 201)
+                sucessResponseCount++;
+            else if (future.get().getStatus() != 409)
+                non409ErrorResponseCount++;
+        }
+
+        assertTrue( sucessResponseCount <= 1 , "Expected 1 successful response. Actual " + sucessResponseCount);
+        assertEquals(0, non409ErrorResponseCount);
+    }
+
+    @Override
+    protected String getBody(){
+        return LegalTagUtils.getBody(COO, name);
+    }
+    @Override
+    protected String getApi() {
+        return "legaltags";
+    }
+    @Override
+    protected String getHttpMethod() {
+        return "POST";
+    }
+}
diff --git a/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/acceptancetests/DeleteLegalTagApiAcceptanceTests.java b/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/acceptancetests/DeleteLegalTagApiAcceptanceTests.java
new file mode 100644
index 0000000000000000000000000000000000000000..73f3db312f00e6e80be96a61ea683ac16eefca66
--- /dev/null
+++ b/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/acceptancetests/DeleteLegalTagApiAcceptanceTests.java
@@ -0,0 +1,55 @@
+package org.opengroup.osdu.legal.acceptancetests;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.opengroup.osdu.legal.util.AcceptanceBaseTest;
+import org.opengroup.osdu.legal.util.LegalTagUtils;
+
+public final class DeleteLegalTagApiAcceptanceTests extends AcceptanceBaseTest {
+
+    private String name;
+    
+    @BeforeEach
+    @Override
+    public void setup() throws Exception {
+        this.legalTagUtils = new LegalTagUtils();
+        super.setup();
+    }
+
+    @AfterEach
+    @Override
+    public void teardown() throws Exception {
+        super.teardown();
+        this.legalTagUtils = null;
+    }
+
+    @Test
+    public void should_return204_when_deletingAContractThatDoesNotExist() throws Exception{
+        name = LegalTagUtils.createRandomNameTenant();
+        validateAccess(204);
+    }
+
+    @Test
+    public void should_return204_when_deletingAContractThatDoesExist() throws Exception{
+        name = LegalTagUtils.createRandomNameTenant();
+        legalTagUtils.getResult(legalTagUtils.create(name), 201, String.class );
+        validateAccess(204);
+    }
+
+    @Test
+    public void should_return400_when_deletingAContractWithAnInvalidName() throws Exception{
+        name = "invalid*name";
+        send("", 400);
+    }
+
+    @Override
+    protected String getApi() {
+        return "legaltags/" + name;
+    }
+
+    @Override
+    protected String getHttpMethod() {
+        return "DELETE";
+    }
+}
diff --git a/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/acceptancetests/GetInfoApiAcceptanceTests.java b/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/acceptancetests/GetInfoApiAcceptanceTests.java
new file mode 100644
index 0000000000000000000000000000000000000000..6c8f5f41c7413337e9fffe1ea71a908093607a49
--- /dev/null
+++ b/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/acceptancetests/GetInfoApiAcceptanceTests.java
@@ -0,0 +1,68 @@
+package org.opengroup.osdu.legal.acceptancetests;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.http.HttpStatus;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.opengroup.osdu.legal.util.AcceptanceBaseTest;
+import org.opengroup.osdu.legal.util.LegalTagUtils;
+import org.opengroup.osdu.legal.util.VersionInfoUtils;
+
+import com.sun.jersey.api.client.ClientResponse;
+
+public final class GetInfoApiAcceptanceTests extends AcceptanceBaseTest {
+
+  private static final VersionInfoUtils VERSION_INFO_UTILS = new VersionInfoUtils();
+
+  @BeforeEach
+  @Override
+  public void setup() throws Exception {
+      this.legalTagUtils = new LegalTagUtils();
+      super.setup();
+  }
+
+  @AfterEach
+  @Override
+  public void teardown() throws Exception {
+      super.teardown();
+      this.legalTagUtils = null;
+  }
+  
+  @Test
+  public void should_returnInfo() throws Exception {
+    ClientResponse response = send(StringUtils.EMPTY, HttpStatus.SC_OK);
+    VersionInfoUtils.VersionInfo responseObject =
+        VERSION_INFO_UTILS.getVersionInfoFromResponse(response);
+
+    assertNotNull(responseObject.groupId);
+    assertNotNull(responseObject.artifactId);
+    assertNotNull(responseObject.version);
+    assertNotNull(responseObject.buildTime);
+    assertNotNull(responseObject.branch);
+    assertNotNull(responseObject.commitId);
+    assertNotNull(responseObject.commitMessage);
+  }
+
+  @Override
+  protected String getApi() {
+    return "info";
+  }
+
+  @Override
+  protected String getHttpMethod() {
+    return "GET";
+  }
+
+  @Override
+  public void should_return307_when_makingHttpRequest() throws Exception {
+    // not actual for this endpoint
+  }
+
+  @Override
+  public void should_return401_when_makingHttpRequestWithoutToken() throws Exception {
+    // not actual for this endpoint
+  }
+}
diff --git a/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/acceptancetests/GetLegalTagApiAcceptanceTests.java b/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/acceptancetests/GetLegalTagApiAcceptanceTests.java
new file mode 100644
index 0000000000000000000000000000000000000000..449b7c553ef4494ff84fedb6464f6b6dbb1fe4a5
--- /dev/null
+++ b/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/acceptancetests/GetLegalTagApiAcceptanceTests.java
@@ -0,0 +1,124 @@
+package org.opengroup.osdu.legal.acceptancetests;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.Map;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.opengroup.osdu.legal.util.AcceptanceBaseTest;
+import org.opengroup.osdu.legal.util.LegalTagUtils;
+import org.opengroup.osdu.legal.util.TestUtils;
+
+import com.sun.jersey.api.client.ClientResponse;
+
+public final class GetLegalTagApiAcceptanceTests extends AcceptanceBaseTest {
+
+    private String name;
+    
+    @BeforeEach
+    @Override
+    public void setup() throws Exception {
+        this.legalTagUtils = new LegalTagUtils();
+        super.setup();
+    }
+
+    @AfterEach
+    @Override
+    public void teardown() throws Exception {
+        super.teardown();
+        this.legalTagUtils = null;
+    }
+    
+    @Test
+    public void should_return400Error_when_givingInvalidName()throws Exception{
+        name = "invalid*name";
+        validateAccess(400);
+    }
+
+    @Test
+    public void should_return404_when_givenNonExistingName()throws Exception{
+        name = TestUtils.getMyDataPartition() + "-iDoNotExist";
+        validateAccess(404);
+    }
+
+    @Test
+    public void should_returnDefaultExpirationDate_when_expirationDateIsNotProvided() throws Exception{
+        name = LegalTagUtils.createRandomNameTenant();
+        ClientResponse resp = legalTagUtils.create("US", name, "", "Transferred Data", TestUtils.getMyDataPartition(), null);
+        LegalTagUtils.ReadableLegalTag result = legalTagUtils.getResult(resp, 201, LegalTagUtils.ReadableLegalTag.class);
+        assertEquals("9999-12-31", result.properties.expirationDate);
+        legalTagUtils.delete(name);
+    }
+
+    @Test
+    public void should_beAbleToRetrieveLegalTag_when_tenantIsAutomaticallyAppendedOnCreation() throws Exception {
+        name = LegalTagUtils.createRandomNameTenant();
+        ClientResponse response = legalTagUtils.create("US", name, "2099-12-25", "Third Party Data");
+        legalTagUtils.getResult(response, 201, String.class);
+
+        Map<String, String> headers = legalTagUtils.getHeaders();
+        response = legalTagUtils.send("legaltags/" + name, "GET",
+                legalTagUtils.accessToken(), "", "", headers);
+        legalTagUtils.getResult(response, 200, LegalTagUtils.ReadableLegalTag.class);
+        legalTagUtils.delete(name);
+    }
+
+    @Test
+    public void should_beAbleToRetrieveLegalTag_when_tenantIsAutomaticallyAppendedOnCreation_withTrailingSlash() throws Exception {
+        name = LegalTagUtils.createRandomNameTenant();
+        ClientResponse response = legalTagUtils.create("US", name, "2099-12-25", "Third Party Data");
+        legalTagUtils.getResult(response, 201, String.class);
+
+        Map<String, String> headers = legalTagUtils.getHeaders();
+        response = legalTagUtils.send("legaltags/" + name + "/", "GET",
+                legalTagUtils.accessToken(), "", "", headers);
+        legalTagUtils.getResult(response, 200, LegalTagUtils.ReadableLegalTag.class);
+        legalTagUtils.delete(name);
+    }
+
+    @Test
+    public void should_retrieveLegalTag_when_givenExistingName() throws Exception {
+        name = LegalTagUtils.createRandomNameTenant();
+        ClientResponse result = legalTagUtils.create("US", name);
+        legalTagUtils.getResult(result, 201, LegalTagUtils.ReadableLegalTag.class);
+
+        ClientResponse response = send("", 200, "", TestUtils.getMyDataPartition());
+        LegalTagUtils.ReadableLegalTag legalTag = legalTagUtils.getResult(response, 200, LegalTagUtils.ReadableLegalTag.class);
+
+        assertEquals(name, legalTag.name);
+        assertEquals("<my description>", legalTag.description);
+
+        assertEquals("A1234", legalTag.properties.contractId);
+        assertEquals("US", legalTag.properties.countryOfOrigin[0]);
+        assertEquals("Transferred Data", legalTag.properties.dataType);
+        assertEquals("EAR99", legalTag.properties.exportClassification);
+        assertEquals("2099-12-25", legalTag.properties.expirationDate);
+        assertEquals("MyCompany", legalTag.properties.originator);
+        assertEquals("No Personal Data", legalTag.properties.personalData);
+        assertEquals("Public", legalTag.properties.securityClassification);
+
+        legalTagUtils.delete(name);
+    }
+
+    @Test
+    @Override
+    public void should_return401_when_makingHttpRequestWithoutToken()throws Exception{
+        name = LegalTagUtils.createRandomNameTenant();
+        super.should_return401_when_makingHttpRequestWithoutToken();
+    }
+
+    @Override
+    protected String getBody(){
+        return "";
+    }
+    @Override
+    protected String getApi() {
+        return "legaltags/" + name;
+    }
+    @Override
+    protected String getHttpMethod() {
+        return "GET";
+    }
+}
diff --git a/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/acceptancetests/GetLegalTagPropertiesApiAcceptanceTests.java b/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/acceptancetests/GetLegalTagPropertiesApiAcceptanceTests.java
new file mode 100644
index 0000000000000000000000000000000000000000..bed1d125353a9d6afd42b85c435e9488e92c3104
--- /dev/null
+++ b/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/acceptancetests/GetLegalTagPropertiesApiAcceptanceTests.java
@@ -0,0 +1,67 @@
+package org.opengroup.osdu.legal.acceptancetests;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.opengroup.osdu.legal.util.AcceptanceBaseTest;
+import org.opengroup.osdu.legal.util.LegalTagUtils;
+
+import com.sun.jersey.api.client.ClientResponse;
+
+public final class GetLegalTagPropertiesApiAcceptanceTests extends AcceptanceBaseTest {
+
+	@BeforeEach
+    @Override
+    public void setup() throws Exception {
+        this.legalTagUtils = new LegalTagUtils();
+        super.setup();
+    }
+
+    @AfterEach
+    @Override
+    public void teardown() throws Exception {
+        super.teardown();
+        this.legalTagUtils = null;
+    }
+    
+    @Test
+    public void should_returnAllLegalTagProperties_when_getPropertiesApi() throws Exception {
+        ClientResponse response = send("", 200);
+        LegalTagUtils.ReadablePropertyValues result = legalTagUtils.getResult(response, 200,
+                LegalTagUtils.ReadablePropertyValues.class);
+
+        System.out.println(result);
+        assertTrue(result.countriesOfOrigin.size() > 0);
+        assertTrue(result.countriesOfOrigin.containsKey("US"));
+
+        assertTrue(result.otherRelevantDataCountries.size() > 0);
+        assertTrue(result.otherRelevantDataCountries.containsKey("FR"));
+
+        assertTrue(result.personalDataTypes.size() > 0);
+        assertTrue(result.personalDataTypes.contains("No Personal Data"));
+
+        assertTrue(result.securityClassifications.size() > 0);
+        assertTrue(result.securityClassifications.contains("Private"));
+
+        assertTrue(result.exportClassificationControlNumbers.size() > 0);
+        assertTrue(result.exportClassificationControlNumbers.contains("EAR99"));
+
+        assertTrue(result.dataTypes.size() > 0);
+        assertTrue(result.dataTypes.contains("First Party Data"));
+    }
+
+    @Override
+    protected String getBody(){
+        return "";
+    }
+    @Override
+    protected String getApi() {
+        return "legaltags:properties";
+    }
+    @Override
+    protected String getHttpMethod() {
+        return "GET";
+    }
+}
diff --git a/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/acceptancetests/GetLegalTagsApiAcceptanceTests.java b/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/acceptancetests/GetLegalTagsApiAcceptanceTests.java
new file mode 100644
index 0000000000000000000000000000000000000000..5981b24a3763862b7f9d11dcad0c8ee8962a7585
--- /dev/null
+++ b/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/acceptancetests/GetLegalTagsApiAcceptanceTests.java
@@ -0,0 +1,104 @@
+package org.opengroup.osdu.legal.acceptancetests;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.Arrays;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.opengroup.osdu.legal.util.AcceptanceBaseTest;
+import org.opengroup.osdu.legal.util.LegalTagUtils;
+import org.opengroup.osdu.legal.util.TestUtils;
+
+import com.sun.jersey.api.client.ClientResponse;
+
+public final class GetLegalTagsApiAcceptanceTests extends AcceptanceBaseTest {
+
+    private String name;
+
+    static protected String wellKnownName = LegalTagUtils.getMyDataPartition() + "-" + LegalTagUtils.createRandomNameTenant();
+
+    @BeforeEach
+    @Override
+    public void setup() throws Exception {
+        this.legalTagUtils = new LegalTagUtils();
+        super.setup();
+        ClientResponse response = legalTagUtils.create("US", wellKnownName);
+        legalTagUtils.getResult(response, 201, LegalTagUtils.ReadableLegalTag.class);
+    }
+
+    @AfterEach
+    public void teardown() throws Exception {
+        legalTagUtils.delete(wellKnownName);
+        super.teardown();
+        this.legalTagUtils = null;
+    }
+
+    @Test
+    public void should_return400Error_when_givingInvalidName()throws Exception{
+        name = "invalid*name";
+        validateAccess(400);
+    }
+
+    @Test
+    public void should_return404_when_givenNonExistingName()throws Exception{
+        name = TestUtils.getMyDataPartition() + "-iDoNotExist";
+        validateAccess(404);
+    }
+
+    @Test
+    public void should_return200_when_userHasApiAccess() throws Exception{
+        name = wellKnownName;
+        validateAccess(200);
+    }
+
+    @Test
+    public void should_return200onBatchRetrieve_when_userHasApiAccess() throws Exception {
+        String wellKnownName2 = LegalTagUtils.getMyDataPartition() + "-" + LegalTagUtils.createRandomNameTenant();
+        ClientResponse response = legalTagUtils.create("US", wellKnownName2);
+        legalTagUtils.getResult(response, 201, LegalTagUtils.ReadableLegalTag.class);
+
+        response = legalTagUtils.send("legaltags:batchRetrieve", "POST", legalTagUtils.accessToken(),
+                LegalTagUtils.createRetrieveBatchBody(wellKnownName, wellKnownName2), "");
+
+        LegalTagUtils.ReadableLegalTags legalTags = legalTagUtils.getResult(response, 200, LegalTagUtils.ReadableLegalTags.class);
+        assertEquals(2, legalTags.legalTags.length);
+
+        LegalTagUtils.ReadableLegalTag legalTag = Arrays.stream(legalTags.legalTags).filter(f -> f.name.equals(wellKnownName)).findFirst().get();
+        assertEquals(wellKnownName, legalTag.name);
+        assertEquals("A1234", legalTag.properties.contractId);
+        assertEquals("US", legalTag.properties.countryOfOrigin[0]);
+        assertEquals(1, legalTag.properties.countryOfOrigin.length);
+        assertEquals("Transferred Data", legalTag.properties.dataType);
+        assertEquals("EAR99", legalTag.properties.exportClassification);
+        assertEquals("MyCompany", legalTag.properties.originator);
+        assertEquals("No Personal Data", legalTag.properties.personalData);
+        assertEquals("Public", legalTag.properties.securityClassification);
+
+        LegalTagUtils.ReadableLegalTag legalTag2 = Arrays.stream(legalTags.legalTags).filter(f -> f.name.equals(wellKnownName2)).findFirst().get();
+        assertEquals(wellKnownName2, legalTag2.name);
+        legalTagUtils.delete(wellKnownName2);
+    }
+
+    @Test
+    @Override
+    public void should_return401_when_makingHttpRequestWithoutToken()throws Exception{
+        name = LegalTagUtils.createRandomNameTenant();
+        super.should_return401_when_makingHttpRequestWithoutToken();
+    }
+
+    @Override
+    protected String getBody(){
+        return LegalTagUtils.createRetrieveBatchBody(name);
+    }
+    @Override
+    protected String getApi() {
+        return "legaltags:batchRetrieve";
+    }
+
+    @Override
+    protected String getHttpMethod() {
+        return "POST";
+    }
+}
diff --git a/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/acceptancetests/ListLegalTagsApiAcceptanceTests.java b/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/acceptancetests/ListLegalTagsApiAcceptanceTests.java
new file mode 100644
index 0000000000000000000000000000000000000000..7c1fd602a67ac0058d7974db4bed4aab9814834d
--- /dev/null
+++ b/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/acceptancetests/ListLegalTagsApiAcceptanceTests.java
@@ -0,0 +1,78 @@
+package org.opengroup.osdu.legal.acceptancetests;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.Arrays;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.opengroup.osdu.legal.util.AcceptanceBaseTest;
+import org.opengroup.osdu.legal.util.LegalTagUtils;
+import org.opengroup.osdu.legal.util.TestUtils;
+
+import com.google.common.base.Strings;
+import com.sun.jersey.api.client.ClientResponse;
+
+public final class ListLegalTagsApiAcceptanceTests extends AcceptanceBaseTest {
+
+	@BeforeEach
+    @Override
+    public void setup() throws Exception {
+        this.legalTagUtils = new LegalTagUtils();
+        super.setup();
+    }
+
+    @AfterEach
+    @Override
+    public void teardown() throws Exception {
+        super.teardown();
+        this.legalTagUtils = null;
+    }
+    
+    @Test
+    public void should_return200_and_allValidLegalTags_when_sendingValidTrueParamter_And_notSendingValidParameter()throws Exception{
+        ClientResponse response = send("", 200, "?valid=true", TestUtils.getMyDataPartition());
+        LegalTagUtils.ReadableLegalTags result = legalTagUtils.getResult(response, 200, LegalTagUtils.ReadableLegalTags.class);
+        System.out.println("number of lts:" + result.legalTags.length ) ;
+        assertTrue(result.legalTags.length > 0);
+        assertFalse(Strings.isNullOrEmpty(result.legalTags[0].name));
+        assertFalse(Strings.isNullOrEmpty(result.legalTags[0].properties.countryOfOrigin[0]));
+
+        ClientResponse response2 = send("", 200, "");
+        LegalTagUtils.ReadableLegalTags result2 = legalTagUtils.getResult(response2, 200, LegalTagUtils.ReadableLegalTags.class);
+        for(LegalTagUtils.ReadableLegalTag tag : result.legalTags){
+            assertTrue(Arrays.stream(result2.legalTags).anyMatch(s -> tag.name.equals(s.name)));
+        }
+    }
+
+    @Test
+    public void should_returnDifferentResults_when_sendingValidParamterTrueOrFalse()throws Exception{
+        ClientResponse response = send("", 200, "?valid=true");
+        LegalTagUtils.ReadableLegalTags result = legalTagUtils.getResult(response, 200, LegalTagUtils.ReadableLegalTags.class);
+
+        ClientResponse response2 = send("", 200, "?valid=false");
+        LegalTagUtils.ReadableLegalTags result2 = legalTagUtils.getResult(response2, 200, LegalTagUtils.ReadableLegalTags.class);
+        assertNotEquals(result.legalTags.length, result2.legalTags.length);
+        for(LegalTagUtils.ReadableLegalTag tag : result.legalTags){
+            assertFalse(Arrays.stream(result2.legalTags).anyMatch(s -> tag.name.equals(s.name)));
+        }
+    }
+
+    @Override
+    protected String getBody(){
+        return "";
+    }
+
+    @Override
+    protected String getApi() {
+        return "legaltags";
+    }
+
+    @Override
+    protected String getHttpMethod() {
+        return "GET";
+    }
+}
diff --git a/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/acceptancetests/QueryLegalTagsApiAcceptanceTests.java b/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/acceptancetests/QueryLegalTagsApiAcceptanceTests.java
new file mode 100644
index 0000000000000000000000000000000000000000..6d827f64d0e8678fb4072cef70155562dd32ab1c
--- /dev/null
+++ b/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/acceptancetests/QueryLegalTagsApiAcceptanceTests.java
@@ -0,0 +1,221 @@
+package org.opengroup.osdu.legal.acceptancetests;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.opengroup.osdu.legal.util.AcceptanceBaseTest;
+import org.opengroup.osdu.legal.util.LegalTagUtils;
+import org.opengroup.osdu.legal.util.TestUtils;
+
+import com.sun.jersey.api.client.ClientResponse;
+
+public final class QueryLegalTagsApiAcceptanceTests extends AcceptanceBaseTest {
+
+    private String name;
+    private static final List<Integer> OK_VALUES = Arrays.asList(200, 405);
+    private static final List<Integer> BAD_REQUEST_VALUES = Arrays.asList(400, 405);
+
+    @BeforeEach
+    @Override
+    public void setup() throws Exception {
+        this.legalTagUtils = new LegalTagUtils();
+        super.setup();
+    }
+
+    @AfterEach
+    @Override
+    public void teardown() throws Exception {
+        super.teardown();
+        this.legalTagUtils = null;
+    }
+    
+    @Test
+    public void should_return400Error_when_givingInvalidPayload1() throws Exception {
+        ClientResponse response = send("{\"notValid\":\"payload\"}", "?valid=true", TestUtils.getMyDataPartition());
+        assertTrue(BAD_REQUEST_VALUES.contains(response.getStatus()), 
+        		String.format("Expected a 400 or 405, but got %d", response.getStatus()));
+    }
+
+    @Test
+    public void should_return200E_when_giving_empty_queryList() throws Exception {
+        ClientResponse response = send("{\"queryList\":[]}", "?valid=true", TestUtils.getMyDataPartition());
+        assertTrue(OK_VALUES.contains(response.getStatus()));
+    }
+
+    @Test
+    public void should_return400Error_when_givingInvalidPayload_no_query_string() throws Exception {
+        ClientResponse response = send("{\"queryList\":[\"name=\"]}", "?valid=true", TestUtils.getMyDataPartition());
+        assertTrue(BAD_REQUEST_VALUES.contains(response.getStatus()));
+    }
+
+    @Test
+    public void should_return200_when_giving_notfound_queryList1() throws Exception {
+        ClientResponse response = send("{\"queryList\":[\"name==notfound\"]}", "?valid=true", TestUtils.getMyDataPartition());
+        assertTrue(OK_VALUES.contains(response.getStatus()));
+    }
+
+    @Test
+    public void should_return200_when_giving_notfound_queryList2() throws Exception {
+        ClientResponse response = send("{\"queryList\":[\"name=notfound\"]}", "?valid=true", TestUtils.getMyDataPartition());
+        assertTrue(OK_VALUES.contains(response.getStatus()));
+    }
+
+    @Test
+    public void should_return200_queryList_countryOfOrigin() throws Exception {
+        ClientResponse response = send("{\"queryList\":[\"countryOfOrigin=US\"]}", "?valid=true", TestUtils.getMyDataPartition());
+        assertTrue(OK_VALUES.contains(response.getStatus()));
+    }
+
+    @Test
+    public void should_return200_queryList_dataType() throws Exception {
+        ClientResponse response = send("{\"queryList\":[\"dataType=public\"]}", "?valid=true", TestUtils.getMyDataPartition());
+        assertTrue(OK_VALUES.contains(response.getStatus()));
+    }
+
+    @Test
+    public void should_return200_queryList_personalData1() throws Exception {
+        ClientResponse response = send("{\"queryList\":[\"personalData=No\"]}", "?valid=true", TestUtils.getMyDataPartition());
+        assertTrue(OK_VALUES.contains(response.getStatus()));
+    }
+
+    @Test
+    public void should_return200_queryList_personalData2() throws Exception {
+        ClientResponse response = send("{\"queryList\":[\"personalData=No Personal\"]}", "?valid=true", TestUtils.getMyDataPartition());
+        assertTrue(OK_VALUES.contains(response.getStatus()));
+    }
+
+    @Test
+    public void should_return200_queryList_exportClassification() throws Exception {
+        ClientResponse response = send("{\"queryList\":[\"exportClassification=EAR99\"]}", "?valid=true", TestUtils.getMyDataPartition());
+        assertTrue(OK_VALUES.contains(response.getStatus()));
+    }
+
+    @Test
+    public void should_return200_queryList_expirationDate() throws Exception {
+        ClientResponse response = send("{\"queryList\":[\"expirationDate between (2023-01-01, 2099-12-31)\"]}", "?valid=true", TestUtils.getMyDataPartition());
+        assertTrue(OK_VALUES.contains(response.getStatus()));
+    }
+
+    @Test
+    public void should_return400Error_when_givingInvalidPayload_no_attribute() throws Exception {
+        ClientResponse response = send("{\"queryList\":[\"=test\"]}", "?valid=true", TestUtils.getMyDataPartition());
+        assertTrue(BAD_REQUEST_VALUES.contains(response.getStatus()));
+    }
+
+    @Test
+    public void should_return200_with_match_name_operator_union_strange() throws Exception {
+        ClientResponse response = send("{\"queryList\":[\"name=*?\"],\"operatorList\":[\"union\"]}", "?valid=true", TestUtils.getMyDataPartition());
+        assertTrue(OK_VALUES.contains(response.getStatus()));
+    }
+
+    @Test
+    public void should_return200_with_match_name_without_operator() throws Exception {
+        ClientResponse response = send("{\"queryList\":[\"name=test\"]}", "?valid=true", TestUtils.getMyDataPartition());
+        assertTrue(OK_VALUES.contains(response.getStatus()));
+    }
+
+    @Test
+    public void should_return200_with_match_name_operator_union() throws Exception {
+        ClientResponse response = send("{\"queryList\":[\"name=test\"],\"operatorList\":[\"union\"]}", "?valid=true", TestUtils.getMyDataPartition());
+        assertTrue(OK_VALUES.contains(response.getStatus()));
+    }
+
+    @Test
+    public void should_return200_with_match_name_operator_intersection() throws Exception {
+        ClientResponse response = send("{\"queryList\":[\"name=test\"],\"operatorList\":[\"intersection\"]}", "?valid=true", TestUtils.getMyDataPartition());
+        assertTrue(OK_VALUES.contains(response.getStatus()));
+    }
+
+    @Test
+    public void should_return200_with_match_name_operator_add() throws Exception {
+        ClientResponse response = send("{\"queryList\":[\"name=test\"],\"operatorList\":[\"add\"]}", "?valid=true", TestUtils.getMyDataPartition());
+        assertTrue(OK_VALUES.contains(response.getStatus()));
+    }
+
+    @Test
+    public void should_return200_with_match_name_operator_add_with_two() throws Exception {
+        ClientResponse response = send("{\"queryList\":[\"name=test\", \"description=test\"],\"operatorList\":[\"add\"]}", "?valid=true", TestUtils.getMyDataPartition());
+        assertTrue(OK_VALUES.contains(response.getStatus()));
+    }
+
+    @Test
+    public void should_return200_with_match_name_operator_union_with_two1() throws Exception {
+        ClientResponse response = send("{\"queryList\":[\"name=test\", \"description=test\"],\"operatorList\":[\"union\"]}", "?valid=true", TestUtils.getMyDataPartition());
+        assertTrue(OK_VALUES.contains(response.getStatus()));
+    }
+
+    @Test
+    public void should_return200_with_match_name_operator_intersection_with_two() throws Exception {
+        ClientResponse response = send("{\"queryList\":[\"name=test\", \"description=test\"],\"operatorList\":[\"intersection\"]}", "?valid=true", TestUtils.getMyDataPartition());
+        assertTrue(OK_VALUES.contains(response.getStatus()));
+    }
+
+    @Test
+    public void should_return200_with_match_name_operator_intersection_with_three() throws Exception {
+        ClientResponse response = send("{\"queryList\":[\"name=test\", \"description=test\", \"exportClassification=EAR99\"],\"operatorList\":[\"intersection\"]}", "?valid=true", TestUtils.getMyDataPartition());
+        assertTrue(OK_VALUES.contains(response.getStatus()));
+    }
+
+    @Test
+    public void should_return200_with_match_name_operator_union_with_three() throws Exception {
+        ClientResponse response = send("{\"queryList\":[\"name=test\", \"description=test\", \"exportClassification=EAR99\"],\"operatorList\":[\"union\"]}", "?valid=true", TestUtils.getMyDataPartition());
+        assertTrue(OK_VALUES.contains(response.getStatus()));
+    }
+
+    @Test
+    public void should_return200_free_text1() throws Exception {
+        ClientResponse response = send("{\"queryList\":[\"any=test\"]}", "?valid=true", TestUtils.getMyDataPartition());
+        assertTrue(OK_VALUES.contains(response.getStatus()));
+    }
+
+    @Test
+    public void should_return200_free_text2() throws Exception {
+        ClientResponse response = send("{\"queryList\":[\"test\"]}", "?valid=true", TestUtils.getMyDataPartition());
+        assertTrue(OK_VALUES.contains(response.getStatus()));
+    }
+
+    @Test
+    public void should_return200_with_match_name_operator_union_with_two2() throws Exception {
+        ClientResponse response = send("{\"queryList\":[\"name=test\", \"description=test\"],\"operatorList\":[\"union\"]}", "?valid=true", TestUtils.getMyDataPartition());
+        assertTrue(OK_VALUES.contains(response.getStatus()));
+    }
+
+    @Test
+    public void should_return200_attribute_does_not_exist() throws Exception {
+        ClientResponse response = send("{\"queryList\":[\"doesnotexist=test\"],\"operatorList\":[\"union\"]}", "?valid=true", TestUtils.getMyDataPartition());
+        assertTrue(OK_VALUES.contains(response.getStatus()));
+    }
+
+    @Test
+    public void should_return200_extension_properties() throws Exception {
+        ClientResponse response = send("{\"queryList\":[\"AgreementPartyType=enabled\"],\"operatorList\":[\"union\"]}", "?valid=true", TestUtils.getMyDataPartition());
+        assertTrue(OK_VALUES.contains(response.getStatus()));
+    }
+
+    @Test
+    @Override
+    public void should_return401_when_makingHttpRequestWithoutToken()throws Exception{
+        name = LegalTagUtils.createRandomNameTenant();
+        super.should_return401_when_makingHttpRequestWithoutToken();
+    }
+
+    @Override
+    protected String getBody() {
+        return LegalTagUtils.createRetrieveBatchBody(name);
+    }
+
+    @Override
+    protected String getApi() {
+        return "legaltags:query";
+    }
+
+    @Override
+    protected String getHttpMethod() {
+        return "POST";
+    }
+}
\ No newline at end of file
diff --git a/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/acceptancetests/UpdateLegalTagApiAcceptanceTests.java b/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/acceptancetests/UpdateLegalTagApiAcceptanceTests.java
new file mode 100644
index 0000000000000000000000000000000000000000..2726c1c452699c34d3603d3a6c9a61c0d44a4e18
--- /dev/null
+++ b/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/acceptancetests/UpdateLegalTagApiAcceptanceTests.java
@@ -0,0 +1,88 @@
+package org.opengroup.osdu.legal.acceptancetests;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.opengroup.osdu.legal.util.Constants.DATA_PARTITION_ID;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.opengroup.osdu.legal.util.AcceptanceBaseTest;
+import org.opengroup.osdu.legal.util.LegalTagUtils;
+import org.opengroup.osdu.legal.util.TestUtils;
+
+import com.sun.jersey.api.client.ClientResponse;
+
+public final class UpdateLegalTagApiAcceptanceTests extends AcceptanceBaseTest {
+
+    static private String defaultName = LegalTagUtils.createRandomNameTenant();
+    private String name;
+    private String expDate;
+
+    @BeforeEach
+    @Override
+    public void setup() throws Exception {
+        this.legalTagUtils = new LegalTagUtils();
+        super.setup();
+        legalTagUtils.create(defaultName);
+        name = defaultName;
+        expDate = "2199-12-25";
+    }
+
+    @AfterEach
+    @Override
+    public void teardown() throws Exception{
+        legalTagUtils.delete(defaultName);
+        super.teardown();
+        this.legalTagUtils = null;
+    }
+
+    @Test
+    public void should_returnOk_and_updateProperties_when_userUpdatesExistingLegalTags() throws Exception{
+        Map<String, String> headers = new HashMap<>();
+        headers.put(DATA_PARTITION_ID, TestUtils.getMyDataPartition());
+        ClientResponse response = legalTagUtils.send(this.getApi(), this.getHttpMethod(), legalTagUtils.accessToken(), getBody(), getQuery(), headers);
+        LegalTagUtils.ReadableLegalTag result = legalTagUtils.getResult(response, 200, LegalTagUtils.ReadableLegalTag.class);
+
+        assertEquals("B1234", result.properties.contractId);
+        assertEquals("2199-12-25", result.properties.expirationDate);
+        assertEquals(name, result.name);
+    }
+    @Test
+    public void should_return400_when_userHasGivenInvalidExpDate() throws Exception{
+        expDate = "2010-12-31"; //set expired date
+        ClientResponse response = legalTagUtils.send(this.getApi(), this.getHttpMethod(), legalTagUtils.accessToken(), getBody(), getQuery());
+        String error = legalTagUtils.getResult(response, 400, String.class);
+        assertEquals("{\"code\":400,\"reason\":\"Validation error.\",\"message\":\"{\\\"errors\\\":[\\\"Expiration date must be a value in the future. Given 2010-12-31\\\"]}\"}", error);
+    }
+
+    @Test
+    public void should_return400_when_givenEmptyBody() throws Exception{
+        ClientResponse response = legalTagUtils.send(this.getApi(), this.getHttpMethod(), legalTagUtils.accessToken(), "{}", getQuery());
+        assertEquals(400, response.getStatus());
+    }
+
+    @Test
+    public void should_return404_when_givenLegalTagToUpdateThatDoesNotExist() throws Exception{
+        name = LegalTagUtils.createRandomNameTenant();
+        ClientResponse response = legalTagUtils.send(this.getApi(), this.getHttpMethod(), legalTagUtils.accessToken(), getBody(), getQuery());
+        assertEquals(404, response.getStatus());
+    }
+
+    @Override
+    protected String getBody(){
+        return LegalTagUtils.updateBody(name, expDate);
+    }
+
+    @Override
+    protected String getApi() {
+        return "legaltags";
+    }
+
+    @Override
+    protected String getHttpMethod() {
+        return "PUT";
+    }
+}
diff --git a/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/acceptancetests/ValidateLegalTagsApiAcceptanceTests.java b/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/acceptancetests/ValidateLegalTagsApiAcceptanceTests.java
new file mode 100644
index 0000000000000000000000000000000000000000..e531d8dd25def69fb0cb7e341d269af4f5a54255
--- /dev/null
+++ b/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/acceptancetests/ValidateLegalTagsApiAcceptanceTests.java
@@ -0,0 +1,109 @@
+package org.opengroup.osdu.legal.acceptancetests;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+import org.opengroup.osdu.legal.util.AcceptanceBaseTest;
+import org.opengroup.osdu.legal.util.LegalTagUtils;
+
+import com.sun.jersey.api.client.ClientResponse;
+
+public final class ValidateLegalTagsApiAcceptanceTests extends AcceptanceBaseTest {
+
+    private String name;
+
+    @BeforeEach
+    @Override
+    public void setup() throws Exception {
+        this.legalTagUtils = new LegalTagUtils();
+        super.setup();
+    }
+
+    @AfterEach
+    @Override
+    public void teardown() throws Exception {
+        super.teardown();
+        this.legalTagUtils = null;
+    }
+    
+    @Test
+    public void should_return400Error_when_givingInvalidName() throws Exception {
+        name = "invalid*name";
+        validateAccess(400);
+    }
+
+    @Test
+    public void should_return200_withNoInvalidTagsReturned_when_userHasOnlyReadDataAccess() throws Exception {
+        name = LegalTagUtils.createRandomNameTenant();
+        ClientResponse response = legalTagUtils.create("US", name);
+        legalTagUtils.getResult(response, 201, LegalTagUtils.ReadableLegalTag.class);
+
+        response = send(LegalTagUtils.createRetrieveBatchBody(name), 200);
+
+        LegalTagUtils.InvalidTagsWithReason invalidTagsWithReason = legalTagUtils.getResult(response, 200, LegalTagUtils.InvalidTagsWithReason.class);
+        assertEquals(0, invalidTagsWithReason.invalidLegalTags.length);
+        legalTagUtils.delete(name);
+    }
+
+    @Test
+    public void should_return200_withNotFoundLegalTagNamesAndReason_when_givenNonexistingLegalTagNames() throws Exception {
+        name = LegalTagUtils.getMyDataPartition() + "-" + "iDoNotExist";
+
+        ClientResponse response = send(LegalTagUtils.createRetrieveBatchBody(name), 200);
+
+        LegalTagUtils.InvalidTagsWithReason invalidTagsWithReason = legalTagUtils.getResult(response, 200, LegalTagUtils.InvalidTagsWithReason.class);
+        assertEquals(1, invalidTagsWithReason.invalidLegalTags.length);
+
+        LegalTagUtils.InvalidTagWithReason invalidTagWithReason = invalidTagsWithReason.invalidLegalTags[0];
+        assertEquals(name, invalidTagWithReason.name);
+        assertEquals("LegalTag not found", invalidTagWithReason.reason);
+    }
+    
+//  Ignored due to not clear test requirements, original test did not create legal tag but expecting response with message "Expiration date must be a value in the future"
+    @Disabled 
+    @Test
+    public void should_return200_withLegalTagNamesAndInvalidExpirationDateReason_when_GivenExistingInvalidLegalTagNames() throws Exception {
+        // Manually created in all env cause compliance api is not allowed invalid legaltag creation.
+        name = "dps-integration-test-1566474656479";
+
+        // Use the following commented code to recreate the legaltag in case the previous invalid legaltag got deleted.
+        // You will need to manually change the expiration date to make the legaltag invalid in the datastore.
+//        ClientResponse response = LegalTagUtils.create("US", name);
+//        legalTagUtils.getResult(response, 201, LegalTagUtils.ReadableLegalTag.class);
+
+        ClientResponse response = send(LegalTagUtils.createRetrieveBatchBody(legalTagUtils.getMyDataPartition() + "-" + name), 200);
+
+        LegalTagUtils.InvalidTagsWithReason invalidTagsWithReason = legalTagUtils.getResult(response, 200, LegalTagUtils.InvalidTagsWithReason.class);
+        assertEquals(1, invalidTagsWithReason.invalidLegalTags.length);
+
+        LegalTagUtils.InvalidTagWithReason invalidTagWithReason = invalidTagsWithReason.invalidLegalTags[0];
+        assertEquals(legalTagUtils.getMyDataPartition() + "-" + name, invalidTagWithReason.name);
+        assertTrue(invalidTagWithReason.reason.startsWith("Expiration date must be a value in the future."));
+    }
+
+    @Test
+    @Override
+    public void should_return401_when_makingHttpRequestWithoutToken()throws Exception{
+        name = LegalTagUtils.createRandomNameTenant();
+        super.should_return401_when_makingHttpRequestWithoutToken();
+    }
+
+    @Override
+    protected String getBody() {
+        return LegalTagUtils.createRetrieveBatchBody(name);
+    }
+
+    @Override
+    protected String getApi() {
+        return "legaltags:validate";
+    }
+
+    @Override
+    protected String getHttpMethod() {
+        return "POST";
+    }
+}
diff --git a/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/swagger/Swagger.java b/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/swagger/Swagger.java
new file mode 100644
index 0000000000000000000000000000000000000000..e4b9ad5e311e730b18bbd76f434cfcca7cc6957e
--- /dev/null
+++ b/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/swagger/Swagger.java
@@ -0,0 +1,46 @@
+package org.opengroup.osdu.legal.swagger;
+
+import com.sun.jersey.api.client.ClientResponse;
+import org.apache.http.HttpStatus;
+import org.junit.jupiter.api.Test;
+import org.opengroup.osdu.legal.util.AcceptanceBaseTest;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public final class Swagger extends AcceptanceBaseTest {
+
+    protected static final String SWAGGER_API_PATH = "swagger";
+
+    @Test
+    public void shouldReturn200_whenSwaggerApiIsCalled() throws Exception {
+        ClientResponse response = legalTagUtils.send(SWAGGER_API_PATH, "GET", "", "", "");
+        assertEquals(HttpStatus.SC_OK, response.getStatus());
+    }
+
+    @Test
+    @Override
+    public void should_returnOk_when_makingHttpOptionsRequest() {
+        // not actual for this endpoint
+    }
+
+    @Test
+    public void should_return401_when_makingHttpRequestWithoutToken() throws Exception {
+        // not actual for this endpoint
+    }
+
+    @Test
+    public void should_return307_when_makingHttpRequest()throws Exception {
+        // not actual for this endpoint
+    }
+
+    @Override
+    protected String getApi() {
+        return SWAGGER_API_PATH;
+    }
+
+    @Override
+    protected String getHttpMethod() {
+        return "GET";
+    }
+
+}
diff --git a/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/swagger/SwaggerApiDocs.java b/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/swagger/SwaggerApiDocs.java
new file mode 100644
index 0000000000000000000000000000000000000000..65b2b0d299fb12eab957fc588be0f313c838bb36
--- /dev/null
+++ b/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/swagger/SwaggerApiDocs.java
@@ -0,0 +1,47 @@
+package org.opengroup.osdu.legal.swagger;
+
+import com.sun.jersey.api.client.ClientResponse;
+import org.apache.http.HttpStatus;
+import org.junit.jupiter.api.Test;
+import org.opengroup.osdu.legal.util.AcceptanceBaseTest;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public final class SwaggerApiDocs extends AcceptanceBaseTest {
+
+    protected static final String SWAGGER_API_DOCS_PATH = "api-docs";
+
+
+    @Test
+    public void shouldReturn200_whenSwaggerApiDocsIsCalled() throws Exception {
+        ClientResponse response = legalTagUtils.send(SWAGGER_API_DOCS_PATH, "GET", "", "", "");
+        assertEquals(HttpStatus.SC_OK, response.getStatus());
+    }
+
+    @Test
+    @Override
+    public void should_returnOk_when_makingHttpOptionsRequest() {
+        // not actual for this endpoint
+    }
+
+    @Test
+    public void should_return401_when_makingHttpRequestWithoutToken() throws Exception {
+        // not actual for this endpoint
+    }
+
+    @Test
+    public void should_return307_when_makingHttpRequest()throws Exception {
+        // not actual for this endpoint
+    }
+
+    @Override
+    protected String getApi() {
+        return SWAGGER_API_DOCS_PATH;
+    }
+
+    @Override
+    protected String getHttpMethod() {
+        return "GET";
+    }
+
+}
diff --git a/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/util/AcceptanceBaseTest.java b/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/util/AcceptanceBaseTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..62395f7743b85dbbb865cca7505ec65086d72d5c
--- /dev/null
+++ b/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/util/AcceptanceBaseTest.java
@@ -0,0 +1,116 @@
+package org.opengroup.osdu.legal.util;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.opengroup.osdu.legal.util.Constants.DATA_PARTITION_ID;
+
+import com.sun.jersey.api.client.ClientResponse;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import lombok.extern.java.Log;
+import org.junit.jupiter.api.Test;
+
+@Log
+public abstract class AcceptanceBaseTest {
+
+	protected LegalTagUtils legalTagUtils;
+
+	protected abstract String getApi();
+
+	protected abstract String getHttpMethod();
+
+	public void setup() throws Exception {}
+
+	public void teardown() throws Exception {}
+
+	protected String getBody(){
+		return "{}";
+	}
+
+	protected String getQuery(){
+		return "";
+	}
+
+	@Test
+	public void should_returnOk_when_makingHttpOptionsRequest() throws Exception{
+		ClientResponse response = legalTagUtils.send(this.getApi(), "OPTIONS", legalTagUtils.accessToken(), "", "");
+		assertEquals(200, response.getStatus());
+	}
+
+	@Test
+	public void should_return307_when_makingHttpRequest()throws Exception{
+		if(this.legalTagUtils.isLocalHost() || legalTagUtils.skipHttp())
+			return; //jetty server returns 403 when running locally when deployed jettyserver is not used and the app returns a 302 so just run against deployed version only when checking http -> https redirects
+		TestUtils testUtils = new TestUtils(true);
+		ClientResponse response = testUtils.send(this.getApi(), this.getHttpMethod(), legalTagUtils.accessToken(),
+				this.getBody(), this.getQuery());
+		assertEquals(307, response.getStatus());
+	}
+
+	@Test
+	public void should_return401_when_makingHttpRequestWithoutToken()throws Exception{
+		if(this.legalTagUtils.isLocalHost() || legalTagUtils.skipHttp())
+			return; //jetty server returns 403 when running locally when deployed jettyserver is not used and the app returns a 302 so just run against deployed version only when checking http -> https redirects
+
+		TestUtils testUtils = new TestUtils(true);
+		ClientResponse response = testUtils.send(this.getApi(), this.getHttpMethod(), "",
+				this.getBody(), this.getQuery());
+		assertEquals(401, response.getStatus());
+	}
+
+	protected ClientResponse send(String requestBody, int responseStatus) throws Exception {
+
+		return this.send(requestBody, responseStatus, "");
+	}
+
+	protected ClientResponse send(String requestBody, int responseStatus, String query) throws Exception {
+		return send(requestBody, responseStatus, query, LegalTagUtils.getMyDataPartition());
+	}
+
+	protected ClientResponse send(String requestBody, int responseStatus, String query, String tenant) throws Exception {
+		Map<String, String> headers = legalTagUtils.getHeaders();
+		headers.put(DATA_PARTITION_ID, tenant);
+		ClientResponse response = legalTagUtils.send(this.getApi(), this.getHttpMethod(), legalTagUtils.accessToken(), requestBody,
+				query, headers);
+
+		assertEquals(responseStatus, response.getStatus());
+
+		if (responseStatus == 204) //no content
+		{
+			return null;
+		}
+
+		return response;
+	}
+
+	protected ClientResponse send(String requestBody, String query, String tenant) throws Exception {
+		Map<String, String> headers = legalTagUtils.getHeaders();
+		headers.put(DATA_PARTITION_ID, tenant);
+		return legalTagUtils.send(this.getApi(), this.getHttpMethod(), legalTagUtils.accessToken(), requestBody,
+				query, headers);
+	}
+
+  protected ClientResponse validateAccess(int expectedResponse) throws Exception {
+    Map<String, String> headers = new HashMap<>();
+    headers.put(DATA_PARTITION_ID, LegalTagUtils.getMyDataPartition());
+
+    ClientResponse response = legalTagUtils
+        .send(this.getApi(), this.getHttpMethod(), legalTagUtils.accessToken(), getBody(),
+            getQuery(), headers);
+    log.info("Response status = " + response.getStatus());
+    assertEquals(expectedResponse, response.getStatus());
+    if (expectedResponse == 204) {
+      if (Objects.nonNull(response.getType())) {
+        log.info("Content-Type = " + response.getType().toString());
+        assertTrue(response.getType().toString().toLowerCase().indexOf("text/html") >= 0); //Google Cloud Run specific
+      } else {
+        assertNull(response.getType());
+      }
+    } else if (response.getType() != null) {
+      assertTrue(response.getType().toString().toLowerCase().indexOf("application/json") >= 0);
+    }
+    return response;
+  }
+}
\ No newline at end of file
diff --git a/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/util/Constants.java b/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/util/Constants.java
new file mode 100644
index 0000000000000000000000000000000000000000..5960c95b43fc2a7bfef7ca0dc343cda778c9e83a
--- /dev/null
+++ b/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/util/Constants.java
@@ -0,0 +1,5 @@
+package org.opengroup.osdu.legal.util;
+
+public class Constants {
+    public static final String DATA_PARTITION_ID  = "data-partition-id";
+}
diff --git a/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/util/LegalTagUtils.java b/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/util/LegalTagUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..c8152b1266e74f80bb21458f46fb6f4bd98871c6
--- /dev/null
+++ b/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/util/LegalTagUtils.java
@@ -0,0 +1,162 @@
+package org.opengroup.osdu.legal.util;
+
+import static org.opengroup.osdu.legal.util.Constants.DATA_PARTITION_ID;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import com.google.api.client.util.Strings;
+import com.google.gson.Gson;
+import com.sun.jersey.api.client.ClientResponse;
+
+public class LegalTagUtils extends TestUtils {
+
+	public static final String INTEGRATION_TESTER_TOKEN = "PRIVILEGED_USER_TOKEN";
+	protected static String token = null;
+	private OpenIDTokenProvider tokenProvider;
+
+	public LegalTagUtils() {
+		token = System.getProperty(INTEGRATION_TESTER_TOKEN, System.getenv(INTEGRATION_TESTER_TOKEN));
+		if (Strings.isNullOrEmpty(token)) {
+			tokenProvider = new OpenIDTokenProvider();
+			token = tokenProvider.getToken();
+		}
+    }
+	
+    public synchronized String accessToken() throws Exception {
+        if (Strings.isNullOrEmpty(token)) {
+            token = tokenProvider.getToken();
+        }
+        return "Bearer " + token;
+    }
+
+    private static InputStream getTestFileInputStream(String fileName) throws IOException {
+        return LegalTagUtils.class.getResourceAsStream("/" + fileName);
+    }
+
+    protected static String readTestFile(String fileName) throws IOException {
+        InputStream inputStream = getTestFileInputStream(fileName);
+        if(inputStream == null) {
+            throw new IOException();
+        }
+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+        byte[] buffer = new byte[1024];
+        int length;
+        while ((length = inputStream.read(buffer)) != -1) {
+            outputStream.write(buffer, 0, length);
+        }
+        return outputStream.toString(StandardCharsets.UTF_8.toString());
+    }
+
+    protected static byte[] getTenantConfigFileContent() throws IOException {
+        String content = readTestFile("TenantConfigTestingPurpose.json");
+        return content.getBytes();
+    }
+
+    public static String createRandomNameTenant() {
+        return TestUtils.getMyDataPartition() + "-gae-integration-test-" + System.currentTimeMillis();
+    }
+
+    boolean skipHttp() {
+        return System.getProperty("SKIP_HTTP_TESTS", System.getenv("SKIP_HTTP_TESTS")) != null;
+    }
+
+    public ClientResponse create(String countryOfOrigin, String name) throws Exception{
+        return create(countryOfOrigin, name, "2099-12-25", "Transferred Data");
+    }
+    public ClientResponse create(String countryOfOrigin, String name, String dataType) throws Exception{
+        return create(countryOfOrigin, name, "2099-12-25", dataType);
+    }
+    public ClientResponse create(String countryOfOrigin, String name, String expDate, String dataType)
+            throws Exception{
+        return create(countryOfOrigin, name, expDate, dataType, TestUtils.getMyDataPartition(),"<my description>");
+    }
+    public ClientResponse create(String countryOfOrigin, String name, String expDate, String dataType,
+                                 String tenantName, String description) throws Exception{
+        String body = getBody(countryOfOrigin, name, expDate, dataType, description);
+
+        Map<String, String> headers = getHeaders();
+        headers.put(DATA_PARTITION_ID, tenantName);
+        ClientResponse resp = send("legaltags", "POST", accessToken(),
+                body, "", headers);
+        Thread.sleep(10);
+        return resp;
+    }
+    public ClientResponse create(String name) throws Exception{
+        return create("US", name);
+    }
+    public ClientResponse delete(String name) throws Exception{
+        return delete(name, TestUtils.getMyDataPartition());
+    }
+    public ClientResponse delete(String name, String tenant) throws Exception{
+        Map<String, String> headers = new HashMap<>();
+        headers.put(DATA_PARTITION_ID, tenant);
+        return send("legaltags/" + name, "DELETE", accessToken(),
+                "", "", headers);
+    }
+
+    public class ReadableLegalTag {
+        public String name;
+        public String description;
+        public Properties properties;
+    }
+    public class ReadableLegalTags {
+        public ReadableLegalTag[] legalTags;
+    }
+    public class InvalidTagWithReason {
+        public String name;
+        public String reason;
+    }
+    public class InvalidTagsWithReason {
+        public InvalidTagWithReason[] invalidLegalTags;
+    }
+    public class Properties {
+        public String countryOfOrigin[]= new String[0];
+        public String contractId = "";
+        public String originator= "";
+        public String dataType = "";
+        public String securityClassification = "";
+        public String personalData = "";
+        public String exportClassification = "";
+        public String expirationDate="";
+    }
+    public static String createRetrieveBatchBody(String... names){
+        RequestLegalTags input = new RequestLegalTags();
+        input.names = names;
+        Gson gson = new Gson();
+        return gson.toJson(input);
+    }
+    public static String getBody(String name) {
+        return getBody("USA", name);
+    }
+    public static String getBody(String COO, String name) {
+        return getBody(COO, name, "2099-12-25", "First Party Data", "<my description>");
+    }
+    public static String updateBody(String name, String expDate) {
+        return "{\"name\": \"" + name + "\","+
+                "\"expirationDate\": \"" + expDate + "\",\"contractId\":\"B1234\"}";
+    }
+    private static String getBody(String countryOfOrigin, String name, String expDate, String dataType, String description) {
+        description = description == null ? "" : "\"description\" : \"" + description + "\",";
+        expDate = ((expDate == null) || (expDate.length() == 0))  ? "" : "\"expirationDate\" : \"" + expDate + "\",";
+
+        return "{\"name\": \"" + name + "\"," + description +
+                "\"properties\": {\"countryOfOrigin\": [\"" + countryOfOrigin + "\"], \"contractId\":\"A1234\"," + expDate + "\"dataType\":\"" + dataType + "\", \"originator\":\" MyCompany     \", \"securityClassification\":\"Public\", \"exportClassification\":\"EAR99\", \"personalData\":\"No Personal Data\"} }";
+    }
+    public class ReadablePropertyValues {
+        public Map<String, String> countriesOfOrigin;
+        public Map<String, String> otherRelevantDataCountries;
+        public Set<String> securityClassifications;
+        public Set<String> exportClassificationControlNumbers;
+        public Set<String> personalDataTypes;
+        public Set<String> dataTypes;
+    }
+    public static class RequestLegalTags {
+        String[] names;
+    }
+}
diff --git a/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/util/OpenIDTokenProvider.java b/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/util/OpenIDTokenProvider.java
new file mode 100644
index 0000000000000000000000000000000000000000..cf77aeb1d62abfc0ed9df59eee495d08fb2d137b
--- /dev/null
+++ b/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/util/OpenIDTokenProvider.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2020-2022 Google LLC
+ * Copyright 2020-2022 EPAM Systems, Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opengroup.osdu.legal.util;
+
+import com.nimbusds.oauth2.sdk.AuthorizationGrant;
+import com.nimbusds.oauth2.sdk.ClientCredentialsGrant;
+import com.nimbusds.oauth2.sdk.ParseException;
+import com.nimbusds.oauth2.sdk.Scope;
+import com.nimbusds.oauth2.sdk.TokenRequest;
+import com.nimbusds.oauth2.sdk.TokenResponse;
+import com.nimbusds.oauth2.sdk.auth.ClientAuthentication;
+import com.nimbusds.oauth2.sdk.auth.ClientSecretBasic;
+import com.nimbusds.oauth2.sdk.auth.Secret;
+import com.nimbusds.oauth2.sdk.id.ClientID;
+import com.nimbusds.openid.connect.sdk.OIDCTokenResponseParser;
+import java.io.IOException;
+import java.net.URI;
+import java.util.Objects;
+import org.opengroup.osdu.legal.util.conf.OpenIDProviderConfig;
+import net.minidev.json.JSONObject;
+
+public class OpenIDTokenProvider {
+
+    private static final OpenIDProviderConfig openIDProviderConfig = OpenIDProviderConfig.Instance();
+    private static final String ID_TOKEN = "id_token";
+    private final AuthorizationGrant clientGrant = new ClientCredentialsGrant();
+    private final URI tokenEndpointURI;
+    private final Scope scope;
+    private final ClientAuthentication clientAuthentication;
+
+    public OpenIDTokenProvider() {
+        this.tokenEndpointURI = openIDProviderConfig.getProviderMetadata().getTokenEndpointURI();
+        this.scope = new Scope(openIDProviderConfig.getScopes());
+        this.clientAuthentication =
+            new ClientSecretBasic(
+                new ClientID(openIDProviderConfig.getClientId()),
+                new Secret(openIDProviderConfig.getClientSecret())
+            );
+    }
+
+    public String getToken() {
+        try {
+            TokenRequest request = new TokenRequest(this.tokenEndpointURI, this.clientAuthentication, this.clientGrant, this.scope);
+            return requestToken(request);
+        } catch (ParseException | IOException e) {
+            throw new RuntimeException("Unable get credentials from INTEGRATION_TESTER variables", e);
+        }
+    }
+
+    private String requestToken(TokenRequest tokenRequest) throws ParseException, IOException {
+
+        TokenResponse parse = OIDCTokenResponseParser.parse(tokenRequest.toHTTPRequest().send());
+
+        if (!parse.indicatesSuccess()) {
+            throw new RuntimeException("Unable get credentials from INTEGRATION_TESTER variables");
+        }
+
+        JSONObject jsonObject = parse.toSuccessResponse().toJSONObject();
+        String idTokenValue = jsonObject.getAsString(ID_TOKEN);
+        if (Objects.isNull(idTokenValue) || idTokenValue.isEmpty()) {
+            throw new RuntimeException("Unable get credentials from INTEGRATION_TESTER variables");
+        }
+        return idTokenValue;
+    }
+}
diff --git a/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/util/TestUtils.java b/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/util/TestUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..1448f6f6e86e6f5ef9a76be9cf404f17786b736e
--- /dev/null
+++ b/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/util/TestUtils.java
@@ -0,0 +1,135 @@
+package org.opengroup.osdu.legal.util;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.opengroup.osdu.legal.util.Constants.DATA_PARTITION_ID;
+
+import java.net.URL;
+import java.security.SecureRandom;
+import java.security.cert.X509Certificate;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+
+import com.google.gson.Gson;
+import com.sun.jersey.api.client.Client;
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.WebResource;
+import javax.ws.rs.core.MediaType;
+
+public class TestUtils {
+
+	protected String baseUrl;
+
+	public TestUtils(){
+		this(false);
+	}
+
+	public TestUtils(boolean enforceHttp){
+		baseUrl = System.getProperty("HOST_URL", System.getenv("HOST_URL"));
+		if(baseUrl == null || baseUrl.contains("-null")) {
+			baseUrl = "https://localhost:8443/api/legal/v1/";
+		}
+
+		if(enforceHttp)
+			baseUrl = baseUrl.replaceFirst("https", "http");
+	}
+
+	public boolean isLocalHost(){
+		return baseUrl.contains("//localhost");
+	}
+
+	public String getBaseHost() {return baseUrl.substring(8,baseUrl.length()-1);}
+
+	public String getApiPath(String api) throws Exception {
+		URL mergedURL = new URL(baseUrl + api);
+		return mergedURL.toString();
+	}
+	
+	public static String getMyDataPartition(){
+		return System.getProperty("MY_TENANT", System.getenv("MY_TENANT"));
+	}
+
+	public ClientResponse send(String path, String httpMethod, String token, String requestBody, String query)
+			throws Exception {
+
+        Map<String, String> headers = getHeaders();
+
+		return send(path, httpMethod, token, requestBody, query, headers);
+	}
+
+    public Map<String, String> getHeaders() {
+        Map<String, String> headers = new HashMap<>();
+
+        //either header should work the same for now so assign either to validate this
+		headers.put(DATA_PARTITION_ID, getMyDataPartition());
+
+        return headers;
+    }
+
+  public ClientResponse send(String path, String httpMethod, String token, String requestBody,
+      String query, Map<String, String> headers) throws Exception {
+
+    Client client = getClient();
+    WebResource webResource = client.resource(getApiPath(path + query));
+
+    final WebResource.Builder builder = webResource.getRequestBuilder();
+    builder.accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_JSON).
+        header("Authorization", token);
+
+    headers.forEach(builder::header);
+
+    ClientResponse response = builder.method(httpMethod, ClientResponse.class, requestBody);
+
+    return response;
+  }
+
+	@SuppressWarnings("unchecked")
+	public <T> T getResult(ClientResponse response, int exepectedStatus, Class<T> classOfT) {
+		String json = response.getEntity(String.class);
+		System.out.println(json);
+
+		assertEquals(exepectedStatus, response.getStatus());
+		if (exepectedStatus == 204) {
+			return null;
+		}
+
+		assertEquals("application/json", response.getType().toString());
+		if (classOfT == String.class) {
+			return (T) json;
+		}
+
+		Gson gson = new Gson();
+		return gson.fromJson(json, classOfT);
+	}
+
+	public Client getClient() {
+		TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
+			@Override
+			public X509Certificate[] getAcceptedIssuers() {
+				return null;
+			}
+
+			@Override
+			public void checkClientTrusted(X509Certificate[] certs, String authType) {
+			}
+
+			@Override
+			public void checkServerTrusted(X509Certificate[] certs, String authType) {
+			}
+		} };
+
+		try {
+			SSLContext sc = SSLContext.getInstance("TLS");
+			sc.init(null, trustAllCerts, new SecureRandom());
+			HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
+		} catch (Exception e) {
+		}
+
+		return Client.create();
+	}
+}
+
diff --git a/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/util/VersionInfoUtils.java b/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/util/VersionInfoUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..2d48377748a5149477e19af4165006c92d196359
--- /dev/null
+++ b/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/util/VersionInfoUtils.java
@@ -0,0 +1,26 @@
+package org.opengroup.osdu.legal.util;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import com.google.gson.Gson;
+import com.sun.jersey.api.client.ClientResponse;
+
+public class VersionInfoUtils {
+
+  public VersionInfo getVersionInfoFromResponse(ClientResponse response) {
+    assertTrue(response.getType().toString().contains("application/json"));
+    String json = response.getEntity(String.class);
+    Gson gson = new Gson();
+    return gson.fromJson(json, VersionInfo.class);
+  }
+
+  public class VersionInfo {
+    public String groupId;
+    public String artifactId;
+    public String version;
+    public String buildTime;
+    public String branch;
+    public String commitId;
+    public String commitMessage;
+  }
+}
diff --git a/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/util/conf/OpenIDProviderConfig.java b/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/util/conf/OpenIDProviderConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..bd0e44f14da6a9a0cac32f3774b318e81d05d8f8
--- /dev/null
+++ b/legal-acceptance-test/src/test/java/org/opengroup/osdu/legal/util/conf/OpenIDProviderConfig.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2020-2022 Google LLC
+ * Copyright 2020-2022 EPAM Systems, Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opengroup.osdu.legal.util.conf;
+
+import com.nimbusds.oauth2.sdk.http.HTTPRequest;
+import com.nimbusds.oauth2.sdk.http.HTTPResponse;
+import com.nimbusds.oauth2.sdk.id.Issuer;
+import com.nimbusds.openid.connect.sdk.op.OIDCProviderConfigurationRequest;
+import com.nimbusds.openid.connect.sdk.op.OIDCProviderMetadata;
+
+public class OpenIDProviderConfig {
+
+	public static final String TEST_OPENID_PROVIDER_CLIENT_ID = "PRIVILEGED_USER_OPENID_PROVIDER_CLIENT_ID";
+	public static final String TEST_OPENID_PROVIDER_CLIENT_SECRET = "PRIVILEGED_USER_OPENID_PROVIDER_CLIENT_SECRET";
+	public static final String TEST_OPENID_PROVIDER_URL = "TEST_OPENID_PROVIDER_URL";
+	
+    private String clientId;
+    private String clientSecret;
+    private String url;
+    private final String[] scopes = {"openid"};
+    private static final OpenIDProviderConfig openIDProviderConfig = new OpenIDProviderConfig();
+    private static OIDCProviderMetadata providerMetadata;
+
+    public static OpenIDProviderConfig Instance() {
+        try {
+			openIDProviderConfig.clientId = System.getProperty(TEST_OPENID_PROVIDER_CLIENT_ID,
+					System.getenv(TEST_OPENID_PROVIDER_CLIENT_ID));
+			openIDProviderConfig.clientSecret = System.getProperty(TEST_OPENID_PROVIDER_CLIENT_SECRET,
+					System.getenv(TEST_OPENID_PROVIDER_CLIENT_SECRET));
+			openIDProviderConfig.url = System.getProperty(TEST_OPENID_PROVIDER_URL,
+					System.getenv(TEST_OPENID_PROVIDER_URL));
+
+            Issuer issuer = new Issuer(openIDProviderConfig.url);
+            OIDCProviderConfigurationRequest request = new OIDCProviderConfigurationRequest(issuer);
+            HTTPRequest httpRequest = request.toHTTPRequest();
+            HTTPResponse httpResponse = httpRequest.send();
+            providerMetadata = OIDCProviderMetadata.parse(httpResponse.getContentAsJSONObject());
+        } catch (Exception e) {
+            throw new RuntimeException("Malformed token provider configuration", e);
+        }
+        return openIDProviderConfig;
+    }
+
+    public String getClientId() {
+        return clientId;
+    }
+
+    public String getClientSecret() {
+        return clientSecret;
+    }
+
+    public String[] getScopes() {
+        return scopes;
+    }
+
+    public OIDCProviderMetadata getProviderMetadata() {
+        return providerMetadata;
+    }
+}
diff --git a/legal-acceptance-test/src/test/resources/TenantConfigTestingPurpose.json b/legal-acceptance-test/src/test/resources/TenantConfigTestingPurpose.json
new file mode 100644
index 0000000000000000000000000000000000000000..fbdf53199ce9339fd4b8478f6ec33d0a21108907
--- /dev/null
+++ b/legal-acceptance-test/src/test/resources/TenantConfigTestingPurpose.json
@@ -0,0 +1,6 @@
+[{
+  "name": "Malaysia",
+  "alpha2": "MY",
+  "numeric": 458,
+  "residencyRisk": "Client consent required"
+}]
\ No newline at end of file
diff --git a/legal-acceptance-test/src/test/resources/logback-test.xml b/legal-acceptance-test/src/test/resources/logback-test.xml
new file mode 100644
index 0000000000000000000000000000000000000000..eb3bc003db7b3425fcc4bd43d35e959d83b2c744
--- /dev/null
+++ b/legal-acceptance-test/src/test/resources/logback-test.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+    <include resource="org/springframework/boot/logging/logback/defaults.xml"/>
+    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
+        <encoder>
+            <pattern>%yellow([%thread]) %highlight(| %-5level |) %green(%d) %cyan(| %logger{15} |) %highlight(%msg) %n</pattern>
+            <charset>utf8</charset>
+        </encoder>
+    </appender>
+    <root level="INFO">
+        <appender-ref ref="CONSOLE" />
+    </root>
+</configuration>
\ No newline at end of file