diff --git a/caosdb-proto b/caosdb-proto
index 73d85fb20bb16902c0a89dda697eed17994712bc..9fa41dce325d370eb8da60a77e921d4a0618f513 160000
--- a/caosdb-proto
+++ b/caosdb-proto
@@ -1 +1 @@
-Subproject commit 73d85fb20bb16902c0a89dda697eed17994712bc
+Subproject commit 9fa41dce325d370eb8da60a77e921d4a0618f513
diff --git a/pom.xml b/pom.xml
index 55aaeedb06b23eba2c78e7b6e27189ee5e7a475f..887653b52755d4340c4b00056c80e78d9584af39 100644
--- a/pom.xml
+++ b/pom.xml
@@ -25,7 +25,7 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>org.caosdb</groupId>
   <artifactId>caosdb-server</artifactId>
-  <version>0.5.1-GRPC0.0.20</version>
+  <version>0.5.1-GRPC0.0.21</version>
   <packaging>jar</packaging>
   <name>CaosDB Server</name>
   <scm>
diff --git a/src/main/java/org/caosdb/server/database/backend/transaction/DeleteEntityProperties.java b/src/main/java/org/caosdb/server/database/backend/transaction/DeleteEntityProperties.java
index 7b02fbf003e49c18bc14a602f7e2f781b495c682..4072c1b2877cd9231424a98948fad32747870537 100644
--- a/src/main/java/org/caosdb/server/database/backend/transaction/DeleteEntityProperties.java
+++ b/src/main/java/org/caosdb/server/database/backend/transaction/DeleteEntityProperties.java
@@ -22,13 +22,12 @@
  */
 package org.caosdb.server.database.backend.transaction;
 
-import static org.caosdb.server.transaction.Transaction.ERROR_INTEGRITY_VIOLATION;
-
 import org.caosdb.server.database.BackendTransaction;
 import org.caosdb.server.database.backend.interfaces.DeleteEntityPropertiesImpl;
 import org.caosdb.server.database.exceptions.IntegrityException;
 import org.caosdb.server.entity.EntityInterface;
 import org.caosdb.server.utils.EntityStatus;
+import org.caosdb.server.utils.ServerMessages;
 
 public class DeleteEntityProperties extends BackendTransaction {
 
@@ -50,7 +49,7 @@ public class DeleteEntityProperties extends BackendTransaction {
       try {
         ret.execute(this.entity.getId());
       } catch (final IntegrityException exc) {
-        this.entity.addError(ERROR_INTEGRITY_VIOLATION);
+        this.entity.addError(ServerMessages.ERROR_INTEGRITY_VIOLATION);
         throw exc;
       }
     }
diff --git a/src/main/java/org/caosdb/server/database/backend/transaction/DeleteSparseEntity.java b/src/main/java/org/caosdb/server/database/backend/transaction/DeleteSparseEntity.java
index 55989d219ad738d5a866e0ef6f322368c8fc559b..e371cfe1f9caf3d4438e8801d4a6cee1119322f8 100644
--- a/src/main/java/org/caosdb/server/database/backend/transaction/DeleteSparseEntity.java
+++ b/src/main/java/org/caosdb/server/database/backend/transaction/DeleteSparseEntity.java
@@ -24,13 +24,12 @@
  */
 package org.caosdb.server.database.backend.transaction;
 
-import static org.caosdb.server.transaction.Transaction.ERROR_INTEGRITY_VIOLATION;
-
 import org.caosdb.server.database.BackendTransaction;
 import org.caosdb.server.database.backend.interfaces.DeleteSparseEntityImpl;
 import org.caosdb.server.database.exceptions.IntegrityException;
 import org.caosdb.server.entity.EntityInterface;
 import org.caosdb.server.utils.EntityStatus;
+import org.caosdb.server.utils.ServerMessages;
 
 public class DeleteSparseEntity extends BackendTransaction {
 
@@ -54,7 +53,7 @@ public class DeleteSparseEntity extends BackendTransaction {
         ret.execute(this.entity.getId());
       }
     } catch (final IntegrityException exc) {
-      this.entity.addError(ERROR_INTEGRITY_VIOLATION);
+      this.entity.addError(ServerMessages.ERROR_INTEGRITY_VIOLATION);
       throw exc;
     }
   }
diff --git a/src/main/java/org/caosdb/server/database/backend/transaction/InsertEntityDatatype.java b/src/main/java/org/caosdb/server/database/backend/transaction/InsertEntityDatatype.java
index 182874d1f1e30ed8f5249e609dbbc42a724d94af..aa139e7db565ae82073d6983915c0c53e9cd8b51 100644
--- a/src/main/java/org/caosdb/server/database/backend/transaction/InsertEntityDatatype.java
+++ b/src/main/java/org/caosdb/server/database/backend/transaction/InsertEntityDatatype.java
@@ -1,12 +1,11 @@
 package org.caosdb.server.database.backend.transaction;
 
-import static org.caosdb.server.transaction.Transaction.ERROR_INTEGRITY_VIOLATION;
-
 import org.caosdb.server.database.BackendTransaction;
 import org.caosdb.server.database.backend.interfaces.InsertEntityDatatypeImpl;
 import org.caosdb.server.database.exceptions.IntegrityException;
 import org.caosdb.server.database.proto.SparseEntity;
 import org.caosdb.server.entity.EntityInterface;
+import org.caosdb.server.utils.ServerMessages;
 
 public class InsertEntityDatatype extends BackendTransaction {
 
@@ -25,7 +24,7 @@ public class InsertEntityDatatype extends BackendTransaction {
     try {
       t.execute(e);
     } catch (final IntegrityException exc) {
-      this.entity.addError(ERROR_INTEGRITY_VIOLATION);
+      this.entity.addError(ServerMessages.ERROR_INTEGRITY_VIOLATION);
       throw exc;
     }
 
diff --git a/src/main/java/org/caosdb/server/database/backend/transaction/InsertSparseEntity.java b/src/main/java/org/caosdb/server/database/backend/transaction/InsertSparseEntity.java
index 22720f836e5cbd4912f3aedccd25398e80a19324..213c7529766dcac4cc002f81380bf8d141cd8065 100644
--- a/src/main/java/org/caosdb/server/database/backend/transaction/InsertSparseEntity.java
+++ b/src/main/java/org/caosdb/server/database/backend/transaction/InsertSparseEntity.java
@@ -22,8 +22,6 @@
  */
 package org.caosdb.server.database.backend.transaction;
 
-import static org.caosdb.server.transaction.Transaction.ERROR_INTEGRITY_VIOLATION;
-
 import org.caosdb.server.database.BackendTransaction;
 import org.caosdb.server.database.backend.interfaces.InsertSparseEntityImpl;
 import org.caosdb.server.database.exceptions.IntegrityException;
@@ -31,6 +29,7 @@ import org.caosdb.server.database.exceptions.TransactionException;
 import org.caosdb.server.database.proto.SparseEntity;
 import org.caosdb.server.entity.EntityInterface;
 import org.caosdb.server.entity.Version;
+import org.caosdb.server.utils.ServerMessages;
 import org.caosdb.server.utils.Undoable;
 
 public class InsertSparseEntity extends BackendTransaction {
@@ -52,7 +51,7 @@ public class InsertSparseEntity extends BackendTransaction {
     try {
       t.execute(e);
     } catch (final IntegrityException exc) {
-      this.entity.addError(ERROR_INTEGRITY_VIOLATION);
+      this.entity.addError(ServerMessages.ERROR_INTEGRITY_VIOLATION);
       throw exc;
     }
 
diff --git a/src/main/java/org/caosdb/server/datatype/ReferenceDatatype.java b/src/main/java/org/caosdb/server/datatype/ReferenceDatatype.java
index 42f60cebc116d23137d359c11015a2978233234e..769d3ebdd109e22dcbc41f2ae7bd478b709f0482 100644
--- a/src/main/java/org/caosdb/server/datatype/ReferenceDatatype.java
+++ b/src/main/java/org/caosdb/server/datatype/ReferenceDatatype.java
@@ -27,9 +27,6 @@ import org.caosdb.server.entity.Message;
 @DatatypeDefinition(name = "Reference")
 public class ReferenceDatatype extends AbstractDatatype {
 
-  public static final Message REFERENCE_ID_NOT_PARSABLE =
-      new Message(217, "The reference is not parsable. It must be an integer.");
-
   @Override
   public ReferenceValue parseValue(final Object value) throws Message {
     return ReferenceValue.parseReference(value);
diff --git a/src/main/java/org/caosdb/server/entity/Entity.java b/src/main/java/org/caosdb/server/entity/Entity.java
index 0a60f9af59f731098a0e194e4848b578094d4e68..76ed7bf1ed2a16dfbade6d6effb162e391ce1c84 100644
--- a/src/main/java/org/caosdb/server/entity/Entity.java
+++ b/src/main/java/org/caosdb/server/entity/Entity.java
@@ -662,18 +662,6 @@ public class Entity extends AbstractObservable implements EntityInterface {
     return ret;
   }
 
-  @Override
-  public final Message getMessage(final String type, final Integer code) {
-    for (final ToElementable m : this.messages) {
-      if (m instanceof Message
-          && ((Message) m).getType().equalsIgnoreCase(type)
-          && ((Message) m).getCode() == code) {
-        return (Message) m;
-      }
-    }
-    return null;
-  }
-
   @Override
   public final void addMessage(final ToElementable m) {
     this.messages.add(m);
@@ -691,7 +679,7 @@ public class Entity extends AbstractObservable implements EntityInterface {
 
   @Override
   public void addInfo(final String description) {
-    final Message m = new Message(MessageType.Info, 0, description);
+    final Message m = new Message(description);
     addMessage(m);
   }
 
diff --git a/src/main/java/org/caosdb/server/entity/Message.java b/src/main/java/org/caosdb/server/entity/Message.java
index a1d9513f3d7a2068e10563fbc2d4fb447fe1964b..7f5c283640470480f552e1d9d61867911d439180 100644
--- a/src/main/java/org/caosdb/server/entity/Message.java
+++ b/src/main/java/org/caosdb/server/entity/Message.java
@@ -21,17 +21,41 @@
  */
 package org.caosdb.server.entity;
 
+import java.util.HashMap;
+import java.util.Map;
+import org.caosdb.api.entity.v1.MessageCode;
 import org.caosdb.server.entity.xml.ToElementable;
+import org.caosdb.server.utils.ServerMessages;
 import org.jdom2.Element;
 
 public class Message extends Exception implements Comparable<Message>, ToElementable {
 
   protected final String type;
-  private final Integer code;
+  private final MessageCode code;
   private final String description;
   private final String body;
 
-  private static final long serialVersionUID = -3005017964769041935L;
+  @Deprecated private static final Map<String, String> legacy_codes_mapping = new HashMap<>();
+
+  static void init() {
+    legacy_codes_mapping.put(
+        ServerMessages.ENTITY_HAS_BEEN_DELETED_SUCCESSFULLY.coreToString(), "10");
+    legacy_codes_mapping.put(ServerMessages.ATOMICITY_ERROR.coreToString(), "12");
+    legacy_codes_mapping.put(ServerMessages.ENTITY_DOES_NOT_EXIST.coreToString(), "101");
+    legacy_codes_mapping.put(ServerMessages.PROPERTY_HAS_NO_DATATYPE.coreToString(), "110");
+    legacy_codes_mapping.put(
+        ServerMessages.ENTITY_HAS_UNQUALIFIED_PROPERTIES.coreToString(), "114");
+    legacy_codes_mapping.put(ServerMessages.ENTITY_HAS_UNQUALIFIED_PARENTS.coreToString(), "116");
+    legacy_codes_mapping.put(ServerMessages.WARNING_OCCURED.coreToString(), "128");
+    legacy_codes_mapping.put(ServerMessages.ENTITY_NAME_IS_NOT_UNIQUE.coreToString(), "152");
+    legacy_codes_mapping.put(ServerMessages.REQUIRED_BY_UNQUALIFIED.coreToString(), "192");
+    legacy_codes_mapping.put(ServerMessages.REFERENCED_ENTITY_DOES_NOT_EXIST.coreToString(), "235");
+    legacy_codes_mapping.put(ServerMessages.AUTHORIZATION_ERROR.coreToString(), "403");
+    legacy_codes_mapping.put(ServerMessages.ROLE_DOES_NOT_EXIST.coreToString(), "1104");
+    legacy_codes_mapping.put(ServerMessages.ENTITY_NAME_DUPLICATES.coreToString(), "0");
+  }
+
+  private static final long serialVersionUID = 1837110172902899264L;
 
   public enum MessageType {
     Warning,
@@ -44,15 +68,18 @@ public class Message extends Exception implements Comparable<Message>, ToElement
     return toString().hashCode();
   }
 
-  @Override
-  public String toString() {
-    return this.type.toString()
-        + " ("
-        + (this.code != null ? Integer.toString(this.code) : "")
+  private String coreToString() {
+    return " ("
+        + (this.code != null ? this.code.toString() : "0")
         + ") - "
         + (this.description != null ? this.description : "");
   }
 
+  @Override
+  public String toString() {
+    return this.type.toString() + coreToString();
+  }
+
   @Override
   public boolean equals(final Object obj) {
     return obj.toString().equals(toString());
@@ -74,33 +101,33 @@ public class Message extends Exception implements Comparable<Message>, ToElement
     this(type, null, description, body);
   }
 
-  public Message(final String type, final Integer code) {
+  public Message(final String type, final MessageCode code) {
     this(type, code, null, null);
   }
 
-  public Message(final Integer code, final String description) {
+  public Message(final MessageCode code, final String description) {
     this(MessageType.Info, code, description);
   }
 
-  public Message(final MessageType type, final Integer code, final String description) {
+  public Message(final MessageType type, final MessageCode code, final String description) {
     this(type.toString(), code, description, null);
   }
 
   public Message(
-      final MessageType type, final Integer code, final String description, final String body) {
+      final MessageType type, final MessageCode code, final String description, final String body) {
     this(type.toString(), code, description, body);
   }
 
-  public Message(final String type, final Integer code, final String description) {
+  public Message(final String type, final MessageCode code, final String description) {
     this(type, code, description, null);
   }
 
   public Message(final MessageType type, final String description) {
-    this(type.toString(), 0, description);
+    this(type.toString(), MessageCode.MESSAGE_CODE_UNKNOWN, description);
   }
 
   public Message(
-      final String type, final Integer code, final String description, final String body) {
+      final String type, final MessageCode code, final String description, final String body) {
     this.code = code;
     this.description = description;
     this.body = body;
@@ -108,7 +135,7 @@ public class Message extends Exception implements Comparable<Message>, ToElement
   }
 
   public Message(
-      final Integer code, final String description, final String body, final MessageType type) {
+      final MessageCode code, final String description, final String body, final MessageType type) {
     this.code = code;
     this.description = description;
     this.body = body;
@@ -116,20 +143,29 @@ public class Message extends Exception implements Comparable<Message>, ToElement
   }
 
   public Message(final String string) {
-    this.code = null;
+    this.code = MessageCode.MESSAGE_CODE_UNKNOWN;
     this.description = string;
     this.body = null;
     this.type = MessageType.Info.toString();
   }
 
-  public Integer getCode() {
+  public MessageCode getCode() {
     return this.code;
   }
 
   public Element toElement() {
+    if (legacy_codes_mapping.isEmpty()) {
+      init();
+    }
     final Element e = new Element(this.type);
     if (this.code != null) {
-      e.setAttribute("code", Integer.toString(this.code));
+      if (legacy_codes_mapping.containsKey(this.coreToString())) {
+        e.setAttribute("code", legacy_codes_mapping.get(this.coreToString()));
+      } else if (this.code == MessageCode.MESSAGE_CODE_UNKNOWN) {
+        e.setAttribute("code", "0");
+      } else {
+        e.setAttribute("code", Integer.toString(this.code.getNumber()));
+      }
     }
     if (this.description != null) {
       e.setAttribute("description", this.description);
@@ -153,8 +189,7 @@ public class Message extends Exception implements Comparable<Message>, ToElement
 
   public final void print(final String indent) {
     System.out.println(indent + "+---| " + this.type + " |------------------------ ");
-    System.out.println(
-        indent + "|        Code: " + (this.code != null ? Integer.toString(this.code) : "null"));
+    System.out.println(indent + "|        Code: " + this.code.toString());
     System.out.println(indent + "| Description: " + this.description);
     System.out.println(indent + "|        Body: " + this.body);
     System.out.println(indent + "+------------------------------------------------------ ");
diff --git a/src/main/java/org/caosdb/server/entity/TransactionEntity.java b/src/main/java/org/caosdb/server/entity/TransactionEntity.java
index 2883c076f437520581037219a724020b47893424..7dd96b7f5ba8dc71c976731fed4d91e43688f919 100644
--- a/src/main/java/org/caosdb/server/entity/TransactionEntity.java
+++ b/src/main/java/org/caosdb/server/entity/TransactionEntity.java
@@ -59,8 +59,6 @@ public interface TransactionEntity {
 
   public abstract List<Message> getMessages(String type);
 
-  public abstract Message getMessage(String type, Integer code);
-
   public abstract void addMessage(ToElementable m);
 
   public abstract void addError(Message m);
diff --git a/src/main/java/org/caosdb/server/entity/wrapper/EntityWrapper.java b/src/main/java/org/caosdb/server/entity/wrapper/EntityWrapper.java
index c83cb67883f5a616109268fb6d62bae40cd73e6b..140bb207b61d6f50a593feb24a43b3e324ddcff7 100644
--- a/src/main/java/org/caosdb/server/entity/wrapper/EntityWrapper.java
+++ b/src/main/java/org/caosdb/server/entity/wrapper/EntityWrapper.java
@@ -340,11 +340,6 @@ public class EntityWrapper implements EntityInterface {
     return this.entity.getMessages(type);
   }
 
-  @Override
-  public Message getMessage(final String type, final Integer code) {
-    return this.entity.getMessage(type, code);
-  }
-
   @Override
   public void addMessage(final ToElementable m) {
     this.entity.addMessage(m);
diff --git a/src/main/java/org/caosdb/server/grpc/CaosDBToGrpcConverters.java b/src/main/java/org/caosdb/server/grpc/CaosDBToGrpcConverters.java
new file mode 100644
index 0000000000000000000000000000000000000000..aa6a260dfb52b5e36520d130219632d26095b0d1
--- /dev/null
+++ b/src/main/java/org/caosdb/server/grpc/CaosDBToGrpcConverters.java
@@ -0,0 +1,441 @@
+package org.caosdb.server.grpc;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import org.caosdb.api.entity.v1.AtomicDataType;
+import org.caosdb.api.entity.v1.CollectionValues;
+import org.caosdb.api.entity.v1.DataType;
+import org.caosdb.api.entity.v1.Entity;
+import org.caosdb.api.entity.v1.Entity.Builder;
+import org.caosdb.api.entity.v1.EntityResponse;
+import org.caosdb.api.entity.v1.EntityRole;
+import org.caosdb.api.entity.v1.Importance;
+import org.caosdb.api.entity.v1.ListDataType;
+import org.caosdb.api.entity.v1.MessageCode;
+import org.caosdb.api.entity.v1.Parent;
+import org.caosdb.api.entity.v1.ReferenceDataType;
+import org.caosdb.api.entity.v1.ScalarValue;
+import org.caosdb.api.entity.v1.SpecialValue;
+import org.caosdb.api.entity.v1.Version;
+import org.caosdb.datetime.DateTimeInterface;
+import org.caosdb.server.datatype.AbstractCollectionDatatype;
+import org.caosdb.server.datatype.AbstractDatatype;
+import org.caosdb.server.datatype.BooleanDatatype;
+import org.caosdb.server.datatype.BooleanValue;
+import org.caosdb.server.datatype.CollectionValue;
+import org.caosdb.server.datatype.DateTimeDatatype;
+import org.caosdb.server.datatype.DoubleDatatype;
+import org.caosdb.server.datatype.FileDatatype;
+import org.caosdb.server.datatype.GenericValue;
+import org.caosdb.server.datatype.IndexedSingleValue;
+import org.caosdb.server.datatype.IntegerDatatype;
+import org.caosdb.server.datatype.ReferenceDatatype;
+import org.caosdb.server.datatype.ReferenceDatatype2;
+import org.caosdb.server.datatype.ReferenceValue;
+import org.caosdb.server.datatype.TextDatatype;
+import org.caosdb.server.datatype.Value;
+import org.caosdb.server.entity.EntityInterface;
+import org.caosdb.server.entity.MagicTypes;
+import org.caosdb.server.entity.Message;
+import org.caosdb.server.entity.Role;
+import org.caosdb.server.entity.StatementStatus;
+import org.caosdb.server.entity.container.ParentContainer;
+import org.caosdb.server.entity.container.PropertyContainer;
+import org.caosdb.server.entity.wrapper.Property;
+
+public class CaosDBToGrpcConverters {
+
+  /** Get the unit as string. */
+  public String getStringUnit(final EntityInterface entity) {
+    final Iterator<Property> iterator = entity.getProperties().iterator();
+    while (iterator.hasNext()) {
+      final Property p = iterator.next();
+      if (MagicTypes.UNIT.getId() == p.getId()) {
+        iterator.remove();
+        return p.getValue().toString();
+      }
+    }
+    return null;
+  }
+
+  public EntityResponse.Builder convert(final EntityInterface from) {
+
+    final Builder entityBuilder = Entity.newBuilder();
+
+    if (from.hasId()) {
+      entityBuilder.setId(Integer.toString(from.getId()));
+    }
+    if (from.getRole() != null) {
+      entityBuilder.setRole(convert(from.getRole()));
+    }
+    if (from.hasName()) {
+      entityBuilder.setName(from.getName());
+    }
+    if (from.hasDescription()) {
+      entityBuilder.setDescription(from.getDescription());
+    }
+    if (from.hasDatatype()) {
+      entityBuilder.setDataType(convert(from.getDatatype()));
+    }
+    if (from.hasValue()) {
+      try {
+        from.parseValue();
+      } catch (final Message e) {
+        // ignore. This problem should be handled elsewhere because this is
+        // only for the serialization of the data and not for the validation.
+        // In any case, the string representation can be used.
+      }
+      entityBuilder.setValue(convert(from.getValue()));
+    }
+    final String unit = getStringUnit(from);
+    if (unit != null) {
+      entityBuilder.setUnit(unit);
+    }
+    if (from.hasProperties()) {
+      entityBuilder.addAllProperties(convert(from.getProperties()));
+    }
+    if (from.hasParents()) {
+      entityBuilder.addAllParents(convert(from.getParents()));
+    }
+
+    final EntityResponse.Builder responseBuilder = EntityResponse.newBuilder();
+    responseBuilder.setEntity(entityBuilder);
+
+    appendMessages(from, responseBuilder);
+
+    return responseBuilder;
+  }
+
+  private EntityRole convert(final Role role) {
+    switch (role) {
+      case RecordType:
+        return EntityRole.ENTITY_ROLE_RECORD_TYPE;
+      case Record:
+        return EntityRole.ENTITY_ROLE_RECORD;
+      case Property:
+        return EntityRole.ENTITY_ROLE_PROPERTY;
+      case File:
+        return EntityRole.ENTITY_ROLE_FILE;
+      default:
+        return EntityRole.ENTITY_ROLE_UNSPECIFIED;
+    }
+  }
+
+  public Iterable<? extends org.caosdb.api.entity.v1.Message> convert(
+      final List<Message> messages) {
+    final List<org.caosdb.api.entity.v1.Message> result = new LinkedList<>();
+    for (final Message m : messages) {
+      result.add(convert(m));
+    }
+    return result;
+  }
+
+  public org.caosdb.api.entity.v1.Message convert(final Message m) {
+    final org.caosdb.api.entity.v1.Message.Builder builder =
+        org.caosdb.api.entity.v1.Message.newBuilder();
+    final MessageCode code = getMessageCode(m);
+    builder.setCode(code.getNumber());
+    builder.setDescription(m.getDescription());
+    return builder.build();
+  }
+
+  public static MessageCode getMessageCode(final Message m) {
+    return m.getCode();
+  }
+
+  public Version convert(final org.caosdb.server.entity.Version from) {
+    final org.caosdb.api.entity.v1.Version.Builder builder = Version.newBuilder();
+
+    builder.setId(from.getId());
+    return builder.build();
+  }
+
+  public Parent convert(final org.caosdb.server.entity.wrapper.Parent from) {
+    final org.caosdb.api.entity.v1.Parent.Builder builder = Parent.newBuilder();
+    if (from.hasId()) {
+      builder.setId(from.getId().toString());
+    }
+    if (from.hasName()) {
+      builder.setName(from.getName());
+    }
+    if (from.hasDescription()) {
+      builder.setDescription(from.getDescription());
+    }
+
+    return builder.build();
+  }
+
+  public org.caosdb.api.entity.v1.Property convert(final Property from) {
+    final org.caosdb.api.entity.v1.Property.Builder builder =
+        org.caosdb.api.entity.v1.Property.newBuilder();
+
+    if (from.hasId()) {
+      builder.setId(from.getId().toString());
+    }
+    if (from.hasName()) {
+      builder.setName(from.getName());
+    }
+    if (from.hasDescription()) {
+      builder.setDescription(from.getDescription());
+    }
+    if (from.hasDatatype()) {
+      builder.setDataType(convert(from.getDatatype()));
+    }
+    final String unit = getStringUnit(from);
+    if (unit != null) {
+      builder.setUnit(unit);
+    }
+    if (from.hasValue()) {
+      try {
+        from.parseValue();
+      } catch (final Message e) {
+        // ignore. This problem should be handled elsewhere because this is
+        // only for the serialization of the data and not for the validation.
+        // In any case, the string representation can be used.
+      }
+      builder.setValue(convert(from.getValue()));
+    }
+    builder.setImportance(convert(from.getStatementStatus()));
+    return builder.build();
+  }
+
+  private org.caosdb.api.entity.v1.Value.Builder convert(final Value value) {
+    if (value instanceof CollectionValue) {
+      return convertCollectionValue((CollectionValue) value);
+    }
+    final org.caosdb.api.entity.v1.Value.Builder builder =
+        org.caosdb.api.entity.v1.Value.newBuilder();
+    builder.setScalarValue(convertScalarValue(value));
+    return builder;
+  }
+
+  private ScalarValue.Builder convertScalarValue(final Value value) {
+
+    if (value instanceof BooleanValue) {
+      return convertBooleanValue((BooleanValue) value);
+
+    } else if (value instanceof ReferenceValue) {
+      return convertReferenceValue((ReferenceValue) value);
+
+    } else if (value instanceof DateTimeInterface) {
+      return convertDateTimeInterface((DateTimeInterface) value);
+
+    } else if (value instanceof GenericValue) {
+      return convertGenericValue((GenericValue) value);
+    }
+    return null;
+  }
+
+  private ScalarValue.Builder convertGenericValue(final GenericValue value) {
+    final Object wrappedValue = value.getValue();
+    if (wrappedValue instanceof Double) {
+      return ScalarValue.newBuilder().setDoubleValue((Double) wrappedValue);
+    } else if (wrappedValue instanceof Integer) {
+      return ScalarValue.newBuilder().setIntegerValue((Integer) wrappedValue);
+    } else {
+      return convertStringValue(value);
+    }
+  }
+
+  private org.caosdb.api.entity.v1.ScalarValue.Builder convertStringValue(final Value value) {
+    if (value.toString().isEmpty()) {
+      return ScalarValue.newBuilder().setSpecialValue(SpecialValue.SPECIAL_VALUE_EMPTY_STRING);
+    }
+    return ScalarValue.newBuilder().setStringValue(value.toString());
+  }
+
+  private org.caosdb.api.entity.v1.ScalarValue.Builder convertDateTimeInterface(
+      final DateTimeInterface value) {
+    return convertStringValue(value);
+  }
+
+  private org.caosdb.api.entity.v1.ScalarValue.Builder convertBooleanValue(
+      final BooleanValue value) {
+    return ScalarValue.newBuilder().setBooleanValue(value.getValue());
+  }
+
+  private ScalarValue.Builder convertReferenceValue(final ReferenceValue value) {
+    return convertStringValue(value);
+  }
+
+  private org.caosdb.api.entity.v1.Value.Builder convertCollectionValue(
+      final CollectionValue value) {
+
+    final org.caosdb.api.entity.v1.Value.Builder builder =
+        org.caosdb.api.entity.v1.Value.newBuilder();
+    final List<ScalarValue> values = new LinkedList<>();
+    value.forEach(
+        (v) -> {
+          values.add(convertScalarValue(v));
+        });
+    builder.setListValues(CollectionValues.newBuilder().addAllValues(values));
+    return builder;
+  }
+
+  private ScalarValue convertScalarValue(final IndexedSingleValue v) {
+    return convertScalarValue(v.getWrapped()).build();
+  }
+
+  private Importance convert(final StatementStatus statementStatus) {
+    switch (statementStatus) {
+      case FIX:
+        return Importance.IMPORTANCE_FIX;
+      case OBLIGATORY:
+        return Importance.IMPORTANCE_OBLIGATORY;
+      case RECOMMENDED:
+        return Importance.IMPORTANCE_RECOMMENDED;
+      case SUGGESTED:
+        return Importance.IMPORTANCE_SUGGESTED;
+      default:
+        return null;
+    }
+  }
+
+  private org.caosdb.api.entity.v1.DataType.Builder convert(final AbstractDatatype datatype) {
+    if (datatype instanceof ReferenceDatatype2) {
+      return DataType.newBuilder()
+          .setReferenceDataType(convertReferenceDatatype((ReferenceDatatype2) datatype));
+    } else if (datatype instanceof FileDatatype) {
+      return DataType.newBuilder()
+          .setReferenceDataType(convertReferenceDatatype((FileDatatype) datatype));
+    } else if (datatype instanceof ReferenceDatatype) {
+      return DataType.newBuilder()
+          .setReferenceDataType(convertReferenceDatatype((ReferenceDatatype) datatype));
+    } else if (datatype instanceof AbstractCollectionDatatype) {
+      return DataType.newBuilder()
+          .setListDataType(
+              convertAbstractCollectionDatatype((AbstractCollectionDatatype) datatype));
+    } else if (datatype instanceof BooleanDatatype) {
+      return DataType.newBuilder()
+          .setAtomicDataType(convertBooleanDatatype((BooleanDatatype) datatype));
+
+    } else if (datatype instanceof DateTimeDatatype) {
+      return DataType.newBuilder()
+          .setAtomicDataType(convertDateTimeDatatype((DateTimeDatatype) datatype));
+
+    } else if (datatype instanceof DoubleDatatype) {
+      return DataType.newBuilder()
+          .setAtomicDataType(convertDoubleDatatype((DoubleDatatype) datatype));
+
+    } else if (datatype instanceof IntegerDatatype) {
+      return DataType.newBuilder()
+          .setAtomicDataType(convertIntegerDatatype((IntegerDatatype) datatype));
+
+    } else if (datatype instanceof TextDatatype) {
+      return DataType.newBuilder().setAtomicDataType(convertTextDatatype((TextDatatype) datatype));
+    }
+    return null;
+  }
+
+  private AtomicDataType convertTextDatatype(final TextDatatype datatype) {
+    return AtomicDataType.ATOMIC_DATA_TYPE_TEXT;
+  }
+
+  private AtomicDataType convertIntegerDatatype(final IntegerDatatype datatype) {
+    return AtomicDataType.ATOMIC_DATA_TYPE_INTEGER;
+  }
+
+  private AtomicDataType convertDoubleDatatype(final DoubleDatatype datatype) {
+    return AtomicDataType.ATOMIC_DATA_TYPE_DOUBLE;
+  }
+
+  private AtomicDataType convertDateTimeDatatype(final DateTimeDatatype datatype) {
+    return AtomicDataType.ATOMIC_DATA_TYPE_DATETIME;
+  }
+
+  private AtomicDataType convertBooleanDatatype(final BooleanDatatype datatype) {
+    return AtomicDataType.ATOMIC_DATA_TYPE_BOOLEAN;
+  }
+
+  private org.caosdb.api.entity.v1.ListDataType.Builder convertAbstractCollectionDatatype(
+      final AbstractCollectionDatatype collectionDatatype) {
+
+    final org.caosdb.api.entity.v1.ListDataType.Builder listBuilder = ListDataType.newBuilder();
+    final AbstractDatatype datatype = collectionDatatype.getDatatype();
+    if (datatype instanceof ReferenceDatatype) {
+      listBuilder.setReferenceDataType(convertReferenceDatatype((ReferenceDatatype) datatype));
+    } else if (datatype instanceof BooleanDatatype) {
+      return listBuilder.setAtomicDataType(convertBooleanDatatype((BooleanDatatype) datatype));
+
+    } else if (datatype instanceof DateTimeDatatype) {
+      return listBuilder.setAtomicDataType(convertDateTimeDatatype((DateTimeDatatype) datatype));
+
+    } else if (datatype instanceof DoubleDatatype) {
+      return listBuilder.setAtomicDataType(convertDoubleDatatype((DoubleDatatype) datatype));
+
+    } else if (datatype instanceof IntegerDatatype) {
+      return listBuilder.setAtomicDataType(convertIntegerDatatype((IntegerDatatype) datatype));
+
+    } else if (datatype instanceof TextDatatype) {
+      return listBuilder.setAtomicDataType(convertTextDatatype((TextDatatype) datatype));
+    }
+    return listBuilder;
+  }
+
+  private org.caosdb.api.entity.v1.ReferenceDataType.Builder convertReferenceDatatype(
+      final ReferenceDatatype datatype) {
+    return ReferenceDataType.newBuilder().setName(datatype.getName());
+  }
+
+  public Iterable<? extends org.caosdb.api.entity.v1.Property> convert(
+      final PropertyContainer from) {
+    final Iterator<org.caosdb.server.entity.wrapper.Property> iterator = from.iterator();
+    return () ->
+        new Iterator<>() {
+
+          @Override
+          public boolean hasNext() {
+            return iterator.hasNext();
+          }
+
+          @Override
+          public org.caosdb.api.entity.v1.Property next() {
+            return convert(iterator.next());
+          }
+        };
+  }
+
+  public Iterable<? extends Parent> convert(final ParentContainer from) {
+    final Iterator<org.caosdb.server.entity.wrapper.Parent> iterator = from.iterator();
+    return () ->
+        new Iterator<>() {
+
+          @Override
+          public boolean hasNext() {
+            return iterator.hasNext();
+          }
+
+          @Override
+          public Parent next() {
+            return convert(iterator.next());
+          }
+        };
+  }
+
+  public void appendMessages(
+      final EntityInterface from, final org.caosdb.api.entity.v1.EntityResponse.Builder builder) {
+    if (from.hasMessage(Message.MessageType.Error.toString())) {
+      builder.addAllErrors(convert(from.getMessages(Message.MessageType.Error.toString())));
+    }
+    if (from.hasMessage(Message.MessageType.Warning.toString())) {
+      builder.addAllWarnings(convert(from.getMessages(Message.MessageType.Warning.toString())));
+    }
+    if (from.hasMessage(Message.MessageType.Info.toString())) {
+      builder.addAllInfos(convert(from.getMessages(Message.MessageType.Info.toString())));
+    }
+  }
+
+  public void appendMessages(
+      final EntityInterface from, final org.caosdb.api.entity.v1.IdResponse.Builder builder) {
+    if (from.hasMessage(Message.MessageType.Error.toString())) {
+      builder.addAllErrors(convert(from.getMessages(Message.MessageType.Error.toString())));
+    }
+    if (from.hasMessage(Message.MessageType.Warning.toString())) {
+      builder.addAllWarnings(convert(from.getMessages(Message.MessageType.Warning.toString())));
+    }
+    if (from.hasMessage(Message.MessageType.Info.toString())) {
+      builder.addAllInfos(convert(from.getMessages(Message.MessageType.Info.toString())));
+    }
+  }
+}
diff --git a/src/main/java/org/caosdb/server/grpc/DownloadBuffer.java b/src/main/java/org/caosdb/server/grpc/DownloadBuffer.java
index ba54a1c84219cd29b80eecd9ee9107c7a3572c93..06c387624c887f5ceeb73efb3ee7b042519a1a6f 100644
--- a/src/main/java/org/caosdb/server/grpc/DownloadBuffer.java
+++ b/src/main/java/org/caosdb/server/grpc/DownloadBuffer.java
@@ -7,9 +7,9 @@ import java.io.IOException;
 import java.nio.MappedByteBuffer;
 import java.nio.channels.FileChannel;
 import java.nio.channels.FileChannel.MapMode;
-import org.caosdb.api.entity.v1alpha1.FileChunk;
-import org.caosdb.api.entity.v1alpha1.FileDownloadResponse;
-import org.caosdb.api.entity.v1alpha1.TransmissionStatus;
+import org.caosdb.api.entity.v1.FileChunk;
+import org.caosdb.api.entity.v1.FileDownloadResponse;
+import org.caosdb.api.entity.v1.TransmissionStatus;
 import org.caosdb.server.entity.FileProperties;
 
 public class DownloadBuffer {
diff --git a/src/main/java/org/caosdb/server/grpc/EntityTransactionServiceImpl.java b/src/main/java/org/caosdb/server/grpc/EntityTransactionServiceImpl.java
index 7f5434df15bd3653462c702a6a500f699e28f69b..a9c74cc1bed1cdd0de26847e629d1264db377753 100644
--- a/src/main/java/org/caosdb/server/grpc/EntityTransactionServiceImpl.java
+++ b/src/main/java/org/caosdb/server/grpc/EntityTransactionServiceImpl.java
@@ -1,473 +1,47 @@
 package org.caosdb.server.grpc;
 
 import io.grpc.stub.StreamObserver;
-import java.util.Collection;
 import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
 import java.util.UUID;
 import org.apache.shiro.SecurityUtils;
-import org.caosdb.api.entity.v1alpha1.AtomicDataType;
-import org.caosdb.api.entity.v1alpha1.CollectionValues;
-import org.caosdb.api.entity.v1alpha1.DataType;
-import org.caosdb.api.entity.v1alpha1.DeleteRequest;
-import org.caosdb.api.entity.v1alpha1.DeleteResponse;
-import org.caosdb.api.entity.v1alpha1.Entity;
-import org.caosdb.api.entity.v1alpha1.Entity.Builder;
-import org.caosdb.api.entity.v1alpha1.EntityRequest;
-import org.caosdb.api.entity.v1alpha1.EntityResponse;
-import org.caosdb.api.entity.v1alpha1.EntityRole;
-import org.caosdb.api.entity.v1alpha1.EntityTransactionServiceGrpc.EntityTransactionServiceImplBase;
-import org.caosdb.api.entity.v1alpha1.FileDescriptor;
-import org.caosdb.api.entity.v1alpha1.IdResponse;
-import org.caosdb.api.entity.v1alpha1.Importance;
-import org.caosdb.api.entity.v1alpha1.InsertRequest;
-import org.caosdb.api.entity.v1alpha1.InsertResponse;
-import org.caosdb.api.entity.v1alpha1.ListDataType;
-import org.caosdb.api.entity.v1alpha1.MessageCode;
-import org.caosdb.api.entity.v1alpha1.MultiTransactionRequest;
-import org.caosdb.api.entity.v1alpha1.MultiTransactionResponse;
-import org.caosdb.api.entity.v1alpha1.Parent;
-import org.caosdb.api.entity.v1alpha1.ReferenceDataType;
-import org.caosdb.api.entity.v1alpha1.RetrieveResponse;
-import org.caosdb.api.entity.v1alpha1.ScalarValue;
-import org.caosdb.api.entity.v1alpha1.SpecialValue;
-import org.caosdb.api.entity.v1alpha1.TransactionRequest;
-import org.caosdb.api.entity.v1alpha1.TransactionRequest.WrappedRequestsCase;
-import org.caosdb.api.entity.v1alpha1.TransactionResponse;
-import org.caosdb.api.entity.v1alpha1.UpdateRequest;
-import org.caosdb.api.entity.v1alpha1.UpdateResponse;
-import org.caosdb.api.entity.v1alpha1.Version;
-import org.caosdb.datetime.DateTimeInterface;
+import org.caosdb.api.entity.v1.DeleteRequest;
+import org.caosdb.api.entity.v1.DeleteResponse;
+import org.caosdb.api.entity.v1.Entity;
+import org.caosdb.api.entity.v1.EntityRequest;
+import org.caosdb.api.entity.v1.EntityResponse;
+import org.caosdb.api.entity.v1.EntityTransactionServiceGrpc.EntityTransactionServiceImplBase;
+import org.caosdb.api.entity.v1.IdResponse;
+import org.caosdb.api.entity.v1.InsertRequest;
+import org.caosdb.api.entity.v1.InsertResponse;
+import org.caosdb.api.entity.v1.MultiTransactionRequest;
+import org.caosdb.api.entity.v1.MultiTransactionResponse;
+import org.caosdb.api.entity.v1.RetrieveResponse;
+import org.caosdb.api.entity.v1.TransactionRequest;
+import org.caosdb.api.entity.v1.TransactionRequest.WrappedRequestsCase;
+import org.caosdb.api.entity.v1.TransactionResponse;
+import org.caosdb.api.entity.v1.UpdateRequest;
+import org.caosdb.api.entity.v1.UpdateResponse;
 import org.caosdb.server.CaosDBException;
-import org.caosdb.server.datatype.AbstractCollectionDatatype;
-import org.caosdb.server.datatype.AbstractDatatype;
-import org.caosdb.server.datatype.BooleanDatatype;
-import org.caosdb.server.datatype.BooleanValue;
-import org.caosdb.server.datatype.CollectionValue;
-import org.caosdb.server.datatype.DateTimeDatatype;
-import org.caosdb.server.datatype.DoubleDatatype;
-import org.caosdb.server.datatype.FileDatatype;
-import org.caosdb.server.datatype.GenericValue;
-import org.caosdb.server.datatype.IndexedSingleValue;
-import org.caosdb.server.datatype.IntegerDatatype;
-import org.caosdb.server.datatype.ListDatatype;
-import org.caosdb.server.datatype.ReferenceDatatype;
-import org.caosdb.server.datatype.ReferenceDatatype2;
-import org.caosdb.server.datatype.ReferenceValue;
-import org.caosdb.server.datatype.TextDatatype;
-import org.caosdb.server.datatype.Value;
 import org.caosdb.server.entity.DeleteEntity;
 import org.caosdb.server.entity.EntityInterface;
 import org.caosdb.server.entity.FileProperties;
 import org.caosdb.server.entity.InsertEntity;
-import org.caosdb.server.entity.MagicTypes;
-import org.caosdb.server.entity.Message;
 import org.caosdb.server.entity.RetrieveEntity;
-import org.caosdb.server.entity.Role;
-import org.caosdb.server.entity.StatementStatus;
 import org.caosdb.server.entity.UpdateEntity;
-import org.caosdb.server.entity.container.ParentContainer;
-import org.caosdb.server.entity.container.PropertyContainer;
 import org.caosdb.server.entity.container.RetrieveContainer;
 import org.caosdb.server.entity.container.WritableContainer;
-import org.caosdb.server.entity.wrapper.Property;
 import org.caosdb.server.transaction.Retrieve;
 import org.caosdb.server.transaction.WriteTransaction;
-import org.caosdb.server.utils.EntityStatus;
 import org.caosdb.server.utils.ServerMessages;
 
 public class EntityTransactionServiceImpl extends EntityTransactionServiceImplBase {
 
-  public EntityTransactionServiceImpl(final FileTransmissionServiceImpl fileTransmissionService) {
-    this.fileTransmissionService = fileTransmissionService;
-  }
-
+  private final CaosDBToGrpcConverters caosdbToGrpc = new CaosDBToGrpcConverters();
+  private final GrpcToCaosDBConverters grpcToCaosdb = new GrpcToCaosDBConverters();
   private final FileTransmissionServiceImpl fileTransmissionService;
 
-  /** Get the unit as string. */
-  public String getStringUnit(final EntityInterface entity) {
-    final Iterator<Property> iterator = entity.getProperties().iterator();
-    while (iterator.hasNext()) {
-      final Property p = iterator.next();
-      if (MagicTypes.UNIT.getId() == p.getId()) {
-        iterator.remove();
-        return p.getValue().toString();
-      }
-    }
-    return null;
-  }
-
-  public EntityResponse.Builder convert(final EntityInterface from) {
-
-    final Builder entityBuilder = Entity.newBuilder();
-
-    if (from.hasId()) {
-      entityBuilder.setId(Integer.toString(from.getId()));
-    }
-    if (from.getRole() != null) {
-      entityBuilder.setRole(convert(from.getRole()));
-    }
-    if (from.hasName()) {
-      entityBuilder.setName(from.getName());
-    }
-    if (from.hasDescription()) {
-      entityBuilder.setDescription(from.getDescription());
-    }
-    if (from.hasDatatype()) {
-      entityBuilder.setDataType(convert(from.getDatatype()));
-    }
-    if (from.hasValue()) {
-      try {
-        from.parseValue();
-      } catch (final Message e) {
-        // ignore. This problem should be handled elsewhere because this is
-        // only for the serialization of the data and not for the validation.
-        // In any case, the string representation can be used.
-      }
-      entityBuilder.setValue(convert(from.getValue()));
-    }
-    final String unit = getStringUnit(from);
-    if (unit != null) {
-      entityBuilder.setUnit(unit);
-    }
-    if (from.hasProperties()) {
-      entityBuilder.addAllProperties(convert(from.getProperties()));
-    }
-    if (from.hasParents()) {
-      entityBuilder.addAllParents(convert(from.getParents()));
-    }
-
-    final EntityResponse.Builder responseBuilder = EntityResponse.newBuilder();
-    responseBuilder.setEntity(entityBuilder);
-
-    appendMessages(from, responseBuilder);
-
-    return responseBuilder;
-  }
-
-  private EntityRole convert(final Role role) {
-    switch (role) {
-      case RecordType:
-        return EntityRole.ENTITY_ROLE_RECORD_TYPE;
-      case Record:
-        return EntityRole.ENTITY_ROLE_RECORD;
-      case Property:
-        return EntityRole.ENTITY_ROLE_PROPERTY;
-      case File:
-        return EntityRole.ENTITY_ROLE_FILE;
-      default:
-        return EntityRole.ENTITY_ROLE_UNSPECIFIED;
-    }
-  }
-
-  public static Iterable<? extends org.caosdb.api.entity.v1alpha1.Message> convert(
-      final List<Message> messages) {
-    final List<org.caosdb.api.entity.v1alpha1.Message> result = new LinkedList<>();
-    for (final Message m : messages) {
-      result.add(convert(m));
-    }
-    return result;
-  }
-
-  public static org.caosdb.api.entity.v1alpha1.Message convert(final Message m) {
-    final org.caosdb.api.entity.v1alpha1.Message.Builder builder =
-        org.caosdb.api.entity.v1alpha1.Message.newBuilder();
-    final MessageCode code = getMessageCode(m);
-    builder.setCode(code.getNumber());
-    builder.setDescription(m.getDescription());
-    return builder.build();
-  }
-
-  public static MessageCode getMessageCode(final Message m) {
-    if (m.equalsCore(ServerMessages.ENTITY_DOES_NOT_EXIST)) {
-      return MessageCode.MESSAGE_CODE_ENTITY_DOES_NOT_EXIST;
-    } else if (m.equalsCore(ServerMessages.ENTITY_HAS_NO_PROPERTIES)) {
-      return MessageCode.MESSAGE_CODE_ENTITY_HAS_NO_PROPERTIES;
-    } else if (m.equalsCore(ServerMessages.INTEGER_OUT_OF_RANGE)) {
-      return MessageCode.MESSAGE_CODE_INTEGER_VALUE_OUT_OF_RANGE;
-    } else if (m.equalsCore(ServerMessages.ENTITY_HAS_BEEN_DELETED_SUCCESSFULLY)) {
-      return MessageCode.MESSAGE_CODE_ENTITY_HAS_BEEN_DELETED_SUCCESSFULLY;
-    } else if (m.getCode() == 0) {
-      return MessageCode.MESSAGE_CODE_UNSPECIFIED;
-    } else {
-      return MessageCode.MESSAGE_CODE_UNKNOWN;
-    }
-  }
-
-  public Version convert(final org.caosdb.server.entity.Version from) {
-    final org.caosdb.api.entity.v1alpha1.Version.Builder builder = Version.newBuilder();
-
-    builder.setId(from.getId());
-    return builder.build();
-  }
-
-  public Parent convert(final org.caosdb.server.entity.wrapper.Parent from) {
-    final org.caosdb.api.entity.v1alpha1.Parent.Builder builder = Parent.newBuilder();
-    if (from.hasId()) {
-      builder.setId(from.getId().toString());
-    }
-    if (from.hasName()) {
-      builder.setName(from.getName());
-    }
-    if (from.hasDescription()) {
-      builder.setDescription(from.getDescription());
-    }
-
-    return builder.build();
-  }
-
-  public org.caosdb.api.entity.v1alpha1.Property convert(final Property from) {
-    final org.caosdb.api.entity.v1alpha1.Property.Builder builder =
-        org.caosdb.api.entity.v1alpha1.Property.newBuilder();
-
-    if (from.hasId()) {
-      builder.setId(from.getId().toString());
-    }
-    if (from.hasName()) {
-      builder.setName(from.getName());
-    }
-    if (from.hasDescription()) {
-      builder.setDescription(from.getDescription());
-    }
-    if (from.hasDatatype()) {
-      builder.setDataType(convert(from.getDatatype()));
-    }
-    final String unit = getStringUnit(from);
-    if (unit != null) {
-      builder.setUnit(unit);
-    }
-    if (from.hasValue()) {
-      try {
-        from.parseValue();
-      } catch (final Message e) {
-        // ignore. This problem should be handled elsewhere because this is
-        // only for the serialization of the data and not for the validation.
-        // In any case, the string representation can be used.
-      }
-      builder.setValue(convert(from.getValue()));
-    }
-    builder.setImportance(convert(from.getStatementStatus()));
-    return builder.build();
-  }
-
-  private org.caosdb.api.entity.v1alpha1.Value.Builder convert(final Value value) {
-    if (value instanceof CollectionValue) {
-      return convertCollectionValue((CollectionValue) value);
-    }
-    final org.caosdb.api.entity.v1alpha1.Value.Builder builder =
-        org.caosdb.api.entity.v1alpha1.Value.newBuilder();
-    builder.setScalarValue(convertScalarValue(value));
-    return builder;
-  }
-
-  private ScalarValue.Builder convertScalarValue(final Value value) {
-
-    if (value instanceof BooleanValue) {
-      return convertBooleanValue((BooleanValue) value);
-
-    } else if (value instanceof ReferenceValue) {
-      return convertReferenceValue((ReferenceValue) value);
-
-    } else if (value instanceof DateTimeInterface) {
-      return convertDateTimeInterface((DateTimeInterface) value);
-
-    } else if (value instanceof GenericValue) {
-      return convertGenericValue((GenericValue) value);
-    }
-    return null;
-  }
-
-  private ScalarValue.Builder convertGenericValue(final GenericValue value) {
-    final Object wrappedValue = value.getValue();
-    if (wrappedValue instanceof Double) {
-      return ScalarValue.newBuilder().setDoubleValue((Double) wrappedValue);
-    } else if (wrappedValue instanceof Integer) {
-      return ScalarValue.newBuilder().setIntegerValue((Integer) wrappedValue);
-    } else {
-      return convertStringValue(value);
-    }
-  }
-
-  private org.caosdb.api.entity.v1alpha1.ScalarValue.Builder convertStringValue(final Value value) {
-    if (value.toString().isEmpty()) {
-      return ScalarValue.newBuilder().setSpecialValue(SpecialValue.SPECIAL_VALUE_EMPTY_STRING);
-    }
-    return ScalarValue.newBuilder().setStringValue(value.toString());
-  }
-
-  private org.caosdb.api.entity.v1alpha1.ScalarValue.Builder convertDateTimeInterface(
-      final DateTimeInterface value) {
-    return convertStringValue(value);
-  }
-
-  private org.caosdb.api.entity.v1alpha1.ScalarValue.Builder convertBooleanValue(
-      final BooleanValue value) {
-    return ScalarValue.newBuilder().setBooleanValue(value.getValue());
-  }
-
-  private ScalarValue.Builder convertReferenceValue(final ReferenceValue value) {
-    return convertStringValue(value);
-  }
-
-  private org.caosdb.api.entity.v1alpha1.Value.Builder convertCollectionValue(
-      final CollectionValue value) {
-
-    final org.caosdb.api.entity.v1alpha1.Value.Builder builder =
-        org.caosdb.api.entity.v1alpha1.Value.newBuilder();
-    final List<ScalarValue> values = new LinkedList<>();
-    value.forEach(
-        (v) -> {
-          values.add(convertScalarValue(v));
-        });
-    builder.setListValues(CollectionValues.newBuilder().addAllValues(values));
-    return builder;
-  }
-
-  private ScalarValue convertScalarValue(final IndexedSingleValue v) {
-    return convertScalarValue(v.getWrapped()).build();
-  }
-
-  private Importance convert(final StatementStatus statementStatus) {
-    switch (statementStatus) {
-      case FIX:
-        return Importance.IMPORTANCE_FIX;
-      case OBLIGATORY:
-        return Importance.IMPORTANCE_OBLIGATORY;
-      case RECOMMENDED:
-        return Importance.IMPORTANCE_RECOMMENDED;
-      case SUGGESTED:
-        return Importance.IMPORTANCE_SUGGESTED;
-      default:
-        return null;
-    }
-  }
-
-  private org.caosdb.api.entity.v1alpha1.DataType.Builder convert(final AbstractDatatype datatype) {
-    if (datatype instanceof ReferenceDatatype2) {
-      return DataType.newBuilder()
-          .setReferenceDataType(convertReferenceDatatype((ReferenceDatatype2) datatype));
-    } else if (datatype instanceof FileDatatype) {
-      return DataType.newBuilder()
-          .setReferenceDataType(convertReferenceDatatype((FileDatatype) datatype));
-    } else if (datatype instanceof ReferenceDatatype) {
-      return DataType.newBuilder()
-          .setReferenceDataType(convertReferenceDatatype((ReferenceDatatype) datatype));
-    } else if (datatype instanceof AbstractCollectionDatatype) {
-      return DataType.newBuilder()
-          .setListDataType(
-              convertAbstractCollectionDatatype((AbstractCollectionDatatype) datatype));
-    } else if (datatype instanceof BooleanDatatype) {
-      return DataType.newBuilder()
-          .setAtomicDataType(convertBooleanDatatype((BooleanDatatype) datatype));
-
-    } else if (datatype instanceof DateTimeDatatype) {
-      return DataType.newBuilder()
-          .setAtomicDataType(convertDateTimeDatatype((DateTimeDatatype) datatype));
-
-    } else if (datatype instanceof DoubleDatatype) {
-      return DataType.newBuilder()
-          .setAtomicDataType(convertDoubleDatatype((DoubleDatatype) datatype));
-
-    } else if (datatype instanceof IntegerDatatype) {
-      return DataType.newBuilder()
-          .setAtomicDataType(convertIntegerDatatype((IntegerDatatype) datatype));
-
-    } else if (datatype instanceof TextDatatype) {
-      return DataType.newBuilder().setAtomicDataType(convertTextDatatype((TextDatatype) datatype));
-    }
-    return null;
-  }
-
-  private AtomicDataType convertTextDatatype(final TextDatatype datatype) {
-    return AtomicDataType.ATOMIC_DATA_TYPE_TEXT;
-  }
-
-  private AtomicDataType convertIntegerDatatype(final IntegerDatatype datatype) {
-    return AtomicDataType.ATOMIC_DATA_TYPE_INTEGER;
-  }
-
-  private AtomicDataType convertDoubleDatatype(final DoubleDatatype datatype) {
-    return AtomicDataType.ATOMIC_DATA_TYPE_DOUBLE;
-  }
-
-  private AtomicDataType convertDateTimeDatatype(final DateTimeDatatype datatype) {
-    return AtomicDataType.ATOMIC_DATA_TYPE_DATETIME;
-  }
-
-  private AtomicDataType convertBooleanDatatype(final BooleanDatatype datatype) {
-    return AtomicDataType.ATOMIC_DATA_TYPE_BOOLEAN;
-  }
-
-  private org.caosdb.api.entity.v1alpha1.ListDataType.Builder convertAbstractCollectionDatatype(
-      final AbstractCollectionDatatype collectionDatatype) {
-
-    final org.caosdb.api.entity.v1alpha1.ListDataType.Builder listBuilder =
-        ListDataType.newBuilder();
-    final AbstractDatatype datatype = collectionDatatype.getDatatype();
-    if (datatype instanceof ReferenceDatatype) {
-      listBuilder.setReferenceDataType(convertReferenceDatatype((ReferenceDatatype) datatype));
-    } else if (datatype instanceof BooleanDatatype) {
-      return listBuilder.setAtomicDataType(convertBooleanDatatype((BooleanDatatype) datatype));
-
-    } else if (datatype instanceof DateTimeDatatype) {
-      return listBuilder.setAtomicDataType(convertDateTimeDatatype((DateTimeDatatype) datatype));
-
-    } else if (datatype instanceof DoubleDatatype) {
-      return listBuilder.setAtomicDataType(convertDoubleDatatype((DoubleDatatype) datatype));
-
-    } else if (datatype instanceof IntegerDatatype) {
-      return listBuilder.setAtomicDataType(convertIntegerDatatype((IntegerDatatype) datatype));
-
-    } else if (datatype instanceof TextDatatype) {
-      return listBuilder.setAtomicDataType(convertTextDatatype((TextDatatype) datatype));
-    }
-    return listBuilder;
-  }
-
-  private org.caosdb.api.entity.v1alpha1.ReferenceDataType.Builder convertReferenceDatatype(
-      final ReferenceDatatype datatype) {
-    return ReferenceDataType.newBuilder().setName(datatype.getName());
-  }
-
-  public Iterable<? extends org.caosdb.api.entity.v1alpha1.Property> convert(
-      final PropertyContainer from) {
-    final Iterator<org.caosdb.server.entity.wrapper.Property> iterator = from.iterator();
-    return () ->
-        new Iterator<>() {
-
-          @Override
-          public boolean hasNext() {
-            return iterator.hasNext();
-          }
-
-          @Override
-          public org.caosdb.api.entity.v1alpha1.Property next() {
-            return convert(iterator.next());
-          }
-        };
-  }
-
-  public Iterable<? extends Parent> convert(final ParentContainer from) {
-    final Iterator<org.caosdb.server.entity.wrapper.Parent> iterator = from.iterator();
-    return () ->
-        new Iterator<>() {
-
-          @Override
-          public boolean hasNext() {
-            return iterator.hasNext();
-          }
-
-          @Override
-          public Parent next() {
-            return convert(iterator.next());
-          }
-        };
-  }
-
-  public Integer getId(final String id) {
-    return Integer.parseInt(id);
+  public EntityTransactionServiceImpl(final FileTransmissionServiceImpl fileTransmissionService) {
+    this.fileTransmissionService = fileTransmissionService;
   }
 
   /**
@@ -503,7 +77,7 @@ public class EntityTransactionServiceImpl extends EntityTransactionServiceImplBa
         final String id = sub_request.getRetrieveRequest().getId();
         if (!id.isBlank()) {
           try {
-            final RetrieveEntity entity = new RetrieveEntity(getId(id));
+            final RetrieveEntity entity = new RetrieveEntity(grpcToCaosdb.getId(id));
             if (fileDownload) {
               entity.setFlag("download_files", "true");
             }
@@ -525,7 +99,7 @@ public class EntityTransactionServiceImpl extends EntityTransactionServiceImplBa
     } else {
       final boolean download_files_container = container.getFlags().containsKey("download_files");
       for (final EntityInterface entity : container) {
-        final EntityResponse.Builder entityResponse = convert(entity);
+        final EntityResponse.Builder entityResponse = caosdbToGrpc.convert(entity);
         if ((download_files_container || entity.getFlags().containsKey("download_files"))
             && entity.hasFileProperties()) {
           if (file_download == null) {
@@ -547,7 +121,7 @@ public class EntityTransactionServiceImpl extends EntityTransactionServiceImplBa
       final String id = sub_request.getRetrieveRequest().getId();
       if (!id.isBlank()) {
         try {
-          getId(id);
+          grpcToCaosdb.getId(id);
         } catch (final NumberFormatException e) {
           // ID wasn't an integer - the server doesn't support string id's yet, so that entity
           // cannot
@@ -564,7 +138,7 @@ public class EntityTransactionServiceImpl extends EntityTransactionServiceImplBa
 
   private EntityResponse entityDoesNotExist(final String id) {
     return EntityResponse.newBuilder()
-        .addErrors(convert(ServerMessages.ENTITY_DOES_NOT_EXIST))
+        .addErrors(caosdbToGrpc.convert(ServerMessages.ENTITY_DOES_NOT_EXIST))
         .setEntity(Entity.newBuilder().setId(id))
         .build();
   }
@@ -632,8 +206,8 @@ public class EntityTransactionServiceImpl extends EntityTransactionServiceImplBa
             final InsertEntity entity =
                 new InsertEntity(
                     insertEntity.getName().isEmpty() ? null : insertEntity.getName(),
-                    convert(insertEntity.getRole()));
-            convert(insertEntity, entity);
+                    grpcToCaosdb.convert(insertEntity.getRole()));
+            grpcToCaosdb.convert(insertEntity, entity);
             addFileUpload(container, entity, insertRequest.getEntityRequest());
             container.add(entity);
           }
@@ -644,9 +218,11 @@ public class EntityTransactionServiceImpl extends EntityTransactionServiceImplBa
 
           try {
             final UpdateEntity entity =
-                new UpdateEntity(getId(updateEntity.getId()), convert(updateEntity.getRole()));
+                new UpdateEntity(
+                    grpcToCaosdb.getId(updateEntity.getId()),
+                    grpcToCaosdb.convert(updateEntity.getRole()));
             entity.setName(updateEntity.getName().isEmpty() ? null : updateEntity.getName());
-            convert(updateEntity, entity);
+            grpcToCaosdb.convert(updateEntity, entity);
             addFileUpload(container, entity, updateRequest.getEntityRequest());
             container.add(entity);
           } catch (final NumberFormatException e) {
@@ -657,7 +233,7 @@ public class EntityTransactionServiceImpl extends EntityTransactionServiceImplBa
         case DELETE_REQUEST:
           final DeleteRequest deleteRequest = subRequest.getDeleteRequest();
           try {
-            final DeleteEntity entity = new DeleteEntity(getId(deleteRequest.getId()));
+            final DeleteEntity entity = new DeleteEntity(grpcToCaosdb.getId(deleteRequest.getId()));
             container.add(entity);
 
           } catch (final NumberFormatException e) {
@@ -684,7 +260,7 @@ public class EntityTransactionServiceImpl extends EntityTransactionServiceImplBa
       if (entity.getId() != null) {
         idResponse.setId(entity.getId().toString());
       }
-      appendMessages(entity, idResponse);
+      caosdbToGrpc.appendMessages(entity, idResponse);
 
       if (entity instanceof InsertEntity) {
         builder
@@ -713,7 +289,7 @@ public class EntityTransactionServiceImpl extends EntityTransactionServiceImplBa
    * @return
    */
   private MultiTransactionResponse failedWriteDueToStringId(final MultiTransactionRequest request) {
-    final org.caosdb.api.entity.v1alpha1.MultiTransactionResponse.Builder builder =
+    final org.caosdb.api.entity.v1.MultiTransactionResponse.Builder builder =
         MultiTransactionResponse.newBuilder();
     for (final TransactionRequest subRequest : request.getRequestsList()) {
       final IdResponse.Builder idResponse = IdResponse.newBuilder();
@@ -730,10 +306,10 @@ public class EntityTransactionServiceImpl extends EntityTransactionServiceImplBa
 
           idResponse.setId(updateEntity.getId());
           try {
-            getId(updateEntity.getId());
+            grpcToCaosdb.getId(updateEntity.getId());
           } catch (final NumberFormatException e) {
             // ID wasn't an integer
-            idResponse.addErrors(convert(ServerMessages.ENTITY_DOES_NOT_EXIST));
+            idResponse.addErrors(caosdbToGrpc.convert(ServerMessages.ENTITY_DOES_NOT_EXIST));
           }
           builder
               .addResponsesBuilder()
@@ -743,10 +319,10 @@ public class EntityTransactionServiceImpl extends EntityTransactionServiceImplBa
           final DeleteRequest deleteRequest = subRequest.getDeleteRequest();
           idResponse.setId(deleteRequest.getId());
           try {
-            getId(deleteRequest.getId());
+            grpcToCaosdb.getId(deleteRequest.getId());
           } catch (final NumberFormatException e) {
             // ID wasn't an integer
-            idResponse.addErrors(convert(ServerMessages.ENTITY_DOES_NOT_EXIST));
+            idResponse.addErrors(caosdbToGrpc.convert(ServerMessages.ENTITY_DOES_NOT_EXIST));
           }
           builder
               .addResponsesBuilder()
@@ -778,281 +354,6 @@ public class EntityTransactionServiceImpl extends EntityTransactionServiceImplBa
     }
   }
 
-  private Role convert(final EntityRole role) {
-    switch (role) {
-      case ENTITY_ROLE_FILE:
-        return Role.File;
-      case ENTITY_ROLE_PROPERTY:
-        return Role.Property;
-      case ENTITY_ROLE_RECORD:
-        return Role.Record;
-      case ENTITY_ROLE_RECORD_TYPE:
-        return Role.RecordType;
-      default:
-        return null;
-    }
-  }
-
-  private void appendMessages(
-      final EntityInterface from,
-      final org.caosdb.api.entity.v1alpha1.EntityResponse.Builder builder) {
-    if (from.hasMessage(Message.MessageType.Error.toString())) {
-      builder.addAllErrors(convert(from.getMessages(Message.MessageType.Error.toString())));
-    }
-    if (from.hasMessage(Message.MessageType.Warning.toString())) {
-      builder.addAllWarnings(convert(from.getMessages(Message.MessageType.Warning.toString())));
-    }
-    if (from.hasMessage(Message.MessageType.Info.toString())) {
-      builder.addAllInfos(convert(from.getMessages(Message.MessageType.Info.toString())));
-    }
-  }
-
-  private void appendMessages(
-      final EntityInterface from, final org.caosdb.api.entity.v1alpha1.IdResponse.Builder builder) {
-    if (from.hasMessage(Message.MessageType.Error.toString())) {
-      builder.addAllErrors(convert(from.getMessages(Message.MessageType.Error.toString())));
-    }
-    if (from.hasMessage(Message.MessageType.Warning.toString())) {
-      builder.addAllWarnings(convert(from.getMessages(Message.MessageType.Warning.toString())));
-    }
-    if (from.hasMessage(Message.MessageType.Info.toString())) {
-      builder.addAllInfos(convert(from.getMessages(Message.MessageType.Info.toString())));
-    }
-  }
-
-  public Property getUnit(final String unitStr) {
-    final EntityInterface magicUnit = MagicTypes.UNIT.getEntity();
-    final Property unit = new Property();
-    unit.setDescription(magicUnit.getDescription());
-    unit.setName(magicUnit.getName());
-    unit.setId(magicUnit.getId());
-    unit.setDatatype(magicUnit.getDatatype());
-    unit.setStatementStatus(StatementStatus.FIX);
-    unit.setValue(new GenericValue(unitStr));
-    unit.setEntityStatus(EntityStatus.QUALIFIED);
-    return unit;
-  }
-
-  public Value getValue(final String valString) {
-    return new GenericValue(valString);
-  }
-
-  private EntityInterface convert(final Entity from, final EntityInterface entity) {
-    entity.setName(from.getName().isEmpty() ? null : from.getName());
-    entity.setDescription(from.getDescription().isBlank() ? null : from.getDescription());
-    if (!from.getUnit().isBlank()) {
-      entity.addProperty(getUnit(from.getUnit()));
-    }
-    if (from.hasDataType()) {
-      entity.setDatatype(convert(from.getDataType()));
-    }
-    if (from.hasValue()) {
-      entity.setValue(convert(from.getValue()));
-    }
-
-    if (from.getPropertiesCount() > 0) {
-      final StatementStatus defaultImportance =
-          entity.getRole() == Role.RecordType ? StatementStatus.RECOMMENDED : StatementStatus.FIX;
-      entity.getProperties().addAll(convertProperties(from.getPropertiesList(), defaultImportance));
-    }
-    if (from.getParentsCount() > 0) {
-      entity.getParents().addAll(convertParents(from.getParentsList()));
-    }
-    if (from.hasFileDescriptor()) {
-      entity.setFileProperties(convert(from.getFileDescriptor()));
-    }
-    return entity;
-  }
-
-  private Value convert(final org.caosdb.api.entity.v1alpha1.Value value) {
-    switch (value.getValueCase()) {
-      case LIST_VALUES:
-        return convertListValue(value.getListValues());
-      case SCALAR_VALUE:
-        return convertScalarValue(value.getScalarValue());
-      default:
-        break;
-    }
-    return null;
-  }
-
-  private CollectionValue convertListValue(final CollectionValues collectionValues) {
-    final CollectionValue result = new CollectionValue();
-    collectionValues
-        .getValuesList()
-        .forEach(
-            (v) -> {
-              result.add(convertScalarValue(v));
-            });
-    return result;
-  }
-
-  private Value convertScalarValue(final org.caosdb.api.entity.v1alpha1.ScalarValue value) {
-    switch (value.getScalarValueCase()) {
-      case BOOLEAN_VALUE:
-        return BooleanValue.valueOf(value.getBooleanValue());
-      case DOUBLE_VALUE:
-        return new GenericValue(value.getDoubleValue());
-      case INTEGER_VALUE:
-        return new GenericValue(Long.toString(value.getIntegerValue()));
-      case SPECIAL_VALUE:
-        return convertSpecial(value.getSpecialValue());
-      case STRING_VALUE:
-        return new GenericValue(value.getStringValue());
-      default:
-        break;
-    }
-    return null;
-  }
-
-  private Value convertSpecial(final SpecialValue specialValue) {
-    if (specialValue == SpecialValue.SPECIAL_VALUE_EMPTY_STRING) {
-      return new GenericValue("");
-    }
-    return null;
-  }
-
-  private AbstractDatatype convert(final DataType dataType) {
-    switch (dataType.getDataTypeCase()) {
-      case ATOMIC_DATA_TYPE:
-        return convertAtomicType(dataType.getAtomicDataType());
-      case LIST_DATA_TYPE:
-        return convertListDataType(dataType.getListDataType());
-      case REFERENCE_DATA_TYPE:
-        return convertReferenceDataType(dataType.getReferenceDataType());
-      default:
-        break;
-    }
-    return null;
-  }
-
-  private ReferenceDatatype convertReferenceDataType(final ReferenceDataType referenceDataType) {
-    final String name = referenceDataType.getName();
-    if (name.equalsIgnoreCase("REFERENCE")) {
-      return new ReferenceDatatype();
-    } else if (name.equalsIgnoreCase("FILE")) {
-      return new FileDatatype();
-    }
-    return new ReferenceDatatype2(name);
-  }
-
-  private AbstractDatatype convertAtomicType(final AtomicDataType dataType) {
-    switch (dataType) {
-      case ATOMIC_DATA_TYPE_BOOLEAN:
-        return AbstractDatatype.datatypeFactory("BOOLEAN");
-      case ATOMIC_DATA_TYPE_DATETIME:
-        return AbstractDatatype.datatypeFactory("DATETIME");
-      case ATOMIC_DATA_TYPE_DOUBLE:
-        return AbstractDatatype.datatypeFactory("DOUBLE");
-      case ATOMIC_DATA_TYPE_INTEGER:
-        return AbstractDatatype.datatypeFactory("INTEGER");
-      case ATOMIC_DATA_TYPE_TEXT:
-        return AbstractDatatype.datatypeFactory("TEXT");
-      default:
-        return null;
-    }
-  }
-
-  private AbstractDatatype convertListDataType(final ListDataType dataType) {
-    switch (dataType.getListDataTypeCase()) {
-      case ATOMIC_DATA_TYPE:
-        return new ListDatatype(convertAtomicType(dataType.getAtomicDataType()));
-      case REFERENCE_DATA_TYPE:
-        return new ListDatatype(convertReferenceDataType(dataType.getReferenceDataType()));
-      default:
-        return null;
-    }
-  }
-
-  private FileProperties convert(final FileDescriptor fileDescriptor) {
-    return new FileProperties(
-        null,
-        fileDescriptor.getPath(),
-        fileDescriptor.getSize() == 0 ? null : fileDescriptor.getSize());
-  }
-
-  private Collection<Property> convertProperties(
-      final List<org.caosdb.api.entity.v1alpha1.Property> propertiesList,
-      final StatementStatus defaultImportance) {
-    final Collection<Property> result = new LinkedList<>();
-    propertiesList.forEach(
-        e -> {
-          result.add(convert(e, defaultImportance));
-        });
-    return result;
-  }
-
-  private Property convert(
-      final org.caosdb.api.entity.v1alpha1.Property e, final StatementStatus defaultImportance) {
-    final Property result = new Property();
-
-    try {
-      result.setId(e.getId().isBlank() ? null : getId(e.getId()));
-    } catch (final NumberFormatException exc) {
-      result.addError(ServerMessages.ENTITY_DOES_NOT_EXIST);
-    }
-    result.setName(e.getName().isBlank() ? null : e.getName());
-    result.setDescription(e.getDescription().isBlank() ? null : e.getDescription());
-    if (!e.getUnit().isBlank()) {
-      result.addProperty(getUnit(e.getUnit()));
-    }
-    if (e.hasDataType()) {
-      result.setDatatype(convert(e.getDataType()));
-    }
-    if (e.hasValue()) {
-      result.setValue(convert(e.getValue()));
-    }
-    if (e.getImportance() != Importance.IMPORTANCE_UNSPECIFIED) {
-      result.setStatementStatus(convert(e.getImportance()));
-    } else {
-      result.setStatementStatus(defaultImportance);
-    }
-    // TODO remove this hard-coded setting when the API supports flags
-    if (result.getFlag("inheritance") == null) {
-      result.setFlag("inheritance", "fix");
-    }
-
-    return result;
-  }
-
-  private StatementStatus convert(final Importance importance) {
-    switch (importance) {
-      case IMPORTANCE_FIX:
-        return StatementStatus.FIX;
-      case IMPORTANCE_OBLIGATORY:
-        return StatementStatus.OBLIGATORY;
-      case IMPORTANCE_RECOMMENDED:
-        return StatementStatus.RECOMMENDED;
-      case IMPORTANCE_SUGGESTED:
-        return StatementStatus.SUGGESTED;
-      default:
-        return null;
-    }
-  }
-
-  private Collection<org.caosdb.server.entity.wrapper.Parent> convertParents(
-      final List<Parent> parentsList) {
-    final Collection<org.caosdb.server.entity.wrapper.Parent> result = new LinkedList<>();
-    parentsList.forEach(
-        e -> {
-          result.add(convert(e));
-        });
-    return result;
-  }
-
-  private org.caosdb.server.entity.wrapper.Parent convert(final Parent e) {
-    final org.caosdb.server.entity.wrapper.Parent result =
-        new org.caosdb.server.entity.wrapper.Parent();
-
-    try {
-      result.setId(e.getId().isBlank() ? null : getId(e.getId()));
-    } catch (final NumberFormatException exc) {
-      result.addError(ServerMessages.ENTITY_DOES_NOT_EXIST);
-    }
-    result.setName(e.getName().isBlank() ? null : e.getName());
-    return result;
-  }
-
   @Override
   public void multiTransaction(
       final MultiTransactionRequest request,
diff --git a/src/main/java/org/caosdb/server/grpc/FileDownload.java b/src/main/java/org/caosdb/server/grpc/FileDownload.java
index d4fdda381ef7a1dc828c487e1d9357709b030a5c..2f3c79899dac73174c65b14e01dbc08c71f1a243 100644
--- a/src/main/java/org/caosdb/server/grpc/FileDownload.java
+++ b/src/main/java/org/caosdb/server/grpc/FileDownload.java
@@ -4,8 +4,8 @@ import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.util.HashMap;
 import java.util.Map;
-import org.caosdb.api.entity.v1alpha1.FileDownloadResponse;
-import org.caosdb.api.entity.v1alpha1.FileTransmissionSettings;
+import org.caosdb.api.entity.v1.FileDownloadResponse;
+import org.caosdb.api.entity.v1.FileTransmissionSettings;
 import org.caosdb.server.entity.FileProperties;
 import org.caosdb.server.utils.Utils;
 
diff --git a/src/main/java/org/caosdb/server/grpc/FileDownloadRegistration.java b/src/main/java/org/caosdb/server/grpc/FileDownloadRegistration.java
index 579495a10ac49f13c5c21475c75efbb99ac4042a..5130404024e52ec0ac36745452a609b01764dc0d 100644
--- a/src/main/java/org/caosdb/server/grpc/FileDownloadRegistration.java
+++ b/src/main/java/org/caosdb/server/grpc/FileDownloadRegistration.java
@@ -7,9 +7,9 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
-import org.caosdb.api.entity.v1alpha1.FileDownloadResponse;
-import org.caosdb.api.entity.v1alpha1.FileTransmissionId;
-import org.caosdb.api.entity.v1alpha1.FileTransmissionSettings;
+import org.caosdb.api.entity.v1.FileDownloadResponse;
+import org.caosdb.api.entity.v1.FileTransmissionId;
+import org.caosdb.api.entity.v1.FileTransmissionSettings;
 import org.caosdb.server.entity.FileProperties;
 import org.caosdb.server.utils.Utils;
 
diff --git a/src/main/java/org/caosdb/server/grpc/FileTransmission.java b/src/main/java/org/caosdb/server/grpc/FileTransmission.java
index 5440b15cbbdb444f595ea69845300aad1ae0e0d3..67eca23a8f3deb557e0d773e6de7ff0ee38821a2 100644
--- a/src/main/java/org/caosdb/server/grpc/FileTransmission.java
+++ b/src/main/java/org/caosdb/server/grpc/FileTransmission.java
@@ -1,8 +1,8 @@
 package org.caosdb.server.grpc;
 
 import java.util.concurrent.locks.ReentrantLock;
-import org.caosdb.api.entity.v1alpha1.FileTransmissionSettings;
-import org.caosdb.api.entity.v1alpha1.RegistrationStatus;
+import org.caosdb.api.entity.v1.FileTransmissionSettings;
+import org.caosdb.api.entity.v1.RegistrationStatus;
 import org.caosdb.server.entity.FileProperties;
 
 public abstract class FileTransmission {
diff --git a/src/main/java/org/caosdb/server/grpc/FileTransmissionServiceImpl.java b/src/main/java/org/caosdb/server/grpc/FileTransmissionServiceImpl.java
index fd46205354369a4d2893ca06f766c2fccb7a4164..0b0c4b50e0851f3298a61c02c5e38e08c29b2601 100644
--- a/src/main/java/org/caosdb/server/grpc/FileTransmissionServiceImpl.java
+++ b/src/main/java/org/caosdb/server/grpc/FileTransmissionServiceImpl.java
@@ -2,19 +2,19 @@ package org.caosdb.server.grpc;
 
 import io.grpc.stub.StreamObserver;
 import java.io.IOException;
-import org.caosdb.api.entity.v1alpha1.FileChunk;
-import org.caosdb.api.entity.v1alpha1.FileDownloadRequest;
-import org.caosdb.api.entity.v1alpha1.FileDownloadResponse;
-import org.caosdb.api.entity.v1alpha1.FileTransmissionId;
-import org.caosdb.api.entity.v1alpha1.FileTransmissionServiceGrpc.FileTransmissionServiceImplBase;
-import org.caosdb.api.entity.v1alpha1.FileTransmissionSettings;
-import org.caosdb.api.entity.v1alpha1.FileUploadRequest;
-import org.caosdb.api.entity.v1alpha1.FileUploadResponse;
-import org.caosdb.api.entity.v1alpha1.RegisterFileUploadRequest;
-import org.caosdb.api.entity.v1alpha1.RegisterFileUploadResponse;
-import org.caosdb.api.entity.v1alpha1.RegisterFileUploadResponse.Builder;
-import org.caosdb.api.entity.v1alpha1.RegistrationStatus;
-import org.caosdb.api.entity.v1alpha1.TransmissionStatus;
+import org.caosdb.api.entity.v1.FileChunk;
+import org.caosdb.api.entity.v1.FileDownloadRequest;
+import org.caosdb.api.entity.v1.FileDownloadResponse;
+import org.caosdb.api.entity.v1.FileTransmissionId;
+import org.caosdb.api.entity.v1.FileTransmissionServiceGrpc.FileTransmissionServiceImplBase;
+import org.caosdb.api.entity.v1.FileTransmissionSettings;
+import org.caosdb.api.entity.v1.FileUploadRequest;
+import org.caosdb.api.entity.v1.FileUploadResponse;
+import org.caosdb.api.entity.v1.RegisterFileUploadRequest;
+import org.caosdb.api.entity.v1.RegisterFileUploadResponse;
+import org.caosdb.api.entity.v1.RegisterFileUploadResponse.Builder;
+import org.caosdb.api.entity.v1.RegistrationStatus;
+import org.caosdb.api.entity.v1.TransmissionStatus;
 import org.caosdb.server.CaosDBServer;
 import org.caosdb.server.entity.FileProperties;
 import org.caosdb.server.utils.CronJob;
diff --git a/src/main/java/org/caosdb/server/grpc/FileUpload.java b/src/main/java/org/caosdb/server/grpc/FileUpload.java
index c417fd7d2b23841c916fad97a6a6678bd1cd8f21..2ec4ca3de3d5d7ad5b9c44ec16deade8725d9145 100644
--- a/src/main/java/org/caosdb/server/grpc/FileUpload.java
+++ b/src/main/java/org/caosdb/server/grpc/FileUpload.java
@@ -5,10 +5,10 @@ import java.io.File;
 import java.io.IOException;
 import java.util.HashMap;
 import java.util.Map;
-import org.caosdb.api.entity.v1alpha1.FileChunk;
-import org.caosdb.api.entity.v1alpha1.FileTransmissionSettings;
-import org.caosdb.api.entity.v1alpha1.FileTransmissionSettings.Builder;
-import org.caosdb.api.entity.v1alpha1.TransmissionStatus;
+import org.caosdb.api.entity.v1.FileChunk;
+import org.caosdb.api.entity.v1.FileTransmissionSettings;
+import org.caosdb.api.entity.v1.FileTransmissionSettings.Builder;
+import org.caosdb.api.entity.v1.TransmissionStatus;
 import org.caosdb.server.FileSystem;
 import org.caosdb.server.entity.FileProperties;
 
diff --git a/src/main/java/org/caosdb/server/grpc/FileUploadRegistration.java b/src/main/java/org/caosdb/server/grpc/FileUploadRegistration.java
index 7e631fadc923f18d5302138c6fa6d494fff6bf13..bfb25be2ec91cda450be282b89f08ace26a16409 100644
--- a/src/main/java/org/caosdb/server/grpc/FileUploadRegistration.java
+++ b/src/main/java/org/caosdb/server/grpc/FileUploadRegistration.java
@@ -5,7 +5,7 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
-import org.caosdb.api.entity.v1alpha1.FileTransmissionId;
+import org.caosdb.api.entity.v1.FileTransmissionId;
 import org.caosdb.server.entity.FileProperties;
 import org.caosdb.server.utils.Utils;
 
diff --git a/src/main/java/org/caosdb/server/grpc/GRPCServer.java b/src/main/java/org/caosdb/server/grpc/GRPCServer.java
index 51c061fa56671100fbc6ec460476ecc16c5a2ce4..469e4b1048b6139c58d41a46b36c738603e536cf 100644
--- a/src/main/java/org/caosdb/server/grpc/GRPCServer.java
+++ b/src/main/java/org/caosdb/server/grpc/GRPCServer.java
@@ -64,6 +64,7 @@ public class GRPCServer {
   private static final Logger logger = LoggerFactory.getLogger(GRPCServer.class.getName());
 
   private final AuthInterceptor authInterceptor = new AuthInterceptor();
+  private final LoggingInterceptor loggingInterceptor = new LoggingInterceptor();
 
   /**
    * Create an ssl context.
@@ -115,14 +116,18 @@ public class GRPCServer {
     final List<ServerServiceDefinition> services = new LinkedList<>();
 
     final GeneralInfoServiceImpl generalInfoService = new GeneralInfoServiceImpl();
-    services.add(ServerInterceptors.intercept(generalInfoService, authInterceptor));
+    services.add(
+        ServerInterceptors.intercept(generalInfoService, loggingInterceptor, authInterceptor));
 
     final FileTransmissionServiceImpl fileTransmissionService = new FileTransmissionServiceImpl();
-    services.add(ServerInterceptors.intercept(fileTransmissionService, authInterceptor));
+    services.add(
+        ServerInterceptors.intercept(fileTransmissionService, loggingInterceptor, authInterceptor));
 
     final EntityTransactionServiceImpl entityTransactionService =
         new EntityTransactionServiceImpl(fileTransmissionService);
-    services.add(ServerInterceptors.intercept(entityTransactionService, authInterceptor));
+    services.add(
+        ServerInterceptors.intercept(
+            entityTransactionService, loggingInterceptor, authInterceptor));
 
     return services;
   }
diff --git a/src/main/java/org/caosdb/server/grpc/GeneralInfoServiceImpl.java b/src/main/java/org/caosdb/server/grpc/GeneralInfoServiceImpl.java
index dfd10ac86090de97a6151e330ade846c1de6273e..7966251c101cc42d948b343648013f19ba8cdb60 100644
--- a/src/main/java/org/caosdb/server/grpc/GeneralInfoServiceImpl.java
+++ b/src/main/java/org/caosdb/server/grpc/GeneralInfoServiceImpl.java
@@ -20,10 +20,10 @@
 package org.caosdb.server.grpc;
 
 import io.grpc.stub.StreamObserver;
-import org.caosdb.api.info.v1alpha1.GeneralInfoServiceGrpc.GeneralInfoServiceImplBase;
-import org.caosdb.api.info.v1alpha1.GetVersionInfoRequest;
-import org.caosdb.api.info.v1alpha1.GetVersionInfoResponse;
-import org.caosdb.api.info.v1alpha1.VersionInfo;
+import org.caosdb.api.info.v1.GeneralInfoServiceGrpc.GeneralInfoServiceImplBase;
+import org.caosdb.api.info.v1.GetVersionInfoRequest;
+import org.caosdb.api.info.v1.GetVersionInfoResponse;
+import org.caosdb.api.info.v1.VersionInfo;
 import org.caosdb.server.CaosDBServer;
 import org.caosdb.server.ServerProperties;
 
diff --git a/src/main/java/org/caosdb/server/grpc/GrpcToCaosDBConverters.java b/src/main/java/org/caosdb/server/grpc/GrpcToCaosDBConverters.java
new file mode 100644
index 0000000000000000000000000000000000000000..302800711262ace87513eee9d5712420a4e496f5
--- /dev/null
+++ b/src/main/java/org/caosdb/server/grpc/GrpcToCaosDBConverters.java
@@ -0,0 +1,288 @@
+package org.caosdb.server.grpc;
+
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+import org.caosdb.api.entity.v1.AtomicDataType;
+import org.caosdb.api.entity.v1.CollectionValues;
+import org.caosdb.api.entity.v1.DataType;
+import org.caosdb.api.entity.v1.Entity;
+import org.caosdb.api.entity.v1.EntityRole;
+import org.caosdb.api.entity.v1.FileDescriptor;
+import org.caosdb.api.entity.v1.Importance;
+import org.caosdb.api.entity.v1.ListDataType;
+import org.caosdb.api.entity.v1.Parent;
+import org.caosdb.api.entity.v1.ReferenceDataType;
+import org.caosdb.api.entity.v1.SpecialValue;
+import org.caosdb.server.datatype.AbstractDatatype;
+import org.caosdb.server.datatype.BooleanValue;
+import org.caosdb.server.datatype.CollectionValue;
+import org.caosdb.server.datatype.FileDatatype;
+import org.caosdb.server.datatype.GenericValue;
+import org.caosdb.server.datatype.ListDatatype;
+import org.caosdb.server.datatype.ReferenceDatatype;
+import org.caosdb.server.datatype.ReferenceDatatype2;
+import org.caosdb.server.datatype.Value;
+import org.caosdb.server.entity.EntityInterface;
+import org.caosdb.server.entity.FileProperties;
+import org.caosdb.server.entity.MagicTypes;
+import org.caosdb.server.entity.Role;
+import org.caosdb.server.entity.StatementStatus;
+import org.caosdb.server.entity.wrapper.Property;
+import org.caosdb.server.utils.EntityStatus;
+import org.caosdb.server.utils.ServerMessages;
+
+public class GrpcToCaosDBConverters {
+
+  public Integer getId(final String id) {
+    return Integer.parseInt(id);
+  }
+
+  public Role convert(final EntityRole role) {
+    switch (role) {
+      case ENTITY_ROLE_FILE:
+        return Role.File;
+      case ENTITY_ROLE_PROPERTY:
+        return Role.Property;
+      case ENTITY_ROLE_RECORD:
+        return Role.Record;
+      case ENTITY_ROLE_RECORD_TYPE:
+        return Role.RecordType;
+      default:
+        return null;
+    }
+  }
+
+  public Property getUnit(final String unitStr) {
+    final EntityInterface magicUnit = MagicTypes.UNIT.getEntity();
+    final Property unit = new Property();
+    unit.setDescription(magicUnit.getDescription());
+    unit.setName(magicUnit.getName());
+    unit.setId(magicUnit.getId());
+    unit.setDatatype(magicUnit.getDatatype());
+    unit.setStatementStatus(StatementStatus.FIX);
+    unit.setValue(new GenericValue(unitStr));
+    unit.setEntityStatus(EntityStatus.QUALIFIED);
+    return unit;
+  }
+
+  public Value getValue(final String valString) {
+    return new GenericValue(valString);
+  }
+
+  public EntityInterface convert(final Entity from, final EntityInterface entity) {
+    entity.setName(from.getName().isEmpty() ? null : from.getName());
+    entity.setDescription(from.getDescription().isBlank() ? null : from.getDescription());
+    if (!from.getUnit().isBlank()) {
+      entity.addProperty(getUnit(from.getUnit()));
+    }
+    if (from.hasDataType()) {
+      entity.setDatatype(convert(from.getDataType()));
+    }
+    if (from.hasValue()) {
+      entity.setValue(convert(from.getValue()));
+    }
+
+    if (from.getPropertiesCount() > 0) {
+      final StatementStatus defaultImportance =
+          entity.getRole() == Role.RecordType ? StatementStatus.RECOMMENDED : StatementStatus.FIX;
+      entity.getProperties().addAll(convertProperties(from.getPropertiesList(), defaultImportance));
+    }
+    if (from.getParentsCount() > 0) {
+      entity.getParents().addAll(convertParents(from.getParentsList()));
+    }
+    if (from.hasFileDescriptor()) {
+      entity.setFileProperties(convert(from.getFileDescriptor()));
+    }
+    return entity;
+  }
+
+  private Value convert(final org.caosdb.api.entity.v1.Value value) {
+    switch (value.getValueCase()) {
+      case LIST_VALUES:
+        return convertListValue(value.getListValues());
+      case SCALAR_VALUE:
+        return convertScalarValue(value.getScalarValue());
+      default:
+        break;
+    }
+    return null;
+  }
+
+  private CollectionValue convertListValue(final CollectionValues collectionValues) {
+    final CollectionValue result = new CollectionValue();
+    collectionValues
+        .getValuesList()
+        .forEach(
+            (v) -> {
+              result.add(convertScalarValue(v));
+            });
+    return result;
+  }
+
+  private Value convertScalarValue(final org.caosdb.api.entity.v1.ScalarValue value) {
+    switch (value.getScalarValueCase()) {
+      case BOOLEAN_VALUE:
+        return BooleanValue.valueOf(value.getBooleanValue());
+      case DOUBLE_VALUE:
+        return new GenericValue(value.getDoubleValue());
+      case INTEGER_VALUE:
+        return new GenericValue(Long.toString(value.getIntegerValue()));
+      case SPECIAL_VALUE:
+        return convertSpecial(value.getSpecialValue());
+      case STRING_VALUE:
+        return new GenericValue(value.getStringValue());
+      default:
+        break;
+    }
+    return null;
+  }
+
+  private Value convertSpecial(final SpecialValue specialValue) {
+    if (specialValue == SpecialValue.SPECIAL_VALUE_EMPTY_STRING) {
+      return new GenericValue("");
+    }
+    return null;
+  }
+
+  private AbstractDatatype convert(final DataType dataType) {
+    switch (dataType.getDataTypeCase()) {
+      case ATOMIC_DATA_TYPE:
+        return convertAtomicType(dataType.getAtomicDataType());
+      case LIST_DATA_TYPE:
+        return convertListDataType(dataType.getListDataType());
+      case REFERENCE_DATA_TYPE:
+        return convertReferenceDataType(dataType.getReferenceDataType());
+      default:
+        break;
+    }
+    return null;
+  }
+
+  private ReferenceDatatype convertReferenceDataType(final ReferenceDataType referenceDataType) {
+    final String name = referenceDataType.getName();
+    if (name.equalsIgnoreCase("REFERENCE")) {
+      return new ReferenceDatatype();
+    } else if (name.equalsIgnoreCase("FILE")) {
+      return new FileDatatype();
+    }
+    return new ReferenceDatatype2(name);
+  }
+
+  private AbstractDatatype convertAtomicType(final AtomicDataType dataType) {
+    switch (dataType) {
+      case ATOMIC_DATA_TYPE_BOOLEAN:
+        return AbstractDatatype.datatypeFactory("BOOLEAN");
+      case ATOMIC_DATA_TYPE_DATETIME:
+        return AbstractDatatype.datatypeFactory("DATETIME");
+      case ATOMIC_DATA_TYPE_DOUBLE:
+        return AbstractDatatype.datatypeFactory("DOUBLE");
+      case ATOMIC_DATA_TYPE_INTEGER:
+        return AbstractDatatype.datatypeFactory("INTEGER");
+      case ATOMIC_DATA_TYPE_TEXT:
+        return AbstractDatatype.datatypeFactory("TEXT");
+      default:
+        return null;
+    }
+  }
+
+  private AbstractDatatype convertListDataType(final ListDataType dataType) {
+    switch (dataType.getListDataTypeCase()) {
+      case ATOMIC_DATA_TYPE:
+        return new ListDatatype(convertAtomicType(dataType.getAtomicDataType()));
+      case REFERENCE_DATA_TYPE:
+        return new ListDatatype(convertReferenceDataType(dataType.getReferenceDataType()));
+      default:
+        return null;
+    }
+  }
+
+  private FileProperties convert(final FileDescriptor fileDescriptor) {
+    return new FileProperties(
+        null,
+        fileDescriptor.getPath(),
+        fileDescriptor.getSize() == 0 ? null : fileDescriptor.getSize());
+  }
+
+  private Collection<Property> convertProperties(
+      final List<org.caosdb.api.entity.v1.Property> propertiesList,
+      final StatementStatus defaultImportance) {
+    final Collection<Property> result = new LinkedList<>();
+    propertiesList.forEach(
+        e -> {
+          result.add(convert(e, defaultImportance));
+        });
+    return result;
+  }
+
+  private Property convert(
+      final org.caosdb.api.entity.v1.Property e, final StatementStatus defaultImportance) {
+    final Property result = new Property();
+
+    try {
+      result.setId(e.getId().isBlank() ? null : getId(e.getId()));
+    } catch (final NumberFormatException exc) {
+      result.addError(ServerMessages.ENTITY_DOES_NOT_EXIST);
+    }
+    result.setName(e.getName().isBlank() ? null : e.getName());
+    result.setDescription(e.getDescription().isBlank() ? null : e.getDescription());
+    if (!e.getUnit().isBlank()) {
+      result.addProperty(getUnit(e.getUnit()));
+    }
+    if (e.hasDataType()) {
+      result.setDatatype(convert(e.getDataType()));
+    }
+    if (e.hasValue()) {
+      result.setValue(convert(e.getValue()));
+    }
+    if (e.getImportance() != Importance.IMPORTANCE_UNSPECIFIED) {
+      result.setStatementStatus(convert(e.getImportance()));
+    } else {
+      result.setStatementStatus(defaultImportance);
+    }
+    // TODO remove this hard-coded setting when the API supports flags
+    if (result.getFlag("inheritance") == null) {
+      result.setFlag("inheritance", "fix");
+    }
+
+    return result;
+  }
+
+  private StatementStatus convert(final Importance importance) {
+    switch (importance) {
+      case IMPORTANCE_FIX:
+        return StatementStatus.FIX;
+      case IMPORTANCE_OBLIGATORY:
+        return StatementStatus.OBLIGATORY;
+      case IMPORTANCE_RECOMMENDED:
+        return StatementStatus.RECOMMENDED;
+      case IMPORTANCE_SUGGESTED:
+        return StatementStatus.SUGGESTED;
+      default:
+        return null;
+    }
+  }
+
+  private Collection<org.caosdb.server.entity.wrapper.Parent> convertParents(
+      final List<Parent> parentsList) {
+    final Collection<org.caosdb.server.entity.wrapper.Parent> result = new LinkedList<>();
+    parentsList.forEach(
+        e -> {
+          result.add(convert(e));
+        });
+    return result;
+  }
+
+  private org.caosdb.server.entity.wrapper.Parent convert(final Parent e) {
+    final org.caosdb.server.entity.wrapper.Parent result =
+        new org.caosdb.server.entity.wrapper.Parent();
+
+    try {
+      result.setId(e.getId().isBlank() ? null : getId(e.getId()));
+    } catch (final NumberFormatException exc) {
+      result.addError(ServerMessages.ENTITY_DOES_NOT_EXIST);
+    }
+    result.setName(e.getName().isBlank() ? null : e.getName());
+    return result;
+  }
+}
diff --git a/src/main/java/org/caosdb/server/grpc/LoggingInterceptor.java b/src/main/java/org/caosdb/server/grpc/LoggingInterceptor.java
new file mode 100644
index 0000000000000000000000000000000000000000..9edd35090659e908ecf7f3fb502d34c36ac7e829
--- /dev/null
+++ b/src/main/java/org/caosdb/server/grpc/LoggingInterceptor.java
@@ -0,0 +1,24 @@
+package org.caosdb.server.grpc;
+
+import io.grpc.Context;
+import io.grpc.Contexts;
+import io.grpc.Metadata;
+import io.grpc.ServerCall;
+import io.grpc.ServerCall.Listener;
+import io.grpc.ServerCallHandler;
+import io.grpc.ServerInterceptor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class LoggingInterceptor implements ServerInterceptor {
+
+  private static final Logger logger = LoggerFactory.getLogger(LoggingInterceptor.class.getName());
+
+  @Override
+  public <ReqT, RespT> Listener<ReqT> interceptCall(
+      ServerCall<ReqT, RespT> call, Metadata headers, ServerCallHandler<ReqT, RespT> next) {
+
+    logger.info(call.getMethodDescriptor().getFullMethodName() + " - " + call.getAttributes());
+    return Contexts.interceptCall(Context.current(), call, headers, next);
+  }
+}
diff --git a/src/main/java/org/caosdb/server/grpc/UploadBuffer.java b/src/main/java/org/caosdb/server/grpc/UploadBuffer.java
index d196da7de14af11fd892f752d35a5043ac7e677e..a955622008d994bd9b0b87aac624790dae6660b2 100644
--- a/src/main/java/org/caosdb/server/grpc/UploadBuffer.java
+++ b/src/main/java/org/caosdb/server/grpc/UploadBuffer.java
@@ -4,7 +4,7 @@ import com.google.protobuf.ByteString;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
-import org.caosdb.api.entity.v1alpha1.TransmissionStatus;
+import org.caosdb.api.entity.v1.TransmissionStatus;
 import org.caosdb.server.entity.FileProperties;
 
 public class UploadBuffer {
diff --git a/src/main/java/org/caosdb/server/jobs/core/CheckDatatypePresent.java b/src/main/java/org/caosdb/server/jobs/core/CheckDatatypePresent.java
index 6a3e27d2c90e0b754cae381afa5fa59186f99871..9ea7d4b3867b781ead42a50b23b5a7befff048f9 100644
--- a/src/main/java/org/caosdb/server/jobs/core/CheckDatatypePresent.java
+++ b/src/main/java/org/caosdb/server/jobs/core/CheckDatatypePresent.java
@@ -95,7 +95,7 @@ public final class CheckDatatypePresent extends EntityJob {
       } else {
 
         // finally, no data type
-        throw ServerMessages.NO_DATATYPE;
+        throw ServerMessages.PROPERTY_HAS_NO_DATATYPE;
       }
 
     } catch (final Message m) {
@@ -214,7 +214,7 @@ public final class CheckDatatypePresent extends EntityJob {
       } catch (final EntityDoesNotExistException exc) {
         entity.addError(ServerMessages.ENTITY_DOES_NOT_EXIST);
       } catch (final EntityWasNotUniqueException exc) {
-        entity.addError(ServerMessages.CANNOT_IDENTIFY_ENTITY_UNIQUELY);
+        entity.addError(ServerMessages.ENTITY_NAME_DUPLICATES);
       }
     }
   }
diff --git a/src/main/java/org/caosdb/server/jobs/core/CheckFileStorageConsistency.java b/src/main/java/org/caosdb/server/jobs/core/CheckFileStorageConsistency.java
index 8dc6fc0c60bc234d65f576377a89244d0a7a673e..e425649bb1bc43a9745120ed078c653f55af2e38 100644
--- a/src/main/java/org/caosdb/server/jobs/core/CheckFileStorageConsistency.java
+++ b/src/main/java/org/caosdb/server/jobs/core/CheckFileStorageConsistency.java
@@ -127,8 +127,6 @@ public class CheckFileStorageConsistency extends FlagJob {
       getContainer()
           .addMessage(
               new Message(
-                  "Info",
-                  0,
                   "Test took too long. The results will be written to './ConsistencyTest.xml'"));
     } else {
       // add info/warning/error
diff --git a/src/main/java/org/caosdb/server/jobs/core/CheckParOblPropPresent.java b/src/main/java/org/caosdb/server/jobs/core/CheckParOblPropPresent.java
index 9588a3056e15f7fb3847db37468bb6a628741203..e6ba9da430e6218e5c40fba968c309ed94152bf6 100644
--- a/src/main/java/org/caosdb/server/jobs/core/CheckParOblPropPresent.java
+++ b/src/main/java/org/caosdb/server/jobs/core/CheckParOblPropPresent.java
@@ -39,9 +39,6 @@ import org.caosdb.server.utils.ServerMessages;
 public class CheckParOblPropPresent extends EntityJob {
 
   public static final String OBL_IMPORTANCE_FLAG_KEY = "force-missing-obligatory";
-  public static final Message ENTITY_NOT_UNIQUE =
-      new Message(
-          MessageType.Error, 0, "Could not check importance. Parent was not uniquely resolvable.");
   public static final Message ILLEGAL_FLAG_VALUE =
       new Message(MessageType.Warning, "Illegal value for flag 'force-missing-obligatory'.");
 
diff --git a/src/main/java/org/caosdb/server/jobs/core/CheckParValid.java b/src/main/java/org/caosdb/server/jobs/core/CheckParValid.java
index fa1c6fd36771e0ddcd08b330724ef1d6aa725956..4e6b097e66bf2e844cad34ae22f45eedf1b6cd67 100644
--- a/src/main/java/org/caosdb/server/jobs/core/CheckParValid.java
+++ b/src/main/java/org/caosdb/server/jobs/core/CheckParValid.java
@@ -124,7 +124,7 @@ public class CheckParValid extends EntityJob {
         } catch (final EntityDoesNotExistException exc) {
           addError(parent, ServerMessages.ENTITY_DOES_NOT_EXIST);
         } catch (final EntityWasNotUniqueException exc) {
-          addError(parent, ServerMessages.NAME_DUPLICATES);
+          addError(parent, ServerMessages.ENTITY_NAME_DUPLICATES);
         }
       }
     }
diff --git a/src/main/java/org/caosdb/server/jobs/core/CheckRefidIsaParRefid.java b/src/main/java/org/caosdb/server/jobs/core/CheckRefidIsaParRefid.java
index b9f804f519948b605a9fa8820c91495618463fba..e739ffde01a38fb1539c97166014350e9f9c61d7 100644
--- a/src/main/java/org/caosdb/server/jobs/core/CheckRefidIsaParRefid.java
+++ b/src/main/java/org/caosdb/server/jobs/core/CheckRefidIsaParRefid.java
@@ -31,7 +31,6 @@ import org.caosdb.server.datatype.ReferenceValue;
 import org.caosdb.server.entity.Entity;
 import org.caosdb.server.entity.EntityInterface;
 import org.caosdb.server.entity.Message;
-import org.caosdb.server.entity.Message.MessageType;
 import org.caosdb.server.entity.Role;
 import org.caosdb.server.entity.wrapper.Parent;
 import org.caosdb.server.jobs.EntityJob;
@@ -143,15 +142,13 @@ public class CheckRefidIsaParRefid extends EntityJob implements Observer {
           getEntity()
               .addInfo(
                   new Message(
-                      MessageType.Info,
-                      0,
                       "Could not resolve all parents of the entity with id "
                           + child.toString()
                           + ". Problematic parent: "
                           + (par.hasName()
                               ? par.getName()
                               : (par.hasCuid() ? par.getCuid() : (par.toString())))));
-          throw ServerMessages.ENTITY_HAS_INVALID_REFERENCE;
+          throw ServerMessages.ENTITY_HAS_UNQUALIFIED_REFERENCE;
         }
         if (isSubType(par.getId(), parent)) {
           return true;
diff --git a/src/main/java/org/caosdb/server/jobs/core/CheckRefidValid.java b/src/main/java/org/caosdb/server/jobs/core/CheckRefidValid.java
index 8563ea716072602684dc1a78870392d573dc3a22..f19424b127feb3273571a7826bf05382299ea58a 100644
--- a/src/main/java/org/caosdb/server/jobs/core/CheckRefidValid.java
+++ b/src/main/java/org/caosdb/server/jobs/core/CheckRefidValid.java
@@ -157,7 +157,7 @@ public class CheckRefidValid extends EntityJob implements Observer {
     if (ref.getEntity().hasEntityStatus()) {
       switch (ref.getEntity().getEntityStatus()) {
         case UNQUALIFIED:
-          getEntity().addError(ServerMessages.ENTITY_HAS_INVALID_REFERENCE);
+          getEntity().addError(ServerMessages.ENTITY_HAS_UNQUALIFIED_REFERENCE);
           getEntity().setEntityStatus(EntityStatus.UNQUALIFIED);
           return false;
         case DELETED:
diff --git a/src/main/java/org/caosdb/server/jobs/core/CheckTargetPathValid.java b/src/main/java/org/caosdb/server/jobs/core/CheckTargetPathValid.java
index 7d06498f5d9e4fbc382e7dde025983ceac6a7fdc..28b914e61d33847e7beb46881c0dac4d9b17f9f0 100644
--- a/src/main/java/org/caosdb/server/jobs/core/CheckTargetPathValid.java
+++ b/src/main/java/org/caosdb/server/jobs/core/CheckTargetPathValid.java
@@ -37,11 +37,6 @@ import org.caosdb.server.utils.ServerMessages;
  */
 public class CheckTargetPathValid extends EntityJob {
 
-  public static final Message TARGET_PATH_NOT_IN_USER_FOLDER =
-      new Message(
-          0,
-          "According to the server's configuration, your file has to be stored to ýour user folder");
-
   @Override
   public final void run() {
     if (getEntity().hasFileProperties()) {
@@ -50,7 +45,7 @@ public class CheckTargetPathValid extends EntityJob {
       if (!file.hasPath()) {
         // the file doesn't have a path property at all
         getEntity().setEntityStatus(EntityStatus.UNQUALIFIED);
-        getEntity().addError(ServerMessages.NO_TARGET_PATH);
+        getEntity().addError(ServerMessages.FILE_HAS_NO_TARGET_PATH);
         return;
       }
 
diff --git a/src/main/java/org/caosdb/server/jobs/core/CheckUnitPresent.java b/src/main/java/org/caosdb/server/jobs/core/CheckUnitPresent.java
index 5e3e6120fadef8f4b519ec694ebbf7588d7c2488..85eb3259dcc17cfdfd2a03aeb3d3360fb04f3908 100644
--- a/src/main/java/org/caosdb/server/jobs/core/CheckUnitPresent.java
+++ b/src/main/java/org/caosdb/server/jobs/core/CheckUnitPresent.java
@@ -42,11 +42,11 @@ public class CheckUnitPresent extends EntityJob {
     if (!hasUnit(getEntity())) {
       switch (getFailureSeverity()) {
         case ERROR:
-          getEntity().addError(ServerMessages.ENTITY_HAS_NO_UNIT);
+          getEntity().addError(ServerMessages.PROPERTY_HAS_NO_UNIT);
           getEntity().setEntityStatus(EntityStatus.UNQUALIFIED);
           break;
         case WARN:
-          getEntity().addWarning(ServerMessages.ENTITY_HAS_NO_UNIT);
+          getEntity().addWarning(ServerMessages.PROPERTY_HAS_NO_UNIT);
         default:
           break;
       }
diff --git a/src/main/java/org/caosdb/server/jobs/core/ExecuteQuery.java b/src/main/java/org/caosdb/server/jobs/core/ExecuteQuery.java
index f11523df384177e2e92dfe0924faf132ac7827fb..0a19977b199195610d96f887c4c538a75b491511 100644
--- a/src/main/java/org/caosdb/server/jobs/core/ExecuteQuery.java
+++ b/src/main/java/org/caosdb/server/jobs/core/ExecuteQuery.java
@@ -22,8 +22,10 @@
  */
 package org.caosdb.server.jobs.core;
 
+import org.caosdb.api.entity.v1.MessageCode;
 import org.caosdb.server.entity.EntityInterface;
 import org.caosdb.server.entity.Message;
+import org.caosdb.server.entity.Message.MessageType;
 import org.caosdb.server.jobs.FlagJob;
 import org.caosdb.server.jobs.JobAnnotation;
 import org.caosdb.server.jobs.TransactionStage;
@@ -50,7 +52,7 @@ public class ExecuteQuery extends FlagJob {
     } catch (final UnsupportedOperationException e) {
       getContainer().addMessage(ServerMessages.QUERY_EXCEPTION);
       getContainer().setStatus(EntityStatus.UNQUALIFIED);
-      getContainer().addMessage(new Message(e.getMessage()));
+      getContainer().addMessage(new Message(MessageType.Info, (MessageCode) null, e.getMessage()));
     }
     getContainer().addMessage(queryInstance);
     if (queryInstance.getQuery().getType() == Type.COUNT) {
diff --git a/src/main/java/org/caosdb/server/jobs/core/Inheritance.java b/src/main/java/org/caosdb/server/jobs/core/Inheritance.java
index 56ac72fab9f980581cf755c5018dad48ad841f96..78e89a53593e3f112650ed81e292d0c62f071e24 100644
--- a/src/main/java/org/caosdb/server/jobs/core/Inheritance.java
+++ b/src/main/java/org/caosdb/server/jobs/core/Inheritance.java
@@ -26,6 +26,7 @@ package org.caosdb.server.jobs.core;
 
 import java.util.ArrayList;
 import java.util.List;
+import org.caosdb.api.entity.v1.MessageCode;
 import org.caosdb.server.database.backend.transaction.RetrieveFullEntityTransaction;
 import org.caosdb.server.entity.Entity;
 import org.caosdb.server.entity.EntityInterface;
@@ -61,7 +62,7 @@ public class Inheritance extends EntityJob {
   public static final Message ILLEGAL_INHERITANCE_MODE =
       new Message(
           MessageType.Warning,
-          0,
+          MessageCode.MESSAGE_CODE_UNKNOWN,
           "Unknown value for flag \"inheritance\". None of the parent's properties have been transfered to the child.");
 
   @Override
diff --git a/src/main/java/org/caosdb/server/jobs/core/InsertFilesInDir.java b/src/main/java/org/caosdb/server/jobs/core/InsertFilesInDir.java
index 8133e4659d55caf29faa56eeb80ced194cd26cfc..5b5418286a81d442822aed0e7252fa4557fb21ff 100644
--- a/src/main/java/org/caosdb/server/jobs/core/InsertFilesInDir.java
+++ b/src/main/java/org/caosdb/server/jobs/core/InsertFilesInDir.java
@@ -30,6 +30,7 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
+import org.caosdb.api.entity.v1.MessageCode;
 import org.caosdb.server.CaosDBException;
 import org.caosdb.server.CaosDBServer;
 import org.caosdb.server.FileSystem;
@@ -132,8 +133,6 @@ public class InsertFilesInDir extends FlagJob {
           getContainer()
               .addMessage(
                   new Message(
-                      MessageType.Info,
-                      0,
                       "Files count in "
                           + dir.getName()
                           + "/: "
@@ -147,7 +146,12 @@ public class InsertFilesInDir extends FlagJob {
         throw new TransactionException(e);
       }
     } else {
-      getContainer().addMessage(new Message(MessageType.Error, 0, "No such directory: " + dirStr));
+      getContainer()
+          .addMessage(
+              new Message(
+                  MessageType.Error,
+                  MessageCode.MESSAGE_CODE_UNKNOWN,
+                  "No such directory: " + dirStr));
       return;
     }
   }
@@ -289,7 +293,7 @@ public class InsertFilesInDir extends FlagJob {
             .addMessage(
                 new Message(
                     MessageType.Warning,
-                    1,
+                    MessageCode.MESSAGE_CODE_UNKNOWN,
                     "Not explicitly included file: " + sub.getCanonicalPath()));
         return false;
       }
@@ -297,7 +301,9 @@ public class InsertFilesInDir extends FlagJob {
         getContainer()
             .addMessage(
                 new Message(
-                    MessageType.Warning, 2, "Explicitly excluded file: " + sub.getCanonicalPath()));
+                    MessageType.Warning,
+                    MessageCode.MESSAGE_CODE_ENTITY_DOES_NOT_EXIST,
+                    "Explicitly excluded file: " + sub.getCanonicalPath()));
         return false;
       }
     }
@@ -305,14 +311,18 @@ public class InsertFilesInDir extends FlagJob {
       getContainer()
           .addMessage(
               new Message(
-                  MessageType.Warning, 3, "Hidden directory or file: " + sub.getCanonicalPath()));
+                  MessageType.Warning,
+                  MessageCode.MESSAGE_CODE_UNKNOWN,
+                  "Hidden directory or file: " + sub.getCanonicalPath()));
       return false;
     }
     if (sub.isDirectory() && !sub.canExecute()) {
       getContainer()
           .addMessage(
               new Message(
-                  MessageType.Warning, 4, "Unaccessible directory: " + sub.getCanonicalPath()));
+                  MessageType.Warning,
+                  MessageCode.MESSAGE_CODE_UNKNOWN,
+                  "Unaccessible directory: " + sub.getCanonicalPath()));
       return false;
     }
     if (!sub.canRead()) {
@@ -320,7 +330,7 @@ public class InsertFilesInDir extends FlagJob {
           .addMessage(
               new Message(
                   MessageType.Warning,
-                  5,
+                  MessageCode.MESSAGE_CODE_UNKNOWN,
                   "Unreadable directory or file: " + sub.getCanonicalPath()));
       return false;
     }
@@ -329,7 +339,7 @@ public class InsertFilesInDir extends FlagJob {
           .addMessage(
               new Message(
                   MessageType.Warning,
-                  6,
+                  MessageCode.MESSAGE_CODE_ENTITY_HAS_UNQUALIFIED_PARENTS,
                   "Directory or file is symbolic link: " + sub.getAbsolutePath()));
       if (!this.forceSymLinks) {
         return false;
@@ -355,11 +365,15 @@ public class InsertFilesInDir extends FlagJob {
     // overlaps the directory to be inserted.
 
     if (!dir.isDirectory()) {
-      throw new Message(MessageType.Error, 0, "Dir is not a directory.");
+      throw new Message(
+          MessageType.Error, MessageCode.MESSAGE_CODE_UNKNOWN, "Dir is not a directory.");
     }
 
     if (!dir.canRead() || !dir.canExecute()) {
-      throw new Message(MessageType.Error, 0, "Cannot read or enter the desired directory.");
+      throw new Message(
+          MessageType.Error,
+          MessageCode.MESSAGE_CODE_UNKNOWN,
+          "Cannot read or enter the desired directory.");
     }
 
     final File base = new File(FileSystem.getBasepath());
@@ -375,7 +389,10 @@ public class InsertFilesInDir extends FlagJob {
         || isSubDir(tmp, dir)
         || isSubDir(dir, root)
         || isSubDir(root, dir)) {
-      throw new Message(MessageType.Error, 0, "Dir is not allowed: " + dir.toString());
+      throw new Message(
+          MessageType.Error,
+          MessageCode.MESSAGE_CODE_UNKNOWN,
+          "Dir is not allowed: " + dir.toString());
     }
 
     for (final File f : getAllowedFolders()) {
@@ -386,7 +403,7 @@ public class InsertFilesInDir extends FlagJob {
     }
     throw new Message(
         MessageType.Error,
-        1,
+        MessageCode.MESSAGE_CODE_UNKNOWN,
         "Dir is not allowed: "
             + dir.toString()
             + " Allowed directories: "
diff --git a/src/main/java/org/caosdb/server/jobs/core/TestMail.java b/src/main/java/org/caosdb/server/jobs/core/TestMail.java
index fb3e87097fae44f3f1f609dd7e347c27c6d971c2..210a9f59b879529f5f96954250556e88f60454be 100644
--- a/src/main/java/org/caosdb/server/jobs/core/TestMail.java
+++ b/src/main/java/org/caosdb/server/jobs/core/TestMail.java
@@ -25,7 +25,6 @@ package org.caosdb.server.jobs.core;
 import org.caosdb.server.CaosDBServer;
 import org.caosdb.server.ServerProperties;
 import org.caosdb.server.entity.Message;
-import org.caosdb.server.entity.Message.MessageType;
 import org.caosdb.server.jobs.FlagJob;
 import org.caosdb.server.jobs.JobAnnotation;
 import org.caosdb.server.utils.ServerMessages;
@@ -49,8 +48,7 @@ public class TestMail extends FlagJob {
       if (Utils.isRFC822Compliant(value)) {
         final Mail m = new Mail(NAME, EMAIL, null, value, "Test mail", "This is a test mail.");
         m.send();
-        getContainer()
-            .addMessage(new Message(MessageType.Info, 0, "A mail has been send to " + value));
+        getContainer().addMessage(new Message("A mail has been send to " + value));
       } else {
         getContainer().addMessage(ServerMessages.EMAIL_NOT_WELL_FORMED);
       }
diff --git a/src/main/java/org/caosdb/server/jobs/core/UniqueName.java b/src/main/java/org/caosdb/server/jobs/core/UniqueName.java
index 2836ccf742ebbd1bbda5a8ed3ae95ac0d69c2fbb..0ef9792556e2b8b6e3981f66cb697ced5659c7a1 100644
--- a/src/main/java/org/caosdb/server/jobs/core/UniqueName.java
+++ b/src/main/java/org/caosdb/server/jobs/core/UniqueName.java
@@ -46,7 +46,7 @@ public class UniqueName extends FlagJob {
       } catch (final EntityDoesNotExistException e) {
         // ok
       } catch (final EntityWasNotUniqueException e) {
-        entity.addError(ServerMessages.NAME_IS_NOT_UNIQUE);
+        entity.addError(ServerMessages.ENTITY_NAME_IS_NOT_UNIQUE);
         entity.setEntityStatus(EntityStatus.UNQUALIFIED);
         return;
       }
@@ -55,7 +55,7 @@ public class UniqueName extends FlagJob {
       for (final EntityInterface e : getContainer()) {
         if (entity != e && e.hasName() && e.getName().equals(entity.getName())) {
           entity.setEntityStatus(EntityStatus.UNQUALIFIED);
-          entity.addError(ServerMessages.NAME_IS_NOT_UNIQUE);
+          entity.addError(ServerMessages.ENTITY_NAME_IS_NOT_UNIQUE);
           return;
         }
       }
diff --git a/src/main/java/org/caosdb/server/query/Query.java b/src/main/java/org/caosdb/server/query/Query.java
index fa5754c65e0e89baf90774fa7def683ece66236b..95f853d607edffa29b69e4f84657560ba3a52a48 100644
--- a/src/main/java/org/caosdb/server/query/Query.java
+++ b/src/main/java/org/caosdb/server/query/Query.java
@@ -46,6 +46,7 @@ import org.antlr.v4.runtime.CharStreams;
 import org.antlr.v4.runtime.CommonTokenStream;
 import org.apache.commons.jcs.access.behavior.ICacheAccess;
 import org.apache.shiro.subject.Subject;
+import org.caosdb.api.entity.v1.MessageCode;
 import org.caosdb.server.CaosDBServer;
 import org.caosdb.server.ServerProperties;
 import org.caosdb.server.caching.Cache;
@@ -754,7 +755,7 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac
   }
 
   private void addWarning(final String w) {
-    this.messages.add(new Message(MessageType.Warning, 0, w));
+    this.messages.add(new Message(MessageType.Warning, MessageCode.MESSAGE_CODE_UNKNOWN, w));
   }
 
   private void cleanUp() {
diff --git a/src/main/java/org/caosdb/server/resource/ScriptingResource.java b/src/main/java/org/caosdb/server/resource/ScriptingResource.java
index 35885bb4376b26fc04977389f4dbf1cd7c40decd..4629457f7bad9eeedfcaf680e6dc3fb5556e6726 100644
--- a/src/main/java/org/caosdb/server/resource/ScriptingResource.java
+++ b/src/main/java/org/caosdb/server/resource/ScriptingResource.java
@@ -96,7 +96,17 @@ public class ScriptingResource extends AbstractCaosDBServerResource {
         return null;
       }
     } catch (Message m) {
-      return error(m, Status.valueOf(m.getCode()));
+      if (m == ServerMessages.SERVER_SIDE_SCRIPT_DOES_NOT_EXIST) {
+        return error(m, Status.CLIENT_ERROR_NOT_FOUND);
+      } else if (m == ServerMessages.SERVER_SIDE_SCRIPT_MISSING_CALL) {
+        return error(m, Status.CLIENT_ERROR_BAD_REQUEST);
+      } else if (m == ServerMessages.SERVER_SIDE_SCRIPT_NOT_EXECUTABLE) {
+        return error(m, Status.CLIENT_ERROR_BAD_REQUEST);
+      } else if (m == ServerMessages.SERVER_SIDE_SCRIPT_TIMEOUT) {
+        return error(m, Status.CLIENT_ERROR_BAD_REQUEST);
+      }
+
+      return error(m, Status.SERVER_ERROR_INTERNAL);
     } finally {
       deleteTmpFiles();
     }
diff --git a/src/main/java/org/caosdb/server/transaction/DeleteUserTransaction.java b/src/main/java/org/caosdb/server/transaction/DeleteUserTransaction.java
index 0f2f5b7fb676e436b131ca69678214c2e34b974c..dc935adc9ea0236ce3c8d54b498ed5f6b15a8c42 100644
--- a/src/main/java/org/caosdb/server/transaction/DeleteUserTransaction.java
+++ b/src/main/java/org/caosdb/server/transaction/DeleteUserTransaction.java
@@ -30,7 +30,6 @@ import org.caosdb.server.database.backend.transaction.DeletePassword;
 import org.caosdb.server.database.backend.transaction.DeleteUser;
 import org.caosdb.server.database.backend.transaction.RetrievePasswordValidator;
 import org.caosdb.server.entity.Message;
-import org.caosdb.server.entity.Message.MessageType;
 import org.caosdb.server.utils.ServerMessages;
 import org.jdom2.Element;
 
@@ -64,7 +63,7 @@ public class DeleteUserTransaction extends AccessControlTransaction {
     final Element ret = new Element("User");
     ret.setAttribute("realm", this.realm);
     ret.setAttribute("name", this.user);
-    ret.addContent(new Message(MessageType.Info, 0, "This user has been deleted.").toElement());
+    ret.addContent(new Message("This user has been deleted.").toElement());
     return ret;
   }
 }
diff --git a/src/main/java/org/caosdb/server/transaction/FileStorageConsistencyCheck.java b/src/main/java/org/caosdb/server/transaction/FileStorageConsistencyCheck.java
index ed93812d22eaad6bf448fa1dede2d92cea1d50a6..e066feb3028eb6dcb9bf645070cadefa9cc45047 100644
--- a/src/main/java/org/caosdb/server/transaction/FileStorageConsistencyCheck.java
+++ b/src/main/java/org/caosdb/server/transaction/FileStorageConsistencyCheck.java
@@ -28,6 +28,7 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map.Entry;
 import java.util.TimeZone;
+import org.caosdb.api.entity.v1.MessageCode;
 import org.caosdb.datetime.UTCDateTime;
 import org.caosdb.server.database.DatabaseAccessManager;
 import org.caosdb.server.database.access.Access;
@@ -176,7 +177,13 @@ public class FileStorageConsistencyCheck extends Thread
         sb.append('\n').append(t.toString());
       }
 
-      e.addContent(new Message("Error", 0, "An exception was thrown.", sb.toString()).toElement());
+      e.addContent(
+          new Message(
+                  "Error",
+                  MessageCode.MESSAGE_CODE_UNKNOWN,
+                  "An exception was thrown.",
+                  sb.toString())
+              .toElement());
     }
 
     final List<Message> results2Messages = results2Messages(getResults(), this.location);
@@ -196,24 +203,36 @@ public class FileStorageConsistencyCheck extends Thread
     final ArrayList<Message> ret = new ArrayList<Message>();
     if (results.isEmpty()) {
       if (location.length() > 0) {
-        ret.add(new Message("Info", 0, "File system below " + location + " is consistent."));
+        ret.add(new Message("File system below " + location + " is consistent."));
       } else {
-        ret.add(new Message("Info", 0, "File system is consistent."));
+        ret.add(new Message("File system is consistent."));
       }
     }
     for (final Entry<String, Integer> r : results.entrySet()) {
       switch (r.getValue()) {
         case FileConsistencyCheck.FILE_DOES_NOT_EXIST:
-          ret.add(new Message("Error", 0, r.getKey() + ": File does not exist."));
+          ret.add(
+              new Message(
+                  "Error",
+                  MessageCode.MESSAGE_CODE_UNKNOWN,
+                  r.getKey() + ": File does not exist."));
           break;
         case FileConsistencyCheck.FILE_MODIFIED:
-          ret.add(new Message("Error", 0, r.getKey() + ": File was modified."));
+          ret.add(
+              new Message(
+                  "Error", MessageCode.MESSAGE_CODE_UNKNOWN, r.getKey() + ": File was modified."));
           break;
         case FileConsistencyCheck.UNKNOWN_FILE:
-          ret.add(new Message("Warning", 0, r.getKey() + ": Unknown file."));
+          ret.add(
+              new Message(
+                  "Warning", MessageCode.MESSAGE_CODE_UNKNOWN, r.getKey() + ": Unknown file."));
           break;
         case FileConsistencyCheck.NONE:
-          ret.add(new Message("Warning", 0, r.getKey() + ": Test result not available."));
+          ret.add(
+              new Message(
+                  "Warning",
+                  MessageCode.MESSAGE_CODE_UNKNOWN,
+                  r.getKey() + ": Test result not available."));
           break;
         default:
           break;
diff --git a/src/main/java/org/caosdb/server/transaction/Transaction.java b/src/main/java/org/caosdb/server/transaction/Transaction.java
index 028afdd695652cbe912e1c48dd0ac2491ec59c3a..b4d63fbb293e0119cefe90db34b9cfb28f4e0ce1 100644
--- a/src/main/java/org/caosdb/server/transaction/Transaction.java
+++ b/src/main/java/org/caosdb/server/transaction/Transaction.java
@@ -33,7 +33,6 @@ import org.caosdb.server.database.exceptions.TransactionException;
 import org.caosdb.server.database.misc.TransactionBenchmark;
 import org.caosdb.server.entity.EntityInterface;
 import org.caosdb.server.entity.Message;
-import org.caosdb.server.entity.Message.MessageType;
 import org.caosdb.server.entity.container.TransactionContainer;
 import org.caosdb.server.jobs.Job;
 import org.caosdb.server.jobs.Schedule;
@@ -52,9 +51,6 @@ import org.caosdb.server.utils.Observer;
 public abstract class Transaction<C extends TransactionContainer> extends AbstractObservable
     implements TransactionInterface {
 
-  public static final Message ERROR_INTEGRITY_VIOLATION =
-      new Message(MessageType.Error, 0, "This entity caused an unexpected integrity violation.");
-
   @Override
   public TransactionBenchmark getTransactionBenchmark() {
     return getContainer().getTransactionBenchmark();
diff --git a/src/main/java/org/caosdb/server/utils/ServerMessages.java b/src/main/java/org/caosdb/server/utils/ServerMessages.java
index a12b9bc4b7c031f39a4aad99e131439440cde621..2e1364a9f78aa5d3695e7662c640bb92ef32a997 100644
--- a/src/main/java/org/caosdb/server/utils/ServerMessages.java
+++ b/src/main/java/org/caosdb/server/utils/ServerMessages.java
@@ -19,7 +19,7 @@
  */
 package org.caosdb.server.utils;
 
-import org.caosdb.api.entity.v1alpha1.MessageCode;
+import org.caosdb.api.entity.v1.MessageCode;
 import org.caosdb.server.CaosDBServer;
 import org.caosdb.server.ServerProperties;
 import org.caosdb.server.entity.Message;
@@ -28,322 +28,417 @@ import org.caosdb.server.entity.Message.MessageType;
 public class ServerMessages {
 
   public static final Message ENTITY_HAS_BEEN_DELETED_SUCCESSFULLY =
-      new Message(MessageType.Info, 10, "This entity has been deleted successfully.");
+      new Message(
+          MessageType.Info,
+          MessageCode.MESSAGE_CODE_ENTITY_HAS_BEEN_DELETED_SUCCESSFULLY,
+          "This entity has been deleted successfully.");
 
   public static final Message ENTITY_DOES_NOT_EXIST =
-      new Message(MessageType.Error, 101, "Entity does not exist.");
+      new Message(
+          MessageType.Error,
+          MessageCode.MESSAGE_CODE_ENTITY_DOES_NOT_EXIST,
+          "Entity does not exist.");
 
   public static final Message ENTITY_HAS_UNQUALIFIED_PROPERTIES =
-      new Message(MessageType.Error, 114, "Entity has unqualified properties.");
+      new Message(
+          MessageType.Error,
+          MessageCode.MESSAGE_CODE_ENTITY_HAS_UNQUALIFIED_PROPERTIES,
+          "Entity has unqualified properties.");
 
   public static final Message ENTITY_HAS_UNQUALIFIED_PARENTS =
-      new Message(MessageType.Error, 116, "Entity has unqualified parents.");
+      new Message(
+          MessageType.Error,
+          MessageCode.MESSAGE_CODE_ENTITY_HAS_UNQUALIFIED_PARENTS,
+          "Entity has unqualified parents.");
 
-  public static final Message PARSING_FAILED = new Message(MessageType.Error, 2, "Parsing failed.");
+  public static final Message PARSING_FAILED =
+      new Message(MessageType.Error, MessageCode.MESSAGE_CODE_UNKNOWN, "Parsing failed.");
 
   public static final Message UNKNOWN_DATATYPE =
-      new Message(MessageType.Error, 0, "Unknown datatype.");
+      new Message(MessageType.Error, MessageCode.MESSAGE_CODE_UNKNOWN, "Unknown datatype.");
 
   public static final Message UNKNOWN_IMPORTANCE =
-      new Message(MessageType.Error, 0, "Unknown importance.");
+      new Message(MessageType.Error, MessageCode.MESSAGE_CODE_UNKNOWN, "Unknown importance.");
 
   public static final Message ENTITY_HAS_NO_ID =
-      new Message(MessageType.Error, 0, "Entity has no ID.");
+      new Message(
+          MessageType.Error, MessageCode.MESSAGE_CODE_ENTITY_HAS_NO_ID, "Entity has no ID.");
 
   public static final Message REQUIRED_BY_PERSISTENT_ENTITY =
       new Message(
           MessageType.Error,
-          0,
+          MessageCode.MESSAGE_CODE_REQUIRED_BY_PERSISTENT_ENTITY,
           "Entity is required by other entities which are not to be deleted.");
 
-  public static final Message NO_DATATYPE =
-      new Message(MessageType.Error, 110, "Property has no datatype.");
+  public static final Message PROPERTY_HAS_NO_DATATYPE =
+      new Message(
+          MessageType.Error,
+          MessageCode.MESSAGE_CODE_PROPERTY_HAS_NO_DATA_TYPE,
+          "Property has no data type.");
 
   public static final Message ENTITY_HAS_NO_DESCRIPTION =
-      new Message(MessageType.Error, 0, "Entity has no description.");
+      new Message(
+          MessageType.Error,
+          MessageCode.MESSAGE_CODE_ENTITY_HAS_NO_DESCRIPTION,
+          "Entity has no description.");
 
   public static final Message ENTITY_HAS_NO_NAME =
-      new Message(MessageType.Error, 0, "Entity has no name.");
+      new Message(
+          MessageType.Error, MessageCode.MESSAGE_CODE_ENTITY_HAS_NO_NAME, "Entity has no name.");
 
   public static final Message OBLIGATORY_PROPERTY_MISSING =
-      new Message(MessageType.Error, 0, "An obligatory property is missing.");
+      new Message(
+          MessageType.Error,
+          MessageCode.MESSAGE_CODE_OBLIGATORY_PROPERTY_MISSING,
+          "An obligatory property is missing.");
 
   public static final Message ENTITY_HAS_NO_PARENTS =
-      new Message(MessageType.Error, 0, "Entity has no parents.");
-
-  public static final Message NAME_DUPLICATES =
-      new Message(MessageType.Error, 0, "Entity can not be identified due to name duplicates.");
+      new Message(
+          MessageType.Error,
+          MessageCode.MESSAGE_CODE_ENTITY_HAS_NO_PARENTS,
+          "Entity has no parents.");
 
   public static final Message ENTITY_HAS_NO_PROPERTIES =
-      new Message(MessageType.Error, 0, "Entity has no properties.");
-
-  public static final Message REFERENCE_HAS_NO_REFID =
-      new Message(MessageType.Error, 0, "Reference property has no refid.");
+      new Message(
+          MessageType.Error,
+          MessageCode.MESSAGE_CODE_ENTITY_HAS_NO_PROPERTIES,
+          "Entity has no properties.");
 
-  public static final Message NO_TARGET_PATH =
-      new Message(MessageType.Error, 0, "No target path specified.");
+  public static final Message FILE_HAS_NO_TARGET_PATH =
+      new Message(
+          MessageType.Error,
+          MessageCode.MESSAGE_CODE_FILE_HAS_NO_TARGET_PATH,
+          "No target path specified.");
 
   public static final Message TARGET_PATH_NOT_ALLOWED =
-      new Message(MessageType.Error, 0, "This target path is not allowed.");
+      new Message(
+          MessageType.Error,
+          MessageCode.MESSAGE_CODE_TARGET_PATH_NOT_ALLOWED,
+          "This target path is not allowed.");
 
   public static final Message TARGET_PATH_EXISTS =
-      new Message(MessageType.Error, 0, "This target path does already exist.");
+      new Message(
+          MessageType.Error,
+          MessageCode.MESSAGE_CODE_TARGET_PATH_EXISTS,
+          "This target path does already exist.");
 
-  public static final Message ENTITY_HAS_NO_UNIT =
-      new Message(MessageType.Error, 0, "Entity has no unit.");
+  public static final Message PROPERTY_HAS_NO_UNIT =
+      new Message(
+          MessageType.Error,
+          MessageCode.MESSAGE_CODE_PROPERTY_HAS_NO_UNIT,
+          "Property has no unit.");
 
   public static final Message CANNOT_PARSE_VALUE =
-      new Message(MessageType.Error, 0, "Cannot parse value.");
+      new Message(
+          MessageType.Error,
+          MessageCode.MESSAGE_CODE_CANNOT_PARSE_VALUE,
+          "Cannot parse the value.");
 
   public static final Message CHECKSUM_TEST_FAILED =
-      new Message(MessageType.Error, 0, "Checksum test failed. File is corrupted.");
+      new Message(
+          MessageType.Error,
+          MessageCode.MESSAGE_CODE_CHECKSUM_TEST_FAILED,
+          "Checksum test failed. File is corrupted.");
 
   public static final Message SIZE_TEST_FAILED =
-      new Message(MessageType.Error, 0, "Size test failed. File is corrupted.");
+      new Message(
+          MessageType.Error,
+          MessageCode.MESSAGE_CODE_SIZE_TEST_FAILED,
+          "Size test failed. File is corrupted.");
 
   public static final Message CANNOT_CREATE_PARENT_FOLDER =
-      new Message(MessageType.Error, 0, "Could not create parent folder in the file system.");
+      new Message(
+          MessageType.Error,
+          MessageCode.MESSAGE_CODE_CANNOT_CREATE_PARENT_FOLDER,
+          "Could not create parent folder in the file system.");
 
   public static final Message FILE_HAS_NOT_BEEN_UPLOAED =
-      new Message(MessageType.Error, 0, "File has not been uploaded.");
+      new Message(
+          MessageType.Error,
+          MessageCode.MESSAGE_CODE_FILE_HAS_NOT_BEEN_UPLOAED,
+          "File has not been uploaded.");
 
   public static final Message THUMBNAIL_HAS_NOT_BEEN_UPLOAED =
-      new Message(MessageType.Error, 0, "Thumbnail has not been uploaded.");
+      new Message(
+          MessageType.Error, MessageCode.MESSAGE_CODE_UNKNOWN, "Thumbnail has not been uploaded.");
 
   public static final Message CANNOT_MOVE_FILE_TO_TARGET_PATH =
-      new Message(MessageType.Error, 0, "Could not move file to it's target folder.");
+      new Message(
+          MessageType.Error,
+          MessageCode.MESSAGE_CODE_CANNOT_MOVE_FILE_TO_TARGET_PATH,
+          "Could not move file to it's target folder.");
 
   public static final Message CANNOT_PARSE_DATETIME_VALUE =
       new Message(
           MessageType.Error,
-          0,
+          MessageCode.MESSAGE_CODE_CANNOT_PARSE_DATETIME_VALUE,
           "Cannot parse value to datetime format (yyyy-mm-dd'T'hh:mm:ss[.fffffffff][TimeZone]).");
 
   public static final Message CANNOT_PARSE_DOUBLE_VALUE =
-      new Message(MessageType.Error, 0, "Cannot parse value to double.");
+      new Message(
+          MessageType.Error,
+          MessageCode.MESSAGE_CODE_CANNOT_PARSE_DOUBLE_VALUE,
+          "Cannot parse value to double.");
 
   public static final Message CANNOT_PARSE_INT_VALUE =
-      new Message(MessageType.Error, 0, "Cannot parse value to integer.");
+      new Message(
+          MessageType.Error,
+          MessageCode.MESSAGE_CODE_CANNOT_PARSE_INT_VALUE,
+          "Cannot parse value to integer.");
 
   public static final Message CANNOT_PARSE_BOOL_VALUE =
       new Message(
           MessageType.Error,
-          0,
+          MessageCode.MESSAGE_CODE_CANNOT_PARSE_BOOL_VALUE,
           "Cannot parse value to boolean (either 'true' or 'false', ignoring case).");
 
   public static final Message CANNOT_CONNECT_TO_DATABASE =
-      new Message(MessageType.Error, 0, "Could not connect to MySQL server.");
-
-  public static final Message REQUEST_BODY_NOT_WELLFORMED =
-      new Message(MessageType.Error, 0, "Request Body was not a well-formed xml.");
-
-  public static final Message REQUEST_BODY_EMPTY =
-      new Message(MessageType.Error, 0, "Request body was empty.");
-
-  public static final Message MYSQL_PROCEDURE_EXCEPTION =
       new Message(
           MessageType.Error,
-          0,
-          "Please check if your MySQL has all required procedures installed.");
+          MessageCode.MESSAGE_CODE_UNKNOWN,
+          "Could not connect to MySQL server.");
 
-  public static final Message REQUEST_HAS_WRONG_ENCODING =
+  public static final Message REQUEST_BODY_NOT_WELLFORMED =
       new Message(
           MessageType.Error,
-          0,
-          "This error occurred while parsing the xml. Probably it has a wrong encoding.");
+          MessageCode.MESSAGE_CODE_UNKNOWN,
+          "Request Body was not a well-formed xml.");
+
+  public static final Message REQUEST_BODY_EMPTY =
+      new Message(MessageType.Error, MessageCode.MESSAGE_CODE_UNKNOWN, "Request body was empty.");
 
   public static final Message REQUEST_DOESNT_CONTAIN_EXPECTED_ELEMENTS =
-      new Message(MessageType.Error, 0, "Request body didn't contain the expected Elements.");
+      new Message(
+          MessageType.Error,
+          MessageCode.MESSAGE_CODE_UNKNOWN,
+          "Request body didn't contain the expected Elements.");
 
   public static final Message FILE_NOT_IN_DROPOFFBOX =
-      new Message(MessageType.Error, 0, "File is not in drop-off box.");
+      new Message(
+          MessageType.Error, MessageCode.MESSAGE_CODE_UNKNOWN, "File is not in drop-off box.");
 
   public static final Message FILE_NOT_FOUND =
-      new Message(MessageType.Error, 0, "File could not be found.");
+      new Message(
+          MessageType.Error, MessageCode.MESSAGE_CODE_FILE_NOT_FOUND, "File could not be found.");
 
   public static final Message CANNOT_MOVE_FILE_TO_TMP =
-      new Message(MessageType.Error, 0, "Could not move file to tmp folder.");
+      new Message(
+          MessageType.Error,
+          MessageCode.MESSAGE_CODE_UNKNOWN,
+          "Could not move file to tmp folder.");
 
   public static final Message CANNOT_READ_FILE =
       new Message(
           MessageType.Error,
-          0,
+          MessageCode.MESSAGE_CODE_UNKNOWN,
           "Insufficient read permission for this file. Please make it readable.");
 
   public static final Message CANNOT_READ_THUMBNAIL =
       new Message(
           MessageType.Error,
-          0,
+          MessageCode.MESSAGE_CODE_UNKNOWN,
           "Insufficient read permission for this file's thumbnail. Please make it readable.");
 
   public static final Message NO_FILE_REPRESENTATION_SUBMITTED =
-      new Message(MessageType.Error, 0, "No file representation submitted.");
+      new Message(
+          MessageType.Error, MessageCode.MESSAGE_CODE_UNKNOWN, "No file representation submitted.");
 
   public static final Message FORM_CONTAINS_UNSUPPORTED_CONTENT =
-      new Message(MessageType.Error, 0, "The form contains unsupported content");
-
-  public static final Message FILE_IS_EMPTY = new Message(MessageType.Error, 0, "File is empty.");
+      new Message(
+          MessageType.Error,
+          MessageCode.MESSAGE_CODE_UNKNOWN,
+          "The form contains unsupported content");
 
   public static final Message WARNING_OCCURED =
       new Message(
           MessageType.Error,
-          128,
+          MessageCode.MESSAGE_CODE_WARNING_OCCURED,
           "A warning occured while processing an entity with the strict flag.");
 
-  public static final Message UNKNOWN_JOB = new Message(MessageType.Warning, 0, "Unknown job.");
-
-  public static final Message NAME_IS_NOT_UNIQUE =
+  public static final Message ENTITY_NAME_IS_NOT_UNIQUE =
       new Message(
           MessageType.Error,
-          152,
+          MessageCode.MESSAGE_CODE_ENTITY_NAME_IS_NOT_UNIQUE,
           "Name is already in use. Choose a different name or reuse an existing entity.");
 
   public static final Message ROLE_NAME_IS_NOT_UNIQUE =
-      new Message(MessageType.Error, 1152, "Role name is already in use. Choose a different name.");
-
-  public static final Message CANNOT_IDENTIFY_ENTITY_UNIQUELY =
       new Message(
-          MessageType.Error, 0, "This entity cannot be identified uniquely due to name dublicates");
+          MessageType.Error,
+          MessageCode.MESSAGE_CODE_UNKNOWN,
+          "Role name is already in use. Choose a different name.");
 
   public static final Message QUERY_EXCEPTION =
-      new Message(MessageType.Error, 13, "This query finished with errors.");
+      new Message(
+          MessageType.Error,
+          MessageCode.MESSAGE_CODE_QUERY_EXCEPTION,
+          "This query finished with errors.");
 
   public static final Message LOGOUT_INFO =
-      new Message(MessageType.Info, 201, "You have successfully logged out.");
+      new Message(
+          MessageType.Info, MessageCode.MESSAGE_CODE_UNKNOWN, "You have successfully logged out.");
 
   public static final Message ENTITY_IS_EMPTY =
-      new Message(MessageType.Error, 0, "This entity is empty.");
+      new Message(MessageType.Error, MessageCode.MESSAGE_CODE_UNKNOWN, "This entity is empty.");
 
   public static final Message TRANSACTION_ROLL_BACK =
       new Message(
           MessageType.Error,
-          0,
+          MessageCode.MESSAGE_CODE_TRANSACTION_ROLL_BACK,
           "An unknown error occured during the transaction and it was rolled back.");
 
   public static final Message FILE_UPLOAD_FAILED =
-      new Message(MessageType.Error, 0, "The file upload failed for an unknown reason.");
+      new Message(
+          MessageType.Error,
+          MessageCode.MESSAGE_CODE_UNKNOWN,
+          "The file upload failed for an unknown reason.");
 
   public static final Message ACCOUNT_CANNOT_BE_ACTIVATED =
-      new Message(MessageType.Error, 0, "This account cannot be activated.");
+      new Message(
+          MessageType.Error, MessageCode.MESSAGE_CODE_UNKNOWN, "This account cannot be activated.");
 
   public static final Message ACCOUNT_DOES_NOT_EXIST =
-      new Message(MessageType.Error, 0, "This account does not exist.");
+      new Message(
+          MessageType.Error, MessageCode.MESSAGE_CODE_UNKNOWN, "This account does not exist.");
 
   public static final Message ACCOUNT_CANNOT_BE_RESET =
-      new Message(MessageType.Error, 0, "This account cannot be reset.");
+      new Message(
+          MessageType.Error, MessageCode.MESSAGE_CODE_UNKNOWN, "This account cannot be reset.");
 
   public static final Message UNKNOWN_UNIT =
       new Message(
           MessageType.Error,
-          0,
+          MessageCode.MESSAGE_CODE_UNKNOWN_UNIT,
           "Unknown unit. Values with this unit cannot be converted to other units when used in search queries.");
 
   public static final Message ACCOUNT_NAME_NOT_UNIQUE =
-      new Message(MessageType.Error, 0, "This user name is yet in use. Please choose another one.");
+      new Message(
+          MessageType.Error,
+          MessageCode.MESSAGE_CODE_UNKNOWN,
+          "This user name is yet in use. Please choose another one.");
 
   public static final Message ACCOUNT_HAS_BEEN_DELETED =
-      new Message(MessageType.Info, 10, "This user has been deleted successfully.");
+      new Message(
+          MessageType.Info,
+          MessageCode.MESSAGE_CODE_UNKNOWN,
+          "This user has been deleted successfully.");
 
   public static final Message PLEASE_SET_A_PASSWORD =
-      new Message(MessageType.Info, 0, "Please set a password.");
+      new Message(MessageType.Info, MessageCode.MESSAGE_CODE_UNKNOWN, "Please set a password.");
 
   public static final Message USER_HAS_BEEN_ACTIVATED =
       new Message(
           MessageType.Info,
-          0,
+          MessageCode.MESSAGE_CODE_UNKNOWN,
           "User has been activated. You can now log in with your username and password.");
 
   public static final Message UNAUTHENTICATED =
-      new Message(MessageType.Error, 401, "Sign in, please.");
+      new Message(MessageType.Error, MessageCode.MESSAGE_CODE_UNKNOWN, "Sign in, please.");
 
   public static final Message AUTHORIZATION_ERROR =
-      new Message(MessageType.Error, 403, "You are not allowed to do this.");
+      new Message(
+          MessageType.Error, MessageCode.MESSAGE_CODE_UNKNOWN, "You are not allowed to do this.");
 
   public static final Message REFERENCE_IS_NOT_ALLOWED_BY_DATATYPE =
       new Message(
           MessageType.Error,
-          0,
+          MessageCode.MESSAGE_CODE_REFERENCE_IS_NOT_ALLOWED_BY_DATA_TYPE,
           "Reference not qualified. The value of this Reference Property is to be a child of its data type.");
 
   public static final Message CANNOT_PARSE_ENTITY_ACL =
-      new Message(MessageType.Error, 0, "Cannot parse EntityACL.");
+      new Message(MessageType.Error, MessageCode.MESSAGE_CODE_UNKNOWN, "Cannot parse EntityACL.");
 
   public static final Message ROLE_DOES_NOT_EXIST =
-      new Message(MessageType.Error, 1104, "User Role does not exist.");
+      new Message(MessageType.Error, MessageCode.MESSAGE_CODE_UNKNOWN, "User Role does not exist.");
 
   public static final Message ENTITY_NAME_DUPLICATES =
-      new Message(MessageType.Error, 0, "This entity cannot be identified due to name duplicates.");
+      new Message(
+          MessageType.Error,
+          MessageCode.MESSAGE_CODE_ENTITY_NAME_DUPLICATES,
+          "This entity cannot be identified due to name duplicates.");
 
   public static final Message DATA_TYPE_NAME_DUPLICATES =
       new Message(
-          MessageType.Error, 0, "This data type cannot be identified due to name duplicates.");
+          MessageType.Error,
+          MessageCode.MESSAGE_CODE_DATA_TYPE_NAME_DUPLICATES,
+          "This data type cannot be identified due to name duplicates.");
 
   public static final Message ENTITY_HAS_NO_NAME_OR_ID =
       new Message(
           MessageType.Error,
-          0,
+          MessageCode.MESSAGE_CODE_ENTITY_HAS_NO_NAME_OR_ID,
           "This entity cannot be identified as it didn't come with a name or id.");
 
   public static final Message EMAIL_NOT_WELL_FORMED =
-      new Message(MessageType.Error, 0, "This email address is not RFC822 compliant.");
+      new Message(
+          MessageType.Error,
+          MessageCode.MESSAGE_CODE_UNKNOWN,
+          "This email address is not RFC822 compliant.");
 
   public static final Message PASSWORD_TOO_WEAK =
       new Message(
           MessageType.Error,
-          0,
+          MessageCode.MESSAGE_CODE_UNKNOWN,
           "This password is too weak. It should be longer than 8 characters and sufficiently random. ");
 
   public static final Message AFFILIATION_ERROR =
       new Message(
-          MessageType.Error, 0, "Affiliation is not defined for this child-parent constellation.");
+          MessageType.Error,
+          MessageCode.MESSAGE_CODE_AFFILIATION_ERROR,
+          "Affiliation is not defined for this child-parent constellation.");
 
   public static final Message QUERY_TEMPLATE_HAS_NO_QUERY_DEFINITION =
-      new Message(MessageType.Error, 0, "This QueryTemplate has no query definition.");
+      new Message(
+          MessageType.Error,
+          MessageCode.MESSAGE_CODE_UNKNOWN,
+          "This QueryTemplate has no query definition.");
 
   public static final Message QUERY_TEMPLATE_WITH_COUNT =
       new Message(
           MessageType.Error,
-          0,
+          MessageCode.MESSAGE_CODE_UNKNOWN,
           "QueryTemplates may not be defined by 'COUNT...' queries for consistency reasons.");
 
   public static final Message QUERY_TEMPLATE_WITH_SELECT =
       new Message(
           MessageType.Error,
-          0,
+          MessageCode.MESSAGE_CODE_UNKNOWN,
           "QueryTemplates may not be defined by 'SELECT... FROM...' queries for consistency reasons.");
 
   public static final Message QUERY_PARSING_ERROR =
       new Message(
           MessageType.Error,
-          0,
+          MessageCode.MESSAGE_CODE_QUERY_PARSING_ERROR,
           "An error occured during the parsing of this query. Maybe you use a wrong syntax?");
 
   public static final Message NAME_PROPERTIES_MUST_BE_TEXT =
       new Message(
           MessageType.Error,
-          0,
+          MessageCode.MESSAGE_CODE_NAME_PROPERTIES_MUST_BE_TEXT,
           "A property which has 'name' as its parent must have a TEXT data type.");
 
   public static final Message PARENT_DUPLICATES_WARNING =
       new Message(
           MessageType.Warning,
-          0,
+          MessageCode.MESSAGE_CODE_PARENT_DUPLICATES_WARNING,
           "This entity had parent duplicates. That is meaningless and only one parent had been inserted.");
 
   public static final Message PARENT_DUPLICATES_ERROR =
       new Message(
           MessageType.Error,
-          0,
+          MessageCode.MESSAGE_CODE_PARENT_DUPLICATES_ERROR,
           "This entity had parent duplicates. Parent duplicates are meaningless and would be ignored (and inserted only once). But these parents had diverging inheritance instructions which cannot be processed.");
 
   public static final Message ATOMICITY_ERROR =
       new Message(
           MessageType.Error,
-          12,
+          MessageCode.MESSAGE_CODE_ATOMICITY_ERROR,
           "One or more entities are not qualified. None of them have been inserted/updated/deleted.");
 
   public static final Message NO_SUCH_ENTITY_ROLE(final String role) {
-    return new Message(MessageType.Error, 0, "There is no such role '" + role + "'.");
+    return new Message(
+        MessageType.Error,
+        MessageCode.MESSAGE_CODE_NO_SUCH_ENTITY_ROLE,
+        "There is no such role '" + role + "'.");
   }
 
   public static Message UNKNOWN_ERROR(final String requestID) {
@@ -364,78 +459,124 @@ public class ServerMessages {
               + " and include the SRID into your report.";
     }
 
-    return new Message(MessageType.Error, 500, description, body.isEmpty() ? null : body);
+    return new Message(
+        MessageType.Error,
+        MessageCode.MESSAGE_CODE_UNKNOWN,
+        description,
+        body.isEmpty() ? null : body);
   }
 
   public static final Message REQUIRED_BY_UNQUALIFIED =
       new Message(
-          MessageType.Error, 192, "This entity cannot be deleted due to dependency problems");
+          MessageType.Error,
+          MessageCode.MESSAGE_CODE_REQUIRED_BY_UNQUALIFIED,
+          "This entity cannot be deleted due to dependency problems");
 
-  public static final Message ENTITY_HAS_INVALID_REFERENCE =
-      new Message(MessageType.Error, 0, "This entity has an invalid reference.");
+  public static final Message ENTITY_HAS_UNQUALIFIED_REFERENCE =
+      new Message(
+          MessageType.Error,
+          MessageCode.MESSAGE_CODE_ENTITY_HAS_UNQUALIFIED_REFERENCE,
+          "This entity has an unqualified reference.");
 
   public static final Message REFERENCED_ENTITY_DOES_NOT_EXIST =
-      new Message(MessageType.Error, 235, "Referenced entity does not exist.");
+      new Message(
+          MessageType.Error,
+          MessageCode.MESSAGE_CODE_REFERENCED_ENTITY_DOES_NOT_EXIST,
+          "Referenced entity does not exist.");
 
   public static final Message REFERENCE_NAME_DUPLICATES =
       new Message(
-          MessageType.Error, 0, "This reference cannot be identified due to name duplicates.");
+          MessageType.Error,
+          MessageCode.MESSAGE_CODE_REFERENCE_NAME_DUPLICATES,
+          "This reference cannot be identified due to name duplicates.");
 
   public static final Message DATATYPE_INHERITANCE_AMBIGUOUS =
       new Message(
           MessageType.Error,
-          0,
+          MessageCode.MESSAGE_CODE_DATA_TYPE_INHERITANCE_AMBIGUOUS,
           "The datatype which is to be inherited could not be detected due to divergent datatypes of at least two parents.");
 
   public static final Message DATA_TYPE_DOES_NOT_ACCEPT_COLLECTION_VALUES =
       new Message(
           MessageType.Error,
-          0,
+          MessageCode.MESSAGE_CODE_DATA_TYPE_DOES_NOT_ACCEPT_COLLECTION_VALUES,
           "This datatype does not accept collections of values (e.g. Lists).");
 
   public static final Message CANNOT_PARSE_UNIT =
-      new Message(MessageType.Error, 0, "This unit cannot be parsed.");
+      new Message(
+          MessageType.Error,
+          MessageCode.MESSAGE_CODE_CANNOT_PARSE_UNIT,
+          "This unit cannot be parsed.");
 
   public static final Message SERVER_SIDE_SCRIPT_DOES_NOT_EXIST =
       new Message(
-          MessageType.Error, 404, "This server-side script does not exist. Did you install it?");
+          MessageType.Error,
+          MessageCode.MESSAGE_CODE_UNKNOWN,
+          "This server-side script does not exist. Did you install it?");
 
   public static final Message SERVER_SIDE_SCRIPT_NOT_EXECUTABLE =
-      new Message(MessageType.Error, 400, "This server-side script is not executable.");
+      new Message(
+          MessageType.Error,
+          MessageCode.MESSAGE_CODE_UNKNOWN,
+          "This server-side script is not executable.");
 
   public static final Message SERVER_SIDE_SCRIPT_ERROR =
-      new Message(MessageType.Error, 500, "The invocation of this server-side script failed.");
+      new Message(
+          MessageType.Error,
+          MessageCode.MESSAGE_CODE_UNKNOWN,
+          "The invocation of this server-side script failed.");
 
   public static final Message SERVER_SIDE_SCRIPT_SETUP_ERROR =
       new Message(
           MessageType.Error,
-          500,
+          MessageCode.MESSAGE_CODE_UNKNOWN,
           "The setup routine for the server-side script failed. This might indicate a misconfiguration of the server. Please contact the administrator.");
 
   public static final Message SERVER_SIDE_SCRIPT_TIMEOUT =
-      new Message(MessageType.Error, 400, "This server-side script did not finish in time.");
+      new Message(
+          MessageType.Error,
+          MessageCode.MESSAGE_CODE_UNKNOWN,
+          "This server-side script did not finish in time.");
 
   public static final Message SERVER_SIDE_SCRIPT_MISSING_CALL =
-      new Message(MessageType.Error, 400, "You must specify the `call` field.");
+      new Message(
+          MessageType.Error,
+          MessageCode.MESSAGE_CODE_UNKNOWN,
+          "You must specify the `call` field.");
 
   public static final Message ADDITIONAL_PROPERTY =
       new Message(
           MessageType.Warning,
-          0,
+          MessageCode.MESSAGE_CODE_ADDITIONAL_PROPERTY,
           "This property is an additional property which has no corresponding property among the properties of the parents.");
 
   public static final Message PROPERTY_WITH_DATATYPE_OVERRIDE =
-      new Message(MessageType.Warning, 0, "This property overrides the datatype.");
+      new Message(
+          MessageType.Warning,
+          MessageCode.MESSAGE_CODE_PROPERTY_WITH_DATA_TYPE_OVERRIDE,
+          "This property overrides the datatype.");
 
   public static final Message PROPERTY_WITH_DESC_OVERRIDE =
-      new Message(MessageType.Warning, 0, "This property overrides the description.");
+      new Message(
+          MessageType.Warning,
+          MessageCode.MESSAGE_CODE_PROPERTY_WITH_DESCRIPTION_OVERRIDE,
+          "This property overrides the description.");
 
   public static final Message PROPERTY_WITH_NAME_OVERRIDE =
-      new Message(MessageType.Warning, 0, "This property overrides the name.");
+      new Message(
+          MessageType.Warning,
+          MessageCode.MESSAGE_CODE_PROPERTY_WITH_NAME_OVERRIDE,
+          "This property overrides the name.");
 
   public static final Message INTEGER_OUT_OF_RANGE =
       new Message(
           MessageType.Error,
-          MessageCode.MESSAGE_CODE_INTEGER_VALUE_OUT_OF_RANGE_VALUE,
+          MessageCode.MESSAGE_CODE_INTEGER_VALUE_OUT_OF_RANGE,
           "The integer value is out of range. This server only supports signed 32 bit integers.");
+
+  public static final Message ERROR_INTEGRITY_VIOLATION =
+      new Message(
+          MessageType.Error,
+          MessageCode.MESSAGE_CODE_INTEGRITY_VIOLATION,
+          "This entity caused an unexpected integrity violation. This is a strong indicator for a server bug. Please report.");
 }