diff --git a/api-openbis-python3-pybis/src/python/pybis/definitions.py b/api-openbis-python3-pybis/src/python/pybis/definitions.py
index 25c31e6656e2ec4425557f4fde6a81ddd9c59a78..035130bb4d9d74fb2661818782a0153bbdf848a1 100644
--- a/api-openbis-python3-pybis/src/python/pybis/definitions.py
+++ b/api-openbis-python3-pybis/src/python/pybis/definitions.py
@@ -167,6 +167,11 @@ def openbis_definitions(entity):
                 "MATERIAL",
                 "HYPERLINK",
                 "XML",
+                "ARRAY_INTEGER",
+                "ARRAY_REAL",
+                "ARRAY_STRING",
+                "ARRAY_TIMESTAMP",
+                "JSON"
             ],
             "identifier": "typeId",
         },
diff --git a/api-openbis-python3-pybis/src/python/pybis/entity_type.py b/api-openbis-python3-pybis/src/python/pybis/entity_type.py
index 139d3a9d0cf8ac4f009f41b2b3712c379c780172..a17be6eb6b3a05c1d4ed396e581f7be514776655 100644
--- a/api-openbis-python3-pybis/src/python/pybis/entity_type.py
+++ b/api-openbis-python3-pybis/src/python/pybis/entity_type.py
@@ -12,29 +12,22 @@
 #   See the License for the specific language governing permissions and
 #   limitations under the License.
 #
-from tabulate import tabulate
-from texttable import Texttable
 from pandas import DataFrame
+
+from .definitions import (
+    get_method_for_entity,
+    get_type_for_entity,
+    get_definition_for_entity,
+)
 from .openbis_object import OpenBisObject
+from .semantic_annotation import SemanticAnnotation
 from .things import Things
 from .utils import (
-    check_datatype,
-    split_identifier,
     format_timestamp,
-    is_identifier,
-    is_permid,
-    nvl,
-    extract_permid,
     extract_code,
     extract_name,
     VERBOSE,
 )
-from .definitions import (
-    get_method_for_entity,
-    get_type_for_entity,
-    get_definition_for_entity,
-)
-from .semantic_annotation import SemanticAnnotation
 
 
 class EntityType:
@@ -193,7 +186,7 @@ class EntityType:
         # assign plugin
         if plugin is not None:
             plugin_obj = self.openbis.get_plugin(plugin)
-            new_assignment["plugin"] = plugin_obj.name
+            new_assignment["plugin"] = plugin_obj.permId
 
         request = self._get_request_for_pa(new_assignment, "Add")
         try:
@@ -229,11 +222,11 @@ class EntityType:
         }
         request = self._get_request_for_pa(items, "Remove", force)
         resp = self.openbis._post_request(self.openbis.as_v3, request)
-        if not resp and VERBOSE:
+        if not resp:
             new_data = self._get_method(self.permId, only_data=True)
             self._set_entity_data(new_data)
-
-            print(f"Property {property_type} revoked from {self.permId}")
+            if VERBOSE:
+                print(f"Property {property_type} revoked from {self.permId}")
 
     def _get_request_for_pa(self, items, item_action, force=False):
 
diff --git a/api-openbis-python3-pybis/src/python/pybis/experiment.py b/api-openbis-python3-pybis/src/python/pybis/experiment.py
index f078aef9b9b962d100a80dfe69c687c7f7a45d27..14eba9723d430e8b495a4c884a6ea0f4706ccdd6 100644
--- a/api-openbis-python3-pybis/src/python/pybis/experiment.py
+++ b/api-openbis-python3-pybis/src/python/pybis/experiment.py
@@ -12,11 +12,7 @@
 #   See the License for the specific language governing permissions and
 #   limitations under the License.
 #
-from .property import PropertyHolder
-from .attribute import AttrHolder
 from .openbis_object import OpenBisObject
-from .definitions import openbis_definitions
-from .utils import VERBOSE
 
 
 class Experiment(
@@ -30,8 +26,11 @@ class Experiment(
         self.a(data)
         self.__dict__["data"] = data
 
-        # put the properties in the self.p namespace (without checking them)
+        # put the properties in the self.p namespace
         for key, value in data["properties"].items():
+            data_type = self.p._property_names[key.lower()]['dataType']
+            if data_type in ("ARRAY_INTEGER", "ARRAY_REAL", "ARRAY_STRING", "ARRAY_TIMESTAMP"):
+                value = self.formatter.to_array(data_type, value)
             self.p.__dict__[key.lower()] = value
 
     def __str__(self):
diff --git a/api-openbis-python3-pybis/src/python/pybis/openbis_object.py b/api-openbis-python3-pybis/src/python/pybis/openbis_object.py
index 5afb398015beec585ff177b47a25ea1a3af9b000..d351da7485764e7616f76691ce64798b8cd1b7bb 100644
--- a/api-openbis-python3-pybis/src/python/pybis/openbis_object.py
+++ b/api-openbis-python3-pybis/src/python/pybis/openbis_object.py
@@ -71,6 +71,9 @@ class OpenBisObject:
         # put the properties in the self.p namespace (without checking them)
         if "properties" in data:
             for key, value in data["properties"].items():
+                data_type = self.p._property_names[key.lower()]['dataType']
+                if data_type in ("ARRAY_INTEGER", "ARRAY_REAL", "ARRAY_STRING", "ARRAY_TIMESTAMP"):
+                    value = self.formatter.to_array(data_type, value)
                 self.p.__dict__[key.lower()] = value
 
         # object is already saved to openBIS, so it is not new anymore
diff --git a/api-openbis-python3-pybis/src/python/pybis/property.py b/api-openbis-python3-pybis/src/python/pybis/property.py
index c792454a77b5dc4c79ba51303d83457aac5c6954..54b8577de72f50f76309aa0d3e8baa7af5f56698 100644
--- a/api-openbis-python3-pybis/src/python/pybis/property.py
+++ b/api-openbis-python3-pybis/src/python/pybis/property.py
@@ -13,14 +13,9 @@
 #   limitations under the License.
 #
 from tabulate import tabulate
-from texttable import Texttable
+
 from pybis.utils import (
     check_datatype,
-    split_identifier,
-    format_timestamp,
-    is_identifier,
-    is_permid,
-    nvl,
 )
 
 
@@ -147,7 +142,7 @@ class PropertyHolder:
                 raise ValueError(
                     f"Value for attribute «{name}» must be one of these terms: {', '.join(terms.df['code'].values)}"
                 )
-        elif data_type in ("INTEGER", "BOOLEAN", "VARCHAR"):
+        elif data_type in ("INTEGER", "BOOLEAN", "VARCHAR", "ARRAY_INTEGER", "ARRAY_REAL", "ARRAY_STRING", "ARRAY_TIMESTAMP"):
             if not check_datatype(data_type, value):
                 raise ValueError(f"Value must be of type {data_type}")
         self.__dict__[name] = value
diff --git a/api-openbis-python3-pybis/src/python/pybis/property_reformatter.py b/api-openbis-python3-pybis/src/python/pybis/property_reformatter.py
index 59739cd644f6dd70d738057f362c9a4fc6a3f46b..5257595ca8ddcdc129821f284f645104795a044a 100644
--- a/api-openbis-python3-pybis/src/python/pybis/property_reformatter.py
+++ b/api-openbis-python3-pybis/src/python/pybis/property_reformatter.py
@@ -12,6 +12,7 @@
 #   See the License for the specific language governing permissions and
 #   limitations under the License.
 #
+import re
 from datetime import datetime
 
 import pandas as pd
@@ -44,9 +45,15 @@ class PropertyReformatter:
             raise ValueError('properties can not be None!')
 
         for key, value in properties.items():
+            if value is None:
+                continue
             property_type = self.openbis.get_property_type(key)
             if property_type.dataType == 'TIMESTAMP':
                 properties[key] = self._format_timestamp(value)
+            elif property_type.dataType == 'ARRAY_TIMESTAMP':
+                properties[key] = ",".join([self._format_timestamp(x) for x in value])
+            elif property_type.dataType.startswith('ARRAY'):
+                properties[key] = ",".join(map(str, value))
                 
         return properties
 
@@ -60,3 +67,17 @@ class PropertyReformatter:
         print(
             f'WARNING: "{value}" is not of any OpenBis supported datetime formats. Reformatting to "{result}"')
         return result
+
+    def to_array(self, data_type, prop_value):
+        if prop_value is None or prop_value == "":
+            return []
+        result = []
+        if data_type == "ARRAY_INTEGER":
+            result = [int(x.strip()) for x in prop_value.split(',')]
+        elif data_type == "ARRAY_REAL":
+            result = [float(x.strip()) for x in prop_value.split(',')]
+        elif data_type == "ARRAY_STRING":
+            result = [x.strip() for x in re.split(r"(?<!\\),", prop_value)]
+        elif data_type == "ARRAY_TIMESTAMP":
+            result = [x.strip() for x in prop_value.split(',')]
+        return result
diff --git a/api-openbis-python3-pybis/src/python/pybis/pybis.py b/api-openbis-python3-pybis/src/python/pybis/pybis.py
index a48ba586b9a59bda23525c47b79d161dadf9f91e..3cb5587b4de42e51cdcc347a3c338be1d1f6be9a 100644
--- a/api-openbis-python3-pybis/src/python/pybis/pybis.py
+++ b/api-openbis-python3-pybis/src/python/pybis/pybis.py
@@ -1292,7 +1292,6 @@ class Openbis:
         if resp.ok:
             resp = resp.json()
             if "error" in resp:
-                # print(full_url)
                 print(json.dumps(request))
                 raise ValueError(resp["error"]["message"])
             elif "result" in resp:
@@ -1300,7 +1299,8 @@ class Openbis:
             else:
                 raise ValueError("request did not return either result nor error")
         else:
-            raise ValueError("general error while performing post request")
+            raise ValueError(
+                f"general error while performing post request. {resp.status_code}:{resp.reason}")
 
     def logout(self):
         """Log out of openBIS. After logout, the session token is no longer valid."""
diff --git a/api-openbis-python3-pybis/src/python/pybis/sample.py b/api-openbis-python3-pybis/src/python/pybis/sample.py
index 5514a7f6821d71de91e62fd10c0cc3426c62a991..be92088af1c4883088d7edd9235985c4b7fe21a1 100644
--- a/api-openbis-python3-pybis/src/python/pybis/sample.py
+++ b/api-openbis-python3-pybis/src/python/pybis/sample.py
@@ -90,8 +90,11 @@ class Sample(OpenBisObject, entity="sample", single_item_method_name="get_sample
         self.a(data)
         self.__dict__["data"] = data
 
-        # put the properties in the self.p namespace (without checking them)
+        # put the properties in the self.p namespace
         for key, value in data["properties"].items():
+            data_type = self.p._property_names[key.lower()]['dataType']
+            if data_type in ("ARRAY_INTEGER", "ARRAY_REAL", "ARRAY_STRING", "ARRAY_TIMESTAMP"):
+                value = self.formatter.to_array(data_type, value)
             self.p.__dict__[key.lower()] = value
 
     def __dir__(self):
diff --git a/api-openbis-python3-pybis/src/python/pybis/utils.py b/api-openbis-python3-pybis/src/python/pybis/utils.py
index 9dff312fda730e37d6670547d7ea735bd3580c32..11bfb5d8742b0b8083f6084fcff6ed61b1735e06 100644
--- a/api-openbis-python3-pybis/src/python/pybis/utils.py
+++ b/api-openbis-python3-pybis/src/python/pybis/utils.py
@@ -12,9 +12,8 @@
 #   See the License for the specific language governing permissions and
 #   limitations under the License.
 #
-from datetime import datetime
-from pathlib import Path
 import re
+from datetime import datetime
 
 # display messages when in a interactive context (IPython or Jupyter)
 try:
@@ -128,6 +127,8 @@ def check_datatype(type_name, value):
         return isinstance(value, bool)
     if type_name == "VARCHAR":
         return isinstance(value, str)
+    if type_name is not None and type_name.startswith("ARRAY"):
+        return isinstance(value, list)
     return True