diff --git a/src/Property.js b/src/Property.js
new file mode 100644
index 0000000000000000000000000000000000000000..27f1d3d9a97fede44b620f958d9663a4823c3df2
--- /dev/null
+++ b/src/Property.js
@@ -0,0 +1,94 @@
+/*
+ * ** header v3.0
+ * This file is a part of the CaosDB Project.
+ *
+ * Copyright (C) 2021 IndiScale GmbH <info@indiscale.com>
+ * Copyright (C) 2021 Florian Spreckelsen <f.spreckelsen@indiscale.com>
+ *
+ * This program is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU Affero General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * ** end header
+ */
+import {
+    api
+} from "./EntityApi";
+
+function _getScalarValue(value) {
+    const valueCases = api.v1.ScalarValue.ScalarValueCase;
+    switch (value.getScalarValueCase()) {
+    case valueCases.SCALAR_VALUE_NOT_SET:
+        return undefined;
+    case valueCases.INTEGER_VALUE:
+        return value.getIntegerValue();
+    case valueCases.DOUBLE_VALUE:
+        return value.getDoubleValue();
+    case valueCases.BOOLEAN_VALUE:
+        return value.getBooleanValue();
+    case valueCases.STRING_VALUE:
+        return value.getStringValue();
+    default:
+        throw `Unkown value type ${value.getScalarValueCase()}.`;
+    }
+}
+
+function _getListValue(listDataType, values) {
+    const listCases = api.v1.ListDataType.ListDataTypeCase;
+    switch (listDataType.getListDataTypeCase()) {
+    case listCases.LIST_DATA_TYPE_NOT_SET:
+        return undefined;
+    case listCases.ATOMIC_DATA_TYPE:
+        return values.map(value => _getScalarValue(value));
+    case listCases.REFERENCE_DATA_TYPE:
+        return values.map(value => _getScalarValue(value));
+    default:
+        throe `Unknown list data type ${listDataType.getListDataTypeCase()}.`
+    }
+}
+
+export class Property {
+
+    constructor(protoProperty) {
+        this.wrappedProperty = protoProperty;
+    }
+
+    getName() {
+        return this.wrappedProperty.getName();
+    }
+
+    getId() {
+        return this.wrappedProperty.getId();
+    }
+
+    getValue() {
+        const wrappedValue = this.wrappedProperty.getValue();
+        if (value === undefined) {
+            // Empty values are undefined regardless of data type
+            return undefined;
+        }
+        const wrappedDataType = this.wrappedProperty.getDataType();
+        const dtypeCases = api.v1.DataType.DataTypeCase;
+        switch (wrappedDataType.getDataTypeCase()) {
+        case dtypeCases.DATA_TYPE_NOT_SET:
+            return undefined;
+        case dtypeCases.ATOMIC_DATA_TYPE:
+            return _getScalarValue(wrappedValue.getScalarValue());
+        case dtypeCases.LIST_DATA_TYPE:
+            return _getListValue(wrappedDataType.getListDataTypeCase(), wrappedValue.getListValues().getValuesList());
+        case dtypeCases.REFERENCE_DATA_TYPE:
+            return _getScalarValue(wrappedValue.getScalarValue());
+        default:
+            throw `Unkown data type ${wrappedDataType.getDataTypeCase()}.`;
+        }
+    }
+}
diff --git a/src/index.js b/src/index.js
index 748dbd281fbe9ca7df8f06ef2de8488a3a89e924..bce5b757a77aafea1941111f46d8347101bbd743 100644
--- a/src/index.js
+++ b/src/index.js
@@ -20,6 +20,12 @@
  *
  * ** end header
  */
+export {
+    Property
+}
+from "./Property";
+
 export {
     TransactionService
-} from "./TransactionService";
+}
+from "./TransactionService";