diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationChangingService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationChangingService.java
index 6e0aad4b79894caec299d17fab5098da4afd6335..1d5d29b7e5674386609566bb5f914259809cc14a 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationChangingService.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationChangingService.java
@@ -37,6 +37,7 @@ import ch.systemsx.cisd.openbis.generic.shared.ICommonServer;
 import ch.systemsx.cisd.openbis.generic.shared.IOpenBisSessionManager;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.IGeneralInformationChangingService;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.Translator;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DeletionType;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.MetaprojectAssignmentsIds;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.NewVocabularyTerm;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.WebAppSettings;
@@ -59,7 +60,7 @@ public class GeneralInformationChangingService extends
         AbstractServer<IGeneralInformationChangingService> implements
         IGeneralInformationChangingService
 {
-    public static final int MINOR_VERSION = 5;
+    public static final int MINOR_VERSION = 6;
 
     @Resource(name = ch.systemsx.cisd.openbis.generic.shared.ResourceNames.COMMON_SERVER)
     private ICommonServer server;
@@ -283,4 +284,53 @@ public class GeneralInformationChangingService extends
 
         return info;
     }
+
+    @Override
+    public void deleteProjects(String sessionToken, List<Long> projectIds, String reason)
+    {
+        server.deleteProjects(sessionToken, TechId.createList(projectIds), reason);
+    }
+
+    @Override
+    public void deleteExperiments(String sessionToken, List<Long> experimentIds, String reason, DeletionType deletionType)
+    {
+        server.deleteExperiments(sessionToken, TechId.createList(experimentIds), reason, Translator.translate(deletionType));
+    }
+
+    @Override
+    public void deleteSamples(String sessionToken, List<Long> sampleIds, String reason, DeletionType deletionType)
+    {
+        server.deleteSamples(sessionToken, TechId.createList(sampleIds), reason, Translator.translate(deletionType));
+    }
+
+    @Override
+    public void deleteDataSets(String sessionToken, List<String> dataSetCodes, String reason, DeletionType deletionType)
+    {
+        server.deleteDataSets(sessionToken, dataSetCodes, reason, Translator.translate(deletionType), false);
+    }
+
+    @Override
+    public void deleteDataSetsForced(String sessionToken, List<String> dataSetCodes, String reason, DeletionType deletionType)
+    {
+        server.deleteDataSetsForced(sessionToken, dataSetCodes, reason, Translator.translate(deletionType), false);
+    }
+
+    @Override
+    public void revertDeletions(String sessionToken, List<Long> deletionIds)
+    {
+        server.revertDeletions(sessionToken, TechId.createList(deletionIds));
+    }
+
+    @Override
+    public void deletePermanently(String sessionToken, List<Long> deletionIds)
+    {
+        server.deletePermanently(sessionToken, TechId.createList(deletionIds));
+    }
+
+    @Override
+    public void deletePermanentlyForced(String sessionToken, List<Long> deletionIds)
+    {
+        server.deletePermanentlyForced(sessionToken, TechId.createList(deletionIds));
+    }
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationChangingServiceLogger.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationChangingServiceLogger.java
index 24eee0ecf042cd0c0219c9160a8dcbcf1bce1df4..de0722b5b355a10cfffadae56327abbe20a393e3 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationChangingServiceLogger.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationChangingServiceLogger.java
@@ -16,12 +16,14 @@
 
 package ch.systemsx.cisd.openbis.generic.server.api.v1;
 
+import java.util.List;
 import java.util.Map;
 
 import ch.systemsx.cisd.authentication.ISessionManager;
 import ch.systemsx.cisd.openbis.common.spring.IInvocationLoggerContext;
 import ch.systemsx.cisd.openbis.generic.shared.AbstractServerLogger;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.IGeneralInformationChangingService;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DeletionType;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.MetaprojectAssignmentsIds;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.NewVocabularyTerm;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.WebAppSettings;
@@ -167,6 +169,56 @@ class GeneralInformationChangingServiceLogger extends AbstractServerLogger imple
         return null;
     }
 
+    @Override
+    public void deleteProjects(String sessionToken, List<Long> projectIds, String reason)
+    {
+        logAccess(sessionToken, "deleteProjects", "projectIds(%s), reason(%s)", abbreviate(projectIds), reason);
+    }
+
+    @Override
+    public void deleteExperiments(String sessionToken, List<Long> experimentIds, String reason, DeletionType deletionType)
+    {
+        logAccess(sessionToken, "deleteExperiments", "experimentIds(%s), reason(%s), deletionType(%s)", abbreviate(experimentIds), reason,
+                deletionType);
+    }
+
+    @Override
+    public void deleteSamples(String sessionToken, List<Long> sampleIds, String reason, DeletionType deletionType)
+    {
+        logAccess(sessionToken, "deleteSamples", "sampleIds(%s), reason(%s), deletionType(%s)", abbreviate(sampleIds), reason, deletionType);
+    }
+
+    @Override
+    public void deleteDataSets(String sessionToken, List<String> dataSetCodes, String reason, DeletionType deletionType)
+    {
+        logAccess(sessionToken, "deleteDataSets", "dataSetCodes(%s), reason(%s), deletionType(%s)", abbreviate(dataSetCodes), reason, deletionType);
+    }
+
+    @Override
+    public void deleteDataSetsForced(String sessionToken, List<String> dataSetCodes, String reason, DeletionType deletionType)
+    {
+        logAccess(sessionToken, "deleteDataSetsForced", "dataSetCodes(%s), reason(%s), deletionType(%s)", abbreviate(dataSetCodes), reason,
+                deletionType);
+    }
+
+    @Override
+    public void revertDeletions(String sessionToken, List<Long> deletionIds)
+    {
+        logAccess(sessionToken, "revertDeletions", "deletionIds(%s)", abbreviate(deletionIds));
+    }
+
+    @Override
+    public void deletePermanently(String sessionToken, List<Long> deletionIds)
+    {
+        logAccess(sessionToken, "deletePermanently", "deletionIds(%s)", abbreviate(deletionIds));
+    }
+
+    @Override
+    public void deletePermanentlyForced(String sessionToken, List<Long> deletionIds)
+    {
+        logAccess(sessionToken, "deletePermanentlyForced", "deletionIds(%s)", abbreviate(deletionIds));
+    }
+
     @Override
     public int getMajorVersion()
     {
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationService.java
index 79655993fcf7ecb0aba247996c91c00161a58304..c09a4b549690bffb907c03271de863b362f49207 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationService.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationService.java
@@ -83,6 +83,8 @@ import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataSetFetchOptions;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataSetType;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataStore;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataStoreURLForDataSets;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Deletion;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DeletionFetchOption;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Experiment;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Material;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.MaterialIdentifier;
@@ -144,7 +146,7 @@ import ch.systemsx.cisd.openbis.generic.shared.util.HibernateUtils;
 public class GeneralInformationService extends AbstractServer<IGeneralInformationService> implements
         IGeneralInformationService
 {
-    public static final int MINOR_VERSION = 29;
+    public static final int MINOR_VERSION = 30;
 
     @Resource(name = ch.systemsx.cisd.openbis.generic.shared.ResourceNames.COMMON_SERVER)
     private ICommonServer commonServer;
@@ -966,14 +968,14 @@ public class GeneralInformationService extends AbstractServer<IGeneralInformatio
         }
         return result;
     }
-    
+
     @Override
     @Transactional(readOnly = true)
     @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER)
     public List<SearchDomain> listAvailableSearchDomains(String sessionToken)
     {
         checkSession(sessionToken);
-        
+
         return commonServer.listAvailableSearchDomains(sessionToken);
     }
 
@@ -1331,4 +1333,22 @@ public class GeneralInformationService extends AbstractServer<IGeneralInformatio
         checkSession(sessionToken);
         return new EntityCodeGenerator(getDAOFactory()).generateCode(prefix, EntityKind.valueOf(entityKind));
     }
+
+    @Override
+    @Transactional(readOnly = true)
+    @RolesAllowed(RoleWithHierarchy.SPACE_USER)
+    public List<Deletion> listDeletions(String sessionToken, EnumSet<DeletionFetchOption> fetchOptions)
+    {
+        if (fetchOptions != null && fetchOptions.contains(DeletionFetchOption.ALL_ENTITIES))
+        {
+            return Translator.translate(commonServer.listDeletions(sessionToken, true));
+        } else if (fetchOptions != null && fetchOptions.contains(DeletionFetchOption.ORIGINAL_ENTITIES))
+        {
+            return Translator.translate(commonServer.listOriginalDeletions(sessionToken));
+        } else
+        {
+            return Translator.translate(commonServer.listDeletions(sessionToken, false));
+        }
+    }
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationServiceLogger.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationServiceLogger.java
index de6b72125c2f2b82ae67751dd7da25a857545101..aab8f57d78108a68ff51688e890f4dbab4ecb07f 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationServiceLogger.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationServiceLogger.java
@@ -34,6 +34,8 @@ import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataSetFetchOption;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataSetType;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataStore;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataStoreURLForDataSets;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Deletion;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DeletionFetchOption;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Experiment;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.ExperimentType;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Material;
@@ -297,7 +299,7 @@ class GeneralInformationServiceLogger extends AbstractServerLogger implements
     }
 
     @Override
-    public List<SearchDomainSearchResult> searchOnSearchDomain(String sessionToken, String preferredSearchDomainOrNull, 
+    public List<SearchDomainSearchResult> searchOnSearchDomain(String sessionToken, String preferredSearchDomainOrNull,
             String searchString, Map<String, String> optionalParametersOrNull)
     {
         logAccess(sessionToken, "search-on-search-domain", "PREFERRED_SEARCH_DOMAIN(%s) SEARCH_STRING(%s)",
@@ -496,4 +498,12 @@ class GeneralInformationServiceLogger extends AbstractServerLogger implements
         logAccess(sessionToken, "generateCode", "sessionToken(%s) prefix(%s) entityKind(%s)", sessionToken, prefix, entityKind);
         return null;
     }
+
+    @Override
+    public List<Deletion> listDeletions(String sessionToken, EnumSet<DeletionFetchOption> fetchOptions)
+    {
+        logAccess(sessionToken, "listDeletions", "fetchOptions(%s)", fetchOptions);
+        return null;
+    }
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/Translator.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/Translator.java
index fdada9000d4109846afdc64dcdd408afdeece4ea..a5fb9f81194cac8298fbeb88911a9c191032fa4b 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/Translator.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/Translator.java
@@ -43,6 +43,10 @@ import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataSetKind;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataSetType;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataSetType.DataSetTypeInitializer;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataStore;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DeletedEntity;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Deletion;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DeletionType;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.EntityKind;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.EntityRegistrationDetails;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.EntityRegistrationDetails.EntityRegistrationDetailsInitializer;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.EntityTypeInitializer;
@@ -93,6 +97,7 @@ import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.id.sample.SamplePermId
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.id.sample.SampleTechIdId;
 import ch.systemsx.cisd.openbis.generic.shared.basic.AttachmentDownloadConstants;
 import ch.systemsx.cisd.openbis.generic.shared.basic.GenericSharedConstants;
+import ch.systemsx.cisd.openbis.generic.shared.basic.IEntityInformationHolderWithIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IIdHolder;
 import ch.systemsx.cisd.openbis.generic.shared.basic.PermlinkUtilities;
 import ch.systemsx.cisd.openbis.generic.shared.basic.URLMethodWithParameters;
@@ -1045,4 +1050,79 @@ public class Translator
         return result;
     }
 
+    public static ch.systemsx.cisd.openbis.generic.shared.basic.dto.DeletionType translate(DeletionType deletionType)
+    {
+        switch (deletionType)
+        {
+            case PERMANENT:
+                return ch.systemsx.cisd.openbis.generic.shared.basic.dto.DeletionType.PERMANENT;
+            case TRASH:
+                return ch.systemsx.cisd.openbis.generic.shared.basic.dto.DeletionType.TRASH;
+            default:
+                throw new IllegalArgumentException("Unknown deletion type: " + deletionType);
+        }
+    }
+
+    public static List<Deletion> translate(List<ch.systemsx.cisd.openbis.generic.shared.basic.dto.Deletion> deletions)
+    {
+        List<Deletion> result = new LinkedList<Deletion>();
+
+        if (deletions != null)
+        {
+            for (ch.systemsx.cisd.openbis.generic.shared.basic.dto.Deletion deletion : deletions)
+            {
+                result.add(translate(deletion));
+            }
+        }
+
+        return result;
+    }
+
+    public static Deletion translate(ch.systemsx.cisd.openbis.generic.shared.basic.dto.Deletion deletion)
+    {
+        Deletion result = new Deletion();
+        result.setId(deletion.getId());
+        result.setReasonOrNull(deletion.getReason());
+        result.setTotalExperimentsCount(deletion.getTotalExperimentsCount());
+        result.setTotalDatasetsCount(deletion.getTotalDatasetsCount());
+        result.setTotalSamplesCount(deletion.getTotalSamplesCount());
+
+        List<DeletedEntity> entities = new LinkedList<DeletedEntity>();
+        for (IEntityInformationHolderWithIdentifier entity : deletion.getDeletedEntities())
+        {
+            entities.add(translate((ch.systemsx.cisd.openbis.generic.shared.basic.dto.DeletedEntity) entity));
+        }
+        result.setDeletedEntities(entities);
+
+        return result;
+    }
+
+    public static DeletedEntity translate(ch.systemsx.cisd.openbis.generic.shared.basic.dto.DeletedEntity entity)
+    {
+        DeletedEntity result = new DeletedEntity();
+        result.setId(entity.getId());
+        result.setCode(entity.getCode());
+        result.setPermId(entity.getPermId());
+        result.setIdentifier(entity.getIdentifier());
+        result.setEntityType(entity.getEntityType().getCode());
+        result.setEntityKind(translate(entity.getEntityKind()));
+        return result;
+    }
+
+    public static EntityKind translate(ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind kind)
+    {
+        switch (kind)
+        {
+            case EXPERIMENT:
+                return EntityKind.EXPERIMENT;
+            case SAMPLE:
+                return EntityKind.SAMPLE;
+            case DATA_SET:
+                return EntityKind.DATA_SET;
+            case MATERIAL:
+                return EntityKind.MATERIAL;
+            default:
+                throw new IllegalArgumentException("Unknown entity kind: " + kind);
+        }
+    }
 }
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/api/v1/GeneralInformationChangingServiceTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/api/v1/GeneralInformationChangingServiceTest.java
index 121be0c20de2fedd3808b1004b51c299fc728f39..df2eb52fdaf1c2f4373f9886b924646002abf75f 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/api/v1/GeneralInformationChangingServiceTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/api/v1/GeneralInformationChangingServiceTest.java
@@ -22,9 +22,12 @@ import static org.testng.AssertJUnit.assertNotNull;
 import static org.testng.AssertJUnit.assertNull;
 import static org.testng.AssertJUnit.assertTrue;
 
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 
+import junit.framework.Assert;
+
 import org.springframework.beans.factory.annotation.Autowired;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
@@ -34,8 +37,17 @@ import ch.systemsx.cisd.common.exceptions.UserFailureException;
 import ch.systemsx.cisd.openbis.generic.shared.ICommonServer;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.IGeneralInformationChangingService;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.IGeneralInformationService;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataSet;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Deletion;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DeletionType;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Experiment;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.MetaprojectAssignments;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.MetaprojectAssignmentsIds;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Project;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Sample;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SearchCriteria;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SearchCriteria.MatchClause;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SearchCriteria.MatchClauseAttribute;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.id.dataset.DataSetCodeId;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.id.experiment.ExperimentIdentifierId;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.id.material.MaterialCodeAndTypeCodeId;
@@ -497,4 +509,216 @@ public class GeneralInformationChangingServiceTest extends SystemTestCase
                 generalInformationChangingService);
     }
 
+    @Test
+    public void testDeleteProject()
+    {
+        testDeletePermanent(new ProjectDeleteAction(), new ProjectListDeletedAction());
+    }
+
+    @Test
+    public void testDeleteExperientPermanent()
+    {
+        testDeletePermanent(new ExperimentDeleteAction(), new ExperimentListDeletedAction());
+    }
+
+    @Test
+    public void testDeleteExperientTrash()
+    {
+        testDeleteTrash(new ExperimentDeleteAction(), new ExperimentListDeletedAction());
+    }
+
+    @Test
+    public void testDeleteSamplePermanent()
+    {
+        testDeletePermanent(new SampleDeleteAction(), new SampleListDeletedAction());
+    }
+
+    @Test
+    public void testDeleteSampleTrash()
+    {
+        testDeleteTrash(new SampleDeleteAction(), new SampleListDeletedAction());
+    }
+
+    @Test
+    public void testDeleteDataSetPermanent()
+    {
+        testDeletePermanent(new DataSetDeleteAction(), new DataSetListDeletedAction());
+    }
+
+    @Test
+    public void testDeleteDataSetTrash()
+    {
+        testDeletePermanent(new DataSetDeleteAction(), new DataSetListDeletedAction());
+    }
+
+    private class ProjectDeleteAction implements DeleteAction<Project>
+    {
+        @Override
+        public void delete(Project project, String reason, DeletionType deletionType)
+        {
+            generalInformationChangingService.deleteProjects(sessionToken, Collections.singletonList(project.getId()), reason);
+        }
+    }
+
+    private class ProjectListDeletedAction implements ListDeletedAction<Project>
+    {
+        @Override
+        public List<Project> list()
+        {
+            List<Project> projects = generalInformationService.listProjects(sessionToken);
+            for (Project project : projects)
+            {
+                if (project.getIdentifier().equals("/TEST-SPACE/PROJECT-TO-DELETE"))
+                {
+                    return Collections.singletonList(project);
+                }
+            }
+            return Collections.emptyList();
+        }
+    }
+
+    private class ExperimentDeleteAction implements DeleteAction<Experiment>
+    {
+        @Override
+        public void delete(Experiment experiment, String reason, DeletionType deletionType)
+        {
+            generalInformationChangingService.deleteExperiments(sessionToken, Collections.singletonList(experiment.getId()), reason,
+                    deletionType);
+        }
+    }
+
+    private class ExperimentListDeletedAction implements ListDeletedAction<Experiment>
+    {
+        @Override
+        public List<Experiment> list()
+        {
+            return generalInformationService.listExperiments(sessionToken, Collections.singletonList("/TEST-SPACE/NOE/EXPERIMENT-TO-DELETE"));
+        }
+    }
+
+    private class SampleDeleteAction implements DeleteAction<Sample>
+    {
+        @Override
+        public void delete(Sample sample, String reason, DeletionType deletionType)
+        {
+            generalInformationChangingService.deleteSamples(sessionToken, Collections.singletonList(sample.getId()), reason,
+                    deletionType);
+        }
+    }
+
+    private class SampleListDeletedAction implements ListDeletedAction<Sample>
+    {
+        @Override
+        public List<Sample> list()
+        {
+            SearchCriteria criteria = new SearchCriteria();
+            criteria.addMatchClause(MatchClause.createAttributeMatch(MatchClauseAttribute.CODE, "SAMPLE-TO-DELETE"));
+            return generalInformationService.searchForSamples(sessionToken, criteria);
+        }
+    }
+
+    private class DataSetDeleteAction implements DeleteAction<DataSet>
+    {
+        @Override
+        public void delete(DataSet dataSet, String reason, DeletionType deletionType)
+        {
+            generalInformationChangingService.deleteDataSets(sessionToken, Collections.singletonList(dataSet.getCode()), reason,
+                    deletionType);
+        }
+    }
+
+    private class DataSetListDeletedAction implements ListDeletedAction<DataSet>
+    {
+        @Override
+        public List<DataSet> list()
+        {
+            SearchCriteria criteria = new SearchCriteria();
+            criteria.addMatchClause(MatchClause.createAttributeMatch(MatchClauseAttribute.CODE, "DATASET-TO-DELETE"));
+            return generalInformationService.searchForDataSets(sessionToken, criteria);
+        }
+    }
+
+    private <T> void testDeleteTrash(DeleteAction<T> deleteAction, ListDeletedAction<T> listAction)
+    {
+        List<T> beforeObjects = listAction.list();
+        List<Deletion> beforeDeletions = generalInformationService.listDeletions(sessionToken, null);
+
+        Assert.assertEquals(1, beforeObjects.size());
+
+        // move an object to trash
+        T deletedObject = beforeObjects.get(0);
+        String reason = "Test delete to trash: " + deletedObject;
+        deleteAction.delete(deletedObject, reason, DeletionType.TRASH);
+
+        List<T> afterObjects = listAction.list();
+        List<Deletion> afterDeletions = generalInformationService.listDeletions(sessionToken, null);
+        Deletion deletion = afterDeletions.get(afterDeletions.size() - 1);
+
+        // the object should not be listed and a new deletion should be appear
+        Assert.assertEquals(0, afterObjects.size());
+        Assert.assertEquals(beforeDeletions.size() + 1, afterDeletions.size());
+        Assert.assertEquals(reason, deletion.getReasonOrNull());
+
+        // revert the logical deletion
+        generalInformationChangingService.revertDeletions(sessionToken, Collections.singletonList(deletion.getId()));
+
+        afterObjects = listAction.list();
+        afterDeletions = generalInformationService.listDeletions(sessionToken, null);
+
+        // the object should be listed again and the deletion should be gone
+        Assert.assertEquals(1, afterObjects.size());
+        Assert.assertEquals(beforeDeletions.size(), afterDeletions.size());
+
+        // move the object again to trash
+        deleteAction.delete(deletedObject, reason, DeletionType.TRASH);
+
+        afterObjects = listAction.list();
+        afterDeletions = generalInformationService.listDeletions(sessionToken, null);
+        deletion = afterDeletions.get(afterDeletions.size() - 1);
+
+        // the object should be gone again and a new deletion should appear
+        Assert.assertEquals(0, afterObjects.size());
+        Assert.assertEquals(beforeDeletions.size() + 1, afterDeletions.size());
+        Assert.assertEquals(reason, deletion.getReasonOrNull());
+
+        // permanently confirm the deletion
+        generalInformationChangingService.deletePermanently(sessionToken, Collections.singletonList(deletion.getId()));
+
+        afterObjects = listAction.list();
+        afterDeletions = generalInformationService.listDeletions(sessionToken, null);
+
+        // both the object and the deletion should be gone
+        Assert.assertEquals(0, afterObjects.size());
+        Assert.assertEquals(beforeDeletions.size(), afterDeletions.size());
+    }
+
+    private <T> void testDeletePermanent(DeleteAction<T> deleteAction, ListDeletedAction<T> listAction)
+    {
+        List<T> beforeObjects = listAction.list();
+        List<Deletion> beforeDeletions = generalInformationService.listDeletions(sessionToken, null);
+
+        Assert.assertEquals(1, beforeObjects.size());
+
+        // delete an object permanently
+        T deletedObject = beforeObjects.get(0);
+        deleteAction.delete(deletedObject, "Test delete permanently: " + deletedObject, DeletionType.PERMANENT);
+
+        List<T> afterObjects = listAction.list();
+        List<Deletion> afterDeletions = generalInformationService.listDeletions(sessionToken, null);
+
+        // the object should be gone and no new deletions should appear
+        Assert.assertEquals(0, afterObjects.size());
+        Assert.assertEquals(beforeDeletions.size(), afterDeletions.size());
+    }
+
+    private interface DeleteAction<T>
+    {
+        public void delete(T object, String reason, DeletionType deletionType);
+    }
+
+    private interface ListDeletedAction<T>
+    {
+        public List<T> list();
+    }
+
 }
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/api/v1/GeneralInformationServiceTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/api/v1/GeneralInformationServiceTest.java
index b3b0c330b7ced4919b1630509488194f82320773..9da43fbb5389af46c04ca5fa421522e719f96283 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/api/v1/GeneralInformationServiceTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/api/v1/GeneralInformationServiceTest.java
@@ -153,7 +153,7 @@ public class GeneralInformationServiceTest extends SystemTestCase
                 }
             });
         assertEquals(
-                "[/CISD/DEFAULT, /CISD/NEMO, /CISD/NOE, /TEST-SPACE/NOE, /TEST-SPACE/TEST-PROJECT, /TESTGROUP/TESTPROJ]",
+                "[/CISD/DEFAULT, /CISD/NEMO, /CISD/NOE, /TEST-SPACE/NOE, /TEST-SPACE/PROJECT-TO-DELETE, /TEST-SPACE/TEST-PROJECT, /TESTGROUP/TESTPROJ]",
                 projects.toString());
 
         loginAsObserver();
@@ -820,7 +820,7 @@ public class GeneralInformationServiceTest extends SystemTestCase
     {
         SearchCriteria criteria = new SearchCriteria();
         List<Sample> samples = generalInformationService.searchForSamples(sessionToken, criteria);
-        assertEquals(700, samples.size());
+        assertEquals(701, samples.size());
     }
 
     @Test
@@ -1355,7 +1355,7 @@ public class GeneralInformationServiceTest extends SystemTestCase
     {
         SearchCriteria criteria = new SearchCriteria();
         List<DataSet> dataSets = generalInformationService.searchForDataSets(sessionToken, criteria);
-        assertEquals(30, dataSets.size());
+        assertEquals(31, dataSets.size());
     }
 
     @Test
@@ -1457,7 +1457,7 @@ public class GeneralInformationServiceTest extends SystemTestCase
         List<Experiment> experiments =
                 generalInformationService.searchForExperiments(sessionToken, searchCriteria);
 
-        assertEntities("[/CISD/NOE/EXP-TEST-2, /TEST-SPACE/NOE/EXP-TEST-2]", experiments);
+        assertEntities("[/CISD/NOE/EXP-TEST-2, /TEST-SPACE/NOE/EXP-TEST-2, /TEST-SPACE/NOE/EXPERIMENT-TO-DELETE]", experiments);
     }
 
     @Test
diff --git a/openbis/sourceTest/sql/postgresql/143/008=data_all.tsv b/openbis/sourceTest/sql/postgresql/143/008=data_all.tsv
index 0562acf77e316a27c9f86f41ac3610953113feaa..86cd32d03341bcde4e8cab27566c12f7356ccb15 100644
--- a/openbis/sourceTest/sql/postgresql/143/008=data_all.tsv
+++ b/openbis/sourceTest/sql/postgresql/143/008=data_all.tsv
@@ -29,3 +29,4 @@
 32	COMPONENT_1A	2	\N	2011-05-09 10:22:59.203+02	2011-05-09 10:22:59.313+02	f	t	2011-05-09 16:34:44.462776+02	8	1	t	\N	\N	\N	\N	0	\N	2014-04-01 09:56:25.410678+02
 33	COMPONENT_2A	2	\N	2011-05-09 10:22:59.203+02	2011-05-09 10:22:59.313+02	f	t	2011-05-09 16:34:44.462776+02	8	1	t	\N	\N	\N	\N	0	\N	2014-04-01 09:56:25.410678+02
 34	COMPONENT_1B	2	\N	2011-05-09 10:22:59.203+02	2011-05-09 10:22:59.313+02	f	t	2011-05-09 16:34:44.462776+02	8	1	t	\N	\N	\N	\N	0	\N	2014-04-01 09:56:25.410678+02
+35	DATASET-TO-DELETE	1	\N	2008-11-05 09:22:59.203+01	2008-11-05 09:22:59.313+01	f	t	2009-03-23 15:34:44.462776+01	23	1	t	\N	2	\N	\N	0	\N	2014-04-01 09:56:25.410678+02
diff --git a/openbis/sourceTest/sql/postgresql/143/028=experiments_all.tsv b/openbis/sourceTest/sql/postgresql/143/028=experiments_all.tsv
index 01506919eadea63bec43b5f8274e0b709dd1cf78..4348f98c0f0638cd45205a5853183858d1811b78 100644
--- a/openbis/sourceTest/sql/postgresql/143/028=experiments_all.tsv
+++ b/openbis/sourceTest/sql/postgresql/143/028=experiments_all.tsv
@@ -10,3 +10,4 @@
 22	EXP-Y	1	2	2008-11-05 09:22:37.246+01	1	\N	f	2009-03-18 10:50:19.475958+01	201108050937246-1031	\N	0	\N
 23	EXP-SPACE-TEST	1	2	2008-11-05 09:22:40.555+01	5	\N	f	2009-03-18 10:50:19.475958+01	201206190940555-1032	\N	0	\N
 24	EXP-TEST-2	1	2	2009-02-09 12:17:55.058768+01	6	\N	f	2009-03-18 10:50:19.475958+01	200902091255058-1037	\N	0	\N
+25	EXPERIMENT-TO-DELETE	1	2	2009-02-09 12:17:55.058768+01	6	\N	f	2009-03-18 10:50:19.475958+01	200902091255058-1038	\N	0	\N
diff --git a/openbis/sourceTest/sql/postgresql/143/029=external_data.tsv b/openbis/sourceTest/sql/postgresql/143/029=external_data.tsv
index aedb869915bbfec00817dad2635f4ad989b2b9f6..c8d9c49cfc6dda4233cbaa4779dfcbb0f05a938a 100644
--- a/openbis/sourceTest/sql/postgresql/143/029=external_data.tsv
+++ b/openbis/sourceTest/sql/postgresql/143/029=external_data.tsv
@@ -20,3 +20,4 @@
 32	contained/COMPONENT_1A	8	1	4	U	\N	AVAILABLE	\N	\N	f	-50	t
 33	contained/COMPONENT_2A	8	1	4	U	\N	AVAILABLE	\N	\N	f	-50	t
 34	contained/COMPONENT_1B	8	1	4	U	\N	AVAILABLE	\N	\N	f	-50	t
+35	xml/dataset-to-delete	8	1	4	U	\N	AVAILABLE	\N	\N	f	-50	t
diff --git a/openbis/sourceTest/sql/postgresql/143/046=projects.tsv b/openbis/sourceTest/sql/postgresql/143/046=projects.tsv
index 898b4e9c55f45f1b367e10bb1a163bac9504dcf7..41d51ac9461421d7bbfd1e0d8a0f45eb479b7cb1 100644
--- a/openbis/sourceTest/sql/postgresql/143/046=projects.tsv
+++ b/openbis/sourceTest/sql/postgresql/143/046=projects.tsv
@@ -4,3 +4,4 @@
 4	20120814110011738-104	NOE	1	\N	\N	2	2008-11-05 09:21:43.312+01	2009-04-03 15:56:37.675094+02	\N	0
 5	20120814110011738-105	TEST-PROJECT	3	\N	\N	2	2008-11-05 09:18:14.967+01	2009-04-03 15:56:37.675094+02	\N	0
 6	20120814110011738-106	NOE	3	\N	\N	2	2008-11-05 09:21:43.312+01	2009-04-03 15:56:37.675094+02	\N	0
+7	20120814110011738-107	PROJECT-TO-DELETE	3	\N	\N	2	2008-11-05 09:21:43.312+01	2009-04-03 15:56:37.675094+02	\N	0
diff --git a/openbis/sourceTest/sql/postgresql/143/057=samples_all.tsv b/openbis/sourceTest/sql/postgresql/143/057=samples_all.tsv
index f75349fc863d237824a72fd369b0163e6e1f4e80..59ea106bbfb25acc6daae1ccd9e209162a9cf83c 100644
--- a/openbis/sourceTest/sql/postgresql/143/057=samples_all.tsv
+++ b/openbis/sourceTest/sql/postgresql/143/057=samples_all.tsv
@@ -1029,3 +1029,4 @@
 1058	EV-PARENT	10	2009-02-09 12:09:19.327518+01	2	\N	3	\N	2009-08-18 17:54:11.56+02	23	201206191219327-1058	\N	EV-PARENT,-1,3,-1	\N	0	\N
 1059	EV-PARENT-NORMAL	11	2009-02-09 12:09:19.327518+01	2	\N	3	\N	2009-08-18 17:54:11.56+02	23	201206191219327-1059	\N	EV-PARENT-NORMAL,-1,3,-1	\N	0	\N
 1060	CP-TEST-4	3	2009-02-09 12:09:50.077973+01	2	\N	3	\N	2009-08-18 17:54:36.929+02	24	200902091250077-1060	\N	CP-TEST-4,-1,1,-1	\N	0	\N
+1061	SAMPLE-TO-DELETE	11	2009-02-09 12:09:19.327518+01	2	\N	3	\N	2009-08-18 17:54:11.56+02	23	201206191219327-1061	\N	SAMPLE-TO-DELETE,-1,3,-1	\N	0	\N
diff --git a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/IGeneralInformationChangingService.java b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/IGeneralInformationChangingService.java
index 095acb83e6c9a5bea5e19490d9cbf675e3004c12..a2fe0f1b6a42d696837f99e21f9af58b5553f8c6 100644
--- a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/IGeneralInformationChangingService.java
+++ b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/IGeneralInformationChangingService.java
@@ -16,10 +16,12 @@
 
 package ch.systemsx.cisd.openbis.generic.shared.api.v1;
 
+import java.util.List;
 import java.util.Map;
 
 import ch.systemsx.cisd.common.api.IRpcService;
 import ch.systemsx.cisd.common.exceptions.UserFailureException;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DeletionType;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.MetaprojectAssignmentsIds;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.NewVocabularyTerm;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.WebAppSettings;
@@ -177,4 +179,86 @@ public interface IGeneralInformationChangingService extends IRpcService
             final String sessionToken,
             final String sampleTypeCode,
             final String sessionKey);
+
+    /**
+     * Deletes the specified projects.
+     * 
+     * @param projectIds Ids of projects to delete
+     * @param reason Reason of the deletion
+     * @since 1.6
+     */
+    public void deleteProjects(String sessionToken, List<Long> projectIds, String reason);
+
+    /**
+     * Deletes or trashes the specified experiments depending on the chosen deletion type.
+     * 
+     * @param experimentIds Ids of experiments to delete
+     * @param reason Reason of the deletion
+     * @param deletionType Type of the deletion
+     * @since 1.6
+     */
+    public void deleteExperiments(String sessionToken, List<Long> experimentIds, String reason,
+            DeletionType deletionType);
+
+    /**
+     * Deletes or trashes the specified samples depending on the chosen deletion type.
+     * 
+     * @param sampleIds Ids of samples to delete
+     * @param reason Reason of the deletion
+     * @param deletionType Type of the deletion
+     * @since 1.6
+     */
+    public void deleteSamples(String sessionToken, List<Long> sampleIds, String reason,
+            DeletionType deletionType);
+
+    /**
+     * Deletes or trashes the specified data sets depending on the chosen deletion type. This method CANNOT delete data sets with deletion_disallow
+     * flag set to true in their type (compare with {@link #deleteDataSetsForced(String, List, String, DeletionType)}.
+     * 
+     * @param dataSetCodes Codes of data sets to delete
+     * @param reason Reason of the deletion
+     * @param deletionType Type of the deletion
+     * @since 1.6
+     */
+    public void deleteDataSets(String sessionToken, List<String> dataSetCodes, String reason,
+            DeletionType deletionType);
+
+    /**
+     * Deletes or trashes the specified data sets depending on the chosen deletion type. This method CAN delete data sets with deletion_disallow flag
+     * set to true in their type but requires special user privileges (compare with {@link #deleteDataSets(String, List, String, DeletionType)}.
+     * 
+     * @param dataSetCodes Codes of data sets to delete
+     * @param reason Reason of the deletion
+     * @param deletionType Type of the deletion
+     * @since 1.6
+     */
+    public void deleteDataSetsForced(String sessionToken, List<String> dataSetCodes, String reason,
+            DeletionType deletionType);
+
+    /**
+     * Reverts specified deletions (puts back all entities moved to trash in the deletions).
+     * 
+     * @param deletionIds Ids of deletions to be reverted
+     * @since 1.6
+     */
+    public void revertDeletions(String sessionToken, List<Long> deletionIds);
+
+    /**
+     * Permanently deletes entities moved to trash in specified deletions. This method CANNOT delete data sets with deletion_disallow flag set to true
+     * in their type (compare with {@link #deletePermanentlyForced(String, List)})
+     * 
+     * @param deletionIds Ids of deletions to be deleted permanently
+     * @since 1.6
+     */
+    public void deletePermanently(String sessionToken, List<Long> deletionIds);
+
+    /**
+     * Permanently deletes entities moved to trash in specified deletions. It CAN delete data sets with deletion_disallow flag set to true in their
+     * type (compare with {@link #deletePermanently(String, List)}).
+     * 
+     * @param deletionIds Ids of deletions to be deleted permanently
+     * @since 1.6
+     */
+    public void deletePermanentlyForced(String sessionToken, List<Long> deletionIds);
+
 }
diff --git a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/IGeneralInformationService.java b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/IGeneralInformationService.java
index 7c08a14f4f30989a87a73e747cff46e88250342e..bde1a3c3f816ecacd9468955e766666e0f28dfa8 100644
--- a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/IGeneralInformationService.java
+++ b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/IGeneralInformationService.java
@@ -32,6 +32,8 @@ import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataSetFetchOption;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataSetType;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataStore;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataStoreURLForDataSets;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Deletion;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DeletionFetchOption;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Experiment;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.ExperimentType;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Material;
@@ -54,7 +56,6 @@ import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.id.sample.ISampleId;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Metaproject;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Vocabulary;
 
-
 /**
  * Service for retrieving general informations.
  * 
@@ -399,28 +400,26 @@ public interface IGeneralInformationService extends IRpcService
             EnumSet<DataSetFetchOption> fetchOptions);
 
     /**
-     * Searches on a search domain. If no preferred search domain is specified the first available one will be used. 
-     * If the preferred sequence search domain doesn't exist or isn't available also the first available one will be used.
+     * Searches on a search domain. If no preferred search domain is specified the first available one will be used. If the preferred sequence search
+     * domain doesn't exist or isn't available also the first available one will be used.
      * 
      * @param preferredSearchDomainOrNull The key of the preferred search domain or <code>null</code>.
      * @param searchString The search string.
-     * @param optionalParametersOrNull Optional parameters. Can be <code>null</code>. 
-     *          The semantics depends on the type of search domain.
+     * @param optionalParametersOrNull Optional parameters. Can be <code>null</code>. The semantics depends on the type of search domain.
      * @since 1.29
      */
-    public List<SearchDomainSearchResult> searchOnSearchDomain(String sessionToken, 
-            String preferredSearchDomainOrNull, String searchString, 
+    public List<SearchDomainSearchResult> searchOnSearchDomain(String sessionToken,
+            String preferredSearchDomainOrNull, String searchString,
             Map<String, String> optionalParametersOrNull);
-    
+
     /**
-     * Lists available search domains. Their name attribute can be used when invoking 
-     * {@link #searchOnSearchDomain(String, String, String, Map)}.
+     * Lists available search domains. Their name attribute can be used when invoking {@link #searchOnSearchDomain(String, String, String, Map)}.
      * 
      * @return empty list if no search domain is available.
      * @since 1.29
      */
     public List<SearchDomain> listAvailableSearchDomains(String sessionToken);
-    
+
     /**
      * Return all data sets matching specified search criteria. Note, that for returned container data sets the contained data sets have only code,
      * type and registration date set.
@@ -429,7 +428,7 @@ public interface IGeneralInformationService extends IRpcService
      * @since 1.8
      */
     public List<DataSet> searchForDataSets(String sessionToken, SearchCriteria searchCriteria);
-    
+
     /**
      * Return all data sets matching specified search criteria and visible to user <var>userId</var>. Note, that for returned container data sets the
      * contained data sets have only code, type and registration date set.
@@ -550,7 +549,7 @@ public interface IGeneralInformationService extends IRpcService
             boolean allVersions);
 
     public Map<String, String> getUserDisplaySettings(final String sessionToken);
-    
+
     /**
      * Lists property types.
      * 
@@ -558,7 +557,7 @@ public interface IGeneralInformationService extends IRpcService
      * @since 1.26
      */
     public List<PropertyType> listPropertyTypes(String sessionToken, boolean withRelations);
-    
+
     /**
      * Generate Code.
      * 
@@ -567,5 +566,14 @@ public interface IGeneralInformationService extends IRpcService
      * @since 1.28
      */
     public String generateCode(String sessionToken, String prefix, String entityKind);
-}
 
+    /**
+     * Returns all deletions.
+     * 
+     * @param fetchOptions Options that control which parts of the deletions are fetched.
+     * @return a sorted list of {@link Deletion}.
+     * @since 1.30
+     */
+    public List<Deletion> listDeletions(String sessionToken, EnumSet<DeletionFetchOption> fetchOptions);
+
+}
diff --git a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/DeletedEntity.java b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/DeletedEntity.java
new file mode 100644
index 0000000000000000000000000000000000000000..2fed29f7fb78973b6f81a4033e8159d22a3006e3
--- /dev/null
+++ b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/DeletedEntity.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2014 ETH Zuerich, Scientific IT Services
+ *
+ * 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
+ *
+ * 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 ch.systemsx.cisd.openbis.generic.shared.api.v1.dto;
+
+import java.io.Serializable;
+
+import ch.systemsx.cisd.base.annotation.JsonObject;
+
+/**
+ * @author pkupczyk
+ */
+@JsonObject("DeletedEntity")
+public class DeletedEntity implements Serializable
+{
+
+    private static final long serialVersionUID = 1L;
+
+    private Long id;
+
+    private String code;
+
+    private String permId;
+
+    private String identifier;
+
+    private String entityType;
+
+    private EntityKind entityKind;
+
+    public Long getId()
+    {
+        return id;
+    }
+
+    public void setId(Long id)
+    {
+        this.id = id;
+    }
+
+    public String getCode()
+    {
+        return code;
+    }
+
+    public void setCode(String code)
+    {
+        this.code = code;
+    }
+
+    public String getPermId()
+    {
+        return permId;
+    }
+
+    public void setPermId(String permId)
+    {
+        this.permId = permId;
+    }
+
+    public String getIdentifier()
+    {
+        return identifier;
+    }
+
+    public void setIdentifier(String identifier)
+    {
+        this.identifier = identifier;
+    }
+
+    public String getEntityType()
+    {
+        return entityType;
+    }
+
+    public void setEntityType(String entityType)
+    {
+        this.entityType = entityType;
+    }
+
+    public EntityKind getEntityKind()
+    {
+        return entityKind;
+    }
+
+    public void setEntityKind(EntityKind entityKind)
+    {
+        this.entityKind = entityKind;
+    }
+
+}
diff --git a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/Deletion.java b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/Deletion.java
new file mode 100644
index 0000000000000000000000000000000000000000..d96f0e47e5aa1f6df283541db8d2b4025b6ca05b
--- /dev/null
+++ b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/Deletion.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2014 ETH Zuerich, Scientific IT Services
+ *
+ * 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
+ *
+ * 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 ch.systemsx.cisd.openbis.generic.shared.api.v1.dto;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import ch.systemsx.cisd.base.annotation.JsonObject;
+
+/**
+ * @author pkupczyk
+ */
+@JsonObject("Deletion")
+public class Deletion implements Serializable
+{
+
+    private static final long serialVersionUID = 1L;
+
+    private Long id;
+
+    private int totalSamplesCount;
+
+    private int totalDatasetsCount;
+
+    private int totalExperimentsCount;
+
+    private String reasonOrNull;
+
+    private List<DeletedEntity> deletedEntities = new ArrayList<DeletedEntity>();
+
+    public Long getId()
+    {
+        return id;
+    }
+
+    public void setId(Long id)
+    {
+        this.id = id;
+    }
+
+    public int getTotalSamplesCount()
+    {
+        return totalSamplesCount;
+    }
+
+    public void setTotalSamplesCount(int totalSamplesCount)
+    {
+        this.totalSamplesCount = totalSamplesCount;
+    }
+
+    public int getTotalDatasetsCount()
+    {
+        return totalDatasetsCount;
+    }
+
+    public void setTotalDatasetsCount(int totalDatasetsCount)
+    {
+        this.totalDatasetsCount = totalDatasetsCount;
+    }
+
+    public int getTotalExperimentsCount()
+    {
+        return totalExperimentsCount;
+    }
+
+    public void setTotalExperimentsCount(int totalExperimentsCount)
+    {
+        this.totalExperimentsCount = totalExperimentsCount;
+    }
+
+    public String getReasonOrNull()
+    {
+        return reasonOrNull;
+    }
+
+    public void setReasonOrNull(String reasonOrNull)
+    {
+        this.reasonOrNull = reasonOrNull;
+    }
+
+    public List<DeletedEntity> getDeletedEntities()
+    {
+        return deletedEntities;
+    }
+
+    public void setDeletedEntities(List<DeletedEntity> deletedEntities)
+    {
+        this.deletedEntities = deletedEntities;
+    }
+
+}
diff --git a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/DeletionFetchOption.java b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/DeletionFetchOption.java
new file mode 100644
index 0000000000000000000000000000000000000000..ff4a45f208f81c33879345555871c7257d8103b1
--- /dev/null
+++ b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/DeletionFetchOption.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2014 ETH Zuerich, Scientific IT Services
+ *
+ * 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
+ *
+ * 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 ch.systemsx.cisd.openbis.generic.shared.api.v1.dto;
+
+import java.io.Serializable;
+
+import ch.systemsx.cisd.base.annotation.JsonObject;
+
+/**
+ * @author pkupczyk
+ */
+@JsonObject("DeletionFetchOption")
+public enum DeletionFetchOption implements Serializable
+{
+
+    /**
+     * Deletions will contain only the originally deleted entities
+     */
+    ORIGINAL_ENTITIES,
+
+    /**
+     * Deletions will contain the originally deleted entities and all the related entities that were also deleted by a cascade.
+     */
+    ALL_ENTITIES
+
+}
diff --git a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/DeletionType.java b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/DeletionType.java
new file mode 100644
index 0000000000000000000000000000000000000000..06dbd6317e8fe716bd91e36246df6a3b3d76a552
--- /dev/null
+++ b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/DeletionType.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2014 ETH Zuerich, Scientific IT Services
+ *
+ * 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
+ *
+ * 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 ch.systemsx.cisd.openbis.generic.shared.api.v1.dto;
+
+import java.io.Serializable;
+
+import ch.systemsx.cisd.base.annotation.JsonObject;
+
+/**
+ * Types of deletion operations.
+ * 
+ * @author pkupczyk
+ */
+@JsonObject("DeletionType")
+public enum DeletionType implements Serializable
+{
+
+    PERMANENT, TRASH
+
+}
diff --git a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/EntityKind.java b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/EntityKind.java
new file mode 100644
index 0000000000000000000000000000000000000000..da1db9d6c5b6d8bef67beb40339c4059f056adaf
--- /dev/null
+++ b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/EntityKind.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2014 ETH Zuerich, Scientific IT Services
+ *
+ * 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
+ *
+ * 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 ch.systemsx.cisd.openbis.generic.shared.api.v1.dto;
+
+import java.io.Serializable;
+
+import ch.systemsx.cisd.base.annotation.JsonObject;
+
+/**
+ * @author pkupczyk
+ */
+@JsonObject("EntityKind")
+public enum EntityKind implements Serializable
+{
+
+    MATERIAL, EXPERIMENT, SAMPLE, DATA_SET
+
+}