diff --git a/duniter4j-core-client/src/main/java/org/duniter/core/client/model/bma/jackson/JacksonUtils.java b/duniter4j-core-client/src/main/java/org/duniter/core/client/model/bma/jackson/JacksonUtils.java
index 9f754aef2c877cdb3a0aa8c4dcc336051ee1b316..d0289195eb54fc66666194b67221cd0f754b28d4 100644
--- a/duniter4j-core-client/src/main/java/org/duniter/core/client/model/bma/jackson/JacksonUtils.java
+++ b/duniter4j-core-client/src/main/java/org/duniter/core/client/model/bma/jackson/JacksonUtils.java
@@ -22,6 +22,7 @@ package org.duniter.core.client.model.bma.jackson;
  * #L%
  */
 
+import com.fasterxml.jackson.core.JsonGenerator;
 import com.fasterxml.jackson.core.util.MinimalPrettyPrinter;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.SerializationConfig;
@@ -58,6 +59,9 @@ public abstract class JacksonUtils extends SimpleModule {
 
         objectMapper.registerModule(module);
 
+        // Adding features
+        //objectMapper.getFactory().configure(JsonGenerator.Feature., true);
+
         return objectMapper;
     }
 
diff --git a/duniter4j-core-client/src/main/java/org/duniter/core/client/model/elasticsearch/MessageRecord.java b/duniter4j-core-client/src/main/java/org/duniter/core/client/model/elasticsearch/Message.java
similarity index 64%
rename from duniter4j-core-client/src/main/java/org/duniter/core/client/model/elasticsearch/MessageRecord.java
rename to duniter4j-core-client/src/main/java/org/duniter/core/client/model/elasticsearch/Message.java
index 5ab690534818f7078d90e7cf259fa042d75f0e02..16102aaa8464694b5d03ed438ae261467c5ab778 100644
--- a/duniter4j-core-client/src/main/java/org/duniter/core/client/model/elasticsearch/MessageRecord.java
+++ b/duniter4j-core-client/src/main/java/org/duniter/core/client/model/elasticsearch/Message.java
@@ -22,17 +22,31 @@ package org.duniter.core.client.model.elasticsearch;
  * #L%
  */
 
+import com.fasterxml.jackson.annotation.JsonGetter;
+import com.fasterxml.jackson.annotation.JsonSetter;
+
 /**
  * Created by blavenie on 01/03/16.
  */
-public class MessageRecord extends Record {
+public class Message extends Record {
 
+    public static final String PROPERTY_TITLE="title";
     public static final String PROPERTY_CONTENT="content";
     public static final String PROPERTY_RECIPIENT="recipient";
+    public static final String PROPERTY_READ_SIGNATURE="read_signature";
 
-
+    private String title;
     private String content;
     private String recipient;
+    private String readSignature;
+
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(String title) {
+        this.title = title;
+    }
 
     public String getContent() {
         return content;
@@ -49,4 +63,15 @@ public class MessageRecord extends Record {
     public void setRecipient(String recipient) {
         this.recipient = recipient;
     }
+
+    @JsonGetter(PROPERTY_READ_SIGNATURE)
+    public String getReadSignature() {
+        return readSignature;
+    }
+
+    @JsonSetter(PROPERTY_READ_SIGNATURE)
+    public void setReadSignature(String readSignature) {
+        this.readSignature = readSignature;
+    }
+
 }
diff --git a/duniter4j-core-client/src/main/java/org/duniter/core/client/model/elasticsearch/Records.java b/duniter4j-core-client/src/main/java/org/duniter/core/client/model/elasticsearch/Records.java
new file mode 100644
index 0000000000000000000000000000000000000000..95f723251985a2d02865e4001598130ab35d176c
--- /dev/null
+++ b/duniter4j-core-client/src/main/java/org/duniter/core/client/model/elasticsearch/Records.java
@@ -0,0 +1,38 @@
+package org.duniter.core.client.model.elasticsearch;
+
+/*
+ * #%L
+ * Duniter4j :: Core Client API
+ * %%
+ * Copyright (C) 2014 - 2016 EIS
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the 
+ * License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public 
+ * License along with this program.  If not, see
+ * <http://www.gnu.org/licenses/gpl-3.0.html>.
+ * #L%
+ */
+
+/**
+ * Helper class
+ * Created by blavenie on 01/03/16.
+ */
+public final class Records {
+
+    public static final String PROPERTY_ISSUER="issuer";
+    public static final String PROPERTY_HASH="hash";
+    public static final String PROPERTY_SIGNATURE="signature";
+    public static final String PROPERTY_TIME="time";
+    public static final String PROPERTY_READ_SIGNATURE="read_signature";
+
+
+}
diff --git a/duniter4j-core-client/src/main/java/org/duniter/core/client/service/HttpServiceImpl.java b/duniter4j-core-client/src/main/java/org/duniter/core/client/service/HttpServiceImpl.java
index f91020e3aadbbfde90945f800df051d042d8e70d..7810c7e5c9f690029c14391ca79b33593f4f3ba3 100644
--- a/duniter4j-core-client/src/main/java/org/duniter/core/client/service/HttpServiceImpl.java
+++ b/duniter4j-core-client/src/main/java/org/duniter/core/client/service/HttpServiceImpl.java
@@ -24,6 +24,7 @@ package org.duniter.core.client.service;
 
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.base.Charsets;
 import com.google.common.base.Joiner;
 import org.apache.http.HttpResponse;
 import org.apache.http.HttpStatus;
@@ -517,7 +518,7 @@ public class HttpServiceImpl implements HttpService, Closeable, InitializingBean
     }
 
     public <T> T readValue(InputStream json, Class<T> clazz) throws IOException {
-        return objectMapper.readValue(json, clazz);
+        return objectMapper.readValue(new InputStreamReader(json, Charsets.UTF_8.name()), clazz);
     }
 
 }
diff --git a/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/model/SynchroResult.java b/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/model/SynchroResult.java
index 51f6050560e4918e3280a0ae984f564f24269d8b..b87dcab03b34a8a1563364704fe5ccfacde3c0f1 100644
--- a/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/model/SynchroResult.java
+++ b/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/model/SynchroResult.java
@@ -33,9 +33,11 @@ public class SynchroResult {
     private long insertTotal = 0;
     private long updateTotal = 0;
     private long deleteTotal = 0;
+    private long invalidSignatureTotal = 0;
     private Map<String, Long> insertHits = new HashMap<>();
     private Map<String, Long> updateHits = new HashMap<>();
     private Map<String, Long> deleteHits = new HashMap<>();
+    private Map<String, Long> invalidSignatureHits = new HashMap<>();
 
     public void addInserts(String index, String type, long nbHits) {
         insertHits.put(index + "/" + type, getInserts(index, type) + nbHits);
@@ -52,6 +54,11 @@ public class SynchroResult {
         deleteTotal += nbHits;
     }
 
+    public void addInvalidSignatures(String index, String type, long nbHits) {
+        invalidSignatureHits.put(index + "/" + type, getDeletes(index, type) + nbHits);
+        invalidSignatureTotal += nbHits;
+    }
+
     public long getInserts(String index, String type) {
         return insertHits.getOrDefault(index + "/" + type, 0l);
     }
@@ -60,6 +67,10 @@ public class SynchroResult {
         return updateHits.getOrDefault(index + "/" + type, 0l);
     }
 
+    public long getInvalidSignatures(String index, String type) {
+        return invalidSignatureHits.getOrDefault(index + "/" + type, 0l);
+    }
+
     public long getDeletes(String index, String type) {
         return deleteHits.getOrDefault(index + "/" + type, 0l);
     }
@@ -76,6 +87,10 @@ public class SynchroResult {
         return deleteTotal;
     }
 
+    public long getInvalidSignatures() {
+        return invalidSignatureTotal;
+    }
+
     public long getTotal() {
         return insertTotal + updateTotal + deleteTotal;
     }
diff --git a/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/service/AbstractService.java b/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/service/AbstractService.java
index f4e61aacbed844b003bf4c0cae2552c1a27a28e3..a06c0220772d339ba8f00743b2098ad5da0844ce 100644
--- a/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/service/AbstractService.java
+++ b/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/service/AbstractService.java
@@ -23,12 +23,14 @@ package org.duniter.elasticsearch.service;
  */
 
 
+import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.google.common.collect.ImmutableSet;
 import org.duniter.core.beans.Bean;
 import org.duniter.core.client.model.bma.jackson.JacksonUtils;
 import org.duniter.core.client.model.elasticsearch.Record;
+import org.duniter.core.client.model.elasticsearch.Records;
 import org.duniter.core.exception.TechnicalException;
 import org.duniter.core.service.CryptoService;
 import org.duniter.elasticsearch.PluginSettings;
@@ -36,7 +38,6 @@ import org.duniter.elasticsearch.client.Duniter4jClient;
 import org.duniter.elasticsearch.exception.InvalidFormatException;
 import org.duniter.elasticsearch.exception.InvalidSignatureException;
 import org.elasticsearch.ElasticsearchException;
-import org.elasticsearch.client.Client;
 import org.elasticsearch.common.logging.ESLogger;
 import org.elasticsearch.common.logging.Loggers;
 import org.nuiton.i18n.I18n;
@@ -111,41 +112,30 @@ public abstract class AbstractService implements Bean {
     }
 
     protected JsonNode readAndVerifyIssuerSignature(String recordJson) throws ElasticsearchException {
+       return readAndVerifyIssuerSignature(recordJson, Records.PROPERTY_ISSUER);
+    }
+
+    protected JsonNode readAndVerifyIssuerSignature(String recordJson, String issuerFieldName) throws ElasticsearchException {
 
         try {
-            JsonNode actualObj = objectMapper.readTree(recordJson);
-            readAndVerifyIssuerSignature(recordJson, actualObj);
-            return actualObj;
+            JsonNode recordObj = objectMapper.readTree(recordJson);
+            readAndVerifyIssuerSignature(recordJson, recordObj, issuerFieldName);
+            return recordObj;
         }
         catch(IOException e) {
             throw new InvalidFormatException("Invalid record JSON: " + e.getMessage(), e);
         }
     }
 
-    protected void readAndVerifyIssuerSignature(String recordJson, JsonNode actualObj) throws ElasticsearchException {
-
-        Set<String> fieldNames = ImmutableSet.copyOf(actualObj.fieldNames());
-        if (!fieldNames.contains(Record.PROPERTY_ISSUER)
-                || !fieldNames.contains(Record.PROPERTY_SIGNATURE)) {
-            throw new InvalidFormatException(String.format("Invalid record JSON format. Required fields [%s,%s]", Record.PROPERTY_ISSUER, Record.PROPERTY_SIGNATURE));
-        }
-        String issuer = getMandatoryField(actualObj, Record.PROPERTY_ISSUER).asText();
-        String signature = getMandatoryField(actualObj, Record.PROPERTY_SIGNATURE).asText();
 
+    protected void readAndVerifyIssuerSignature(JsonNode actualObj, String issuerFieldName) throws ElasticsearchException, JsonProcessingException {
         // Remove hash and signature
-        recordJson = JacksonUtils.removeAttribute(recordJson, Record.PROPERTY_SIGNATURE);
-        recordJson = JacksonUtils.removeAttribute(recordJson, Record.PROPERTY_HASH);
-
-        if (!cryptoService.verify(recordJson, signature, issuer)) {
-            throw new InvalidSignatureException("Invalid signature of JSON string");
-        }
-
-        // TODO: check issuer is in the WOT ?
+        String recordJson = objectMapper.writeValueAsString(actualObj);
+        readAndVerifyIssuerSignature(recordJson, actualObj, issuerFieldName);
     }
 
-
     protected String getIssuer(JsonNode actualObj) {
-        return  getMandatoryField(actualObj, Record.PROPERTY_ISSUER).asText();
+        return  getMandatoryField(actualObj, Records.PROPERTY_ISSUER).asText();
     }
 
     protected JsonNode getMandatoryField(JsonNode actualObj, String fieldName) {
@@ -160,4 +150,32 @@ public abstract class AbstractService implements Bean {
 
         T execute() throws TechnicalException;
     }
+
+    /* -- internal methods -- */
+
+    private void readAndVerifyIssuerSignature(String recordJson, JsonNode recordObj, String issuerFieldName) throws ElasticsearchException {
+
+        Set<String> fieldNames = ImmutableSet.copyOf(recordObj.fieldNames());
+        if (!fieldNames.contains(issuerFieldName)
+                || !fieldNames.contains(Records.PROPERTY_SIGNATURE)) {
+            throw new InvalidFormatException(String.format("Invalid record JSON format. Required fields [%s,%s]", Records.PROPERTY_ISSUER, Records.PROPERTY_SIGNATURE));
+        }
+        String issuer = getMandatoryField(recordObj, issuerFieldName).asText();
+        String signature = getMandatoryField(recordObj, Records.PROPERTY_SIGNATURE).asText();
+
+        // Remove hash and signature
+        recordJson = JacksonUtils.removeAttribute(recordJson, Records.PROPERTY_SIGNATURE);
+        recordJson = JacksonUtils.removeAttribute(recordJson, Records.PROPERTY_HASH);
+
+        // Remove 'read_signature' attribute if exists (added AFTER signature)
+        if (fieldNames.contains(Records.PROPERTY_READ_SIGNATURE)) {
+            recordJson = JacksonUtils.removeAttribute(recordJson, Records.PROPERTY_READ_SIGNATURE);
+        }
+
+        if (!cryptoService.verify(recordJson, signature, issuer)) {
+            throw new InvalidSignatureException("Invalid signature of JSON string");
+        }
+
+        // TODO: check issuer is in the WOT ?
+    }
 }
diff --git a/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/service/AbstractSynchroService.java b/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/service/AbstractSynchroService.java
index 906872b71d511febf4b82d2836ead95cf3a80b86..65c0c73e59c022de5b6e28fdafc00a12380d5ed5 100644
--- a/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/service/AbstractSynchroService.java
+++ b/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/service/AbstractSynchroService.java
@@ -22,7 +22,10 @@ package org.duniter.elasticsearch.service;
  * #L%
  */
 
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.JsonNode;
+import com.google.common.base.Charsets;
 import com.google.common.base.Joiner;
 import org.duniter.core.util.Preconditions;
 import org.apache.commons.io.IOUtils;
@@ -37,7 +40,9 @@ import org.duniter.core.service.CryptoService;
 import org.duniter.core.util.StringUtils;
 import org.duniter.elasticsearch.PluginSettings;
 import org.duniter.elasticsearch.client.Duniter4jClient;
+import org.duniter.elasticsearch.exception.DuniterElasticsearchException;
 import org.duniter.elasticsearch.exception.InvalidFormatException;
+import org.duniter.elasticsearch.exception.InvalidSignatureException;
 import org.duniter.elasticsearch.model.SynchroResult;
 import org.duniter.elasticsearch.service.AbstractService;
 import org.duniter.elasticsearch.service.ServiceLocator;
@@ -90,25 +95,18 @@ public abstract class AbstractSynchroService extends AbstractService {
                                       String fromIndex, String fromType,
                                       String toIndex, String toType,
                                       long sinceTime) {
-        Preconditions.checkNotNull(result);
-        Preconditions.checkNotNull(peer);
-        Preconditions.checkNotNull(fromIndex);
-        Preconditions.checkNotNull(fromType);
-        Preconditions.checkNotNull(toIndex);
-        Preconditions.checkNotNull(toType);
-
         return doImportChanges(result, peer, fromIndex, fromType, toIndex, toType, Record.PROPERTY_ISSUER, Record.PROPERTY_TIME, sinceTime);
     }
 
     protected long importChanges(SynchroResult result, Peer peer, String index, String type, long sinceTime) {
-        Preconditions.checkNotNull(result);
-        Preconditions.checkNotNull(peer);
-        Preconditions.checkNotNull(index);
-        Preconditions.checkNotNull(type);
-
         return doImportChanges(result, peer, index, type, index, type, Record.PROPERTY_ISSUER, Record.PROPERTY_TIME, sinceTime);
     }
 
+    protected long importChanges(SynchroResult result, Peer peer, String index, String type,
+                                 String issuerFieldName, String versionFieldName, long sinceTime) {
+        return doImportChanges(result, peer, index, type, index, type, issuerFieldName, versionFieldName, sinceTime);
+    }
+
     /* -- private methods -- */
 
     private long doImportChanges(SynchroResult result,
@@ -116,7 +114,14 @@ public abstract class AbstractSynchroService extends AbstractService {
                                  String fromIndex, String fromType,
                                  String toIndex, String toType,
                                  String issuerFieldName, String versionFieldName, long sinceTime) {
-
+        Preconditions.checkNotNull(result);
+        Preconditions.checkNotNull(peer);
+        Preconditions.checkNotNull(fromIndex);
+        Preconditions.checkNotNull(fromType);
+        Preconditions.checkNotNull(toIndex);
+        Preconditions.checkNotNull(toType);
+        Preconditions.checkNotNull(issuerFieldName);
+        Preconditions.checkNotNull(versionFieldName);
 
         long offset = 0;
         int size = pluginSettings.getIndexBulkSize() / 10;
@@ -177,8 +182,8 @@ public abstract class AbstractSynchroService extends AbstractService {
             HttpPost httpPost = new HttpPost(httpService.getPath(peer, fromIndex, fromType, "_search"));
             httpPost.setHeader("Content-Type", "application/json;charset=UTF-8");
             httpPost.setEntity(new ByteArrayEntity(bos.bytes().array()));
-            if (logger.isDebugEnabled()) {
-                logger.debug(String.format("[%s] [%s/%s] Sending POST request: %s", peer, fromIndex, fromType, new String(bos.bytes().array())));
+            if (logger.isTraceEnabled()) {
+                logger.trace(String.format("[%s] [%s/%s] Sending POST request: %s", peer, fromIndex, fromType, new String(bos.bytes().array())));
             }
             // Parse response
             node = httpService.executeRequest(httpPost, JsonNode.class, String.class);
@@ -190,6 +195,9 @@ public abstract class AbstractSynchroService extends AbstractService {
         catch(TechnicalException e) {
             throw new TechnicalException("Unable to parse search response", e);
         }
+        catch(Exception e) {
+            throw new TechnicalException("Unable to parse search response", e);
+        }
 
         node = node.get("hits");
         int total = node == null ? 0 : node.get("total").asInt(0);
@@ -203,6 +211,7 @@ public abstract class AbstractSynchroService extends AbstractService {
 
         long insertHits = 0;
         long updateHits = 0;
+        long invalidSignatureHits = 0;
 
         if (offset < total) {
 
@@ -233,13 +242,22 @@ public abstract class AbstractSynchroService extends AbstractService {
 
                     // Insert (new doc)
                     if (doInsert) {
-                        String json = source.toString();
-                        //readAndVerifyIssuerSignature(json, source);
+
                         if (debug) {
-                            logger.trace(String.format("[%s] [%s/%s] insert _id=%s\n%s", peer, toIndex, toType, id, json));
+                            logger.trace(String.format("[%s] [%s/%s] insert _id=%s\n%s", peer, toIndex, toType, id, source.toString()));
+                        }
+
+                        // TODO: found why some user/profile document failed !
+                        // Il semble que le format JSON ne soit pas le même que celui qui a été signé
+                        try {
+                            readAndVerifyIssuerSignature(source, issuerFieldName);
+                        } catch(InvalidSignatureException e) {
+                            invalidSignatureHits++;
+                            logger.warn(String.format("[%s] [%s/%s/%s] %s.\n%s", peer, toIndex, toType, id, e.getMessage(), source.toString()));
                         }
+
                         bulkRequest.add(client.prepareIndex(toIndex, toType, id)
-                                .setSource(json.getBytes())
+                                .setSource(objectMapper.writeValueAsBytes(source))
                         );
                         insertHits++;
                     }
@@ -258,26 +276,38 @@ public abstract class AbstractSynchroService extends AbstractService {
                         boolean doUpdate = (existingVersion == null || version > existingVersion.longValue());
 
                         if (doUpdate) {
-                            String json = source.toString();
-                            //readAndVerifyIssuerSignature(json, source);
                             if (debug) {
-                                logger.trace(String.format("[%s] [%s/%s] update _id=%s\n%s", peer, toIndex, toType, id, json));
+                                logger.trace(String.format("[%s] [%s/%s] update _id=%s\n%s", peer, toIndex, toType, id, source.toString()));
+                            }
+
+                            // TODO: found why some user/profile document failed !
+                            // Il semble que le format JSON ne soit pas le même que celui qui a été signé
+                            try {
+                                readAndVerifyIssuerSignature(source, issuerFieldName);
+                            } catch(InvalidSignatureException e) {
+                                invalidSignatureHits++;
+                                logger.warn(String.format("[%s] [%s/%s/%s] %s.\n%s", peer, toIndex, toType, id, e.getMessage(), source.toString()));
                             }
+
                             bulkRequest.add(client.prepareIndex(toIndex, toType, id)
-                                    .setSource(json.getBytes()));
+                                    .setSource(objectMapper.writeValueAsBytes(source)));
 
                             updateHits++;
                         }
                     }
 
-                } catch (InvalidFormatException e) {
-                    if (debug) {
-                        logger.debug(String.format("[%s] [%s/%s] %s. Skipping.", peer, toIndex, toType, e.getMessage()));
+                }
+                catch (DuniterElasticsearchException e) {
+                    if (logger.isDebugEnabled()) {
+                        logger.warn(String.format("[%s] [%s/%s/%s] %s. Skipping.\n%s", peer, toIndex, toType, id, e.getMessage(), source.toString()));
+                    }
+                    else {
+                        logger.warn(String.format("[%s] [%s/%s/%s] %s. Skipping.", peer, toIndex, toType, id, e.getMessage()));
                     }
                     // Skipping document (continue)
                 }
                 catch (Exception e) {
-                    logger.warn(String.format("[%s] [%s/%s] %s. Skipping.", peer, toIndex, toType, e.getMessage()), e);
+                    logger.error(String.format("[%s] [%s/%s/%s] %s. Skipping.", peer, toIndex, toType, id, e.getMessage()), e);
                     // Skipping document (continue)
                 }
             }
@@ -308,12 +338,8 @@ public abstract class AbstractSynchroService extends AbstractService {
         // update result stats
         result.addInserts(toIndex, toType, insertHits);
         result.addUpdates(toIndex, toType, updateHits);
+        result.addInvalidSignatures(toIndex, toType, invalidSignatureHits);
 
         return counter;
-
-        /*}
-        finally {
-            //IOUtils.closeQuietly(response);
-        }*/
     }
 }
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/model/Message.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/model/Message.java
index 5ac4d34ff439a27309a6f756e72b233098a871d3..04f2e4c4df7b1100e91cf29dd52556d989b62cd0 100644
--- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/model/Message.java
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/model/Message.java
@@ -41,9 +41,10 @@ public class Message extends Record {
 
 
     public static final String PROPERTY_NONCE="nonce";
+    public static final String PROPERTY_TITLE="title";
     public static final String PROPERTY_CONTENT="content";
     public static final String PROPERTY_RECIPIENT="recipient";
-    public static final String PROPERTY_READ_SIGNATURE="readSignature";
+    public static final String PROPERTY_READ_SIGNATURE="read_signature";
 
     private String nonce;
 
@@ -72,12 +73,12 @@ public class Message extends Record {
         this.recipient = recipient;
     }
 
-    @JsonGetter("read_signature")
+    @JsonGetter(PROPERTY_READ_SIGNATURE)
     public String getReadSignature() {
         return readSignature;
     }
 
-    @JsonSetter("read_signature")
+    @JsonSetter(PROPERTY_READ_SIGNATURE)
     public void setReadSignature(String readSignature) {
         this.readSignature = readSignature;
     }
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/HistoryService.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/HistoryService.java
index e2004b8a5a11d5bf93e8db584b19a7b6420c1c66..fc4b3ce7b2d45e62f0774c3ae6ac5029bda2fc28 100644
--- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/HistoryService.java
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/HistoryService.java
@@ -26,20 +26,18 @@ package org.duniter.elasticsearch.user.service;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.JsonNode;
 import org.duniter.core.client.model.elasticsearch.DeleteRecord;
-import org.duniter.core.client.model.elasticsearch.MessageRecord;
 import org.duniter.core.exception.TechnicalException;
 import org.duniter.core.service.CryptoService;
 import org.duniter.elasticsearch.client.Duniter4jClient;
 import org.duniter.elasticsearch.exception.NotFoundException;
-import org.duniter.elasticsearch.user.service.AbstractService;
 import org.duniter.elasticsearch.user.PluginSettings;
+import org.duniter.elasticsearch.user.model.Message;
 import org.duniter.elasticsearch.user.model.UserEvent;
 import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder;
 import org.elasticsearch.action.index.IndexResponse;
 import org.elasticsearch.action.search.SearchRequestBuilder;
 import org.elasticsearch.action.search.SearchResponse;
 import org.elasticsearch.action.search.SearchType;
-import org.elasticsearch.client.Client;
 import org.elasticsearch.common.inject.Inject;
 import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.common.xcontent.XContentBuilder;
@@ -125,16 +123,16 @@ public class HistoryService extends AbstractService {
             throw new NotFoundException(String.format("Index [%s] not exists.", index));
         }
 
-        // Special case for message: check if deletion issuer is the message recipient
+        // Message: check if deletion issuer is the message recipient
         if (MessageService.INDEX.equals(index) && MessageService.INBOX_TYPE.equals(type)) {
-            client.checkSameDocumentField(index, type, id, MessageRecord.PROPERTY_RECIPIENT, issuer);
+            client.checkSameDocumentField(index, type, id, Message.PROPERTY_RECIPIENT, issuer);
         }
-        // Special case for invitation: check if deletion issuer is the invitation recipient
+        // Invitation: check if deletion issuer is the invitation recipient
         else if (UserInvitationService.INDEX.equals(index)) {
-            client.checkSameDocumentField(index, type, id, MessageRecord.PROPERTY_RECIPIENT, issuer);
+            client.checkSameDocumentField(index, type, id, Message.PROPERTY_RECIPIENT, issuer);
         }
         else {
-            // Check document issuer
+            // Check same document issuer
             client.checkSameDocumentIssuer(index, type, id, issuer);
         }
 
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/SynchroService.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/SynchroService.java
index 1c32e078c86b173e534eaa036b8fd160e9bab341..0fc9540733629281c6c8a252714a691ab71d1bfe 100644
--- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/SynchroService.java
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/SynchroService.java
@@ -23,6 +23,7 @@ package org.duniter.elasticsearch.user.service;
  */
 
 import org.duniter.core.client.model.elasticsearch.Protocol;
+import org.duniter.core.client.model.elasticsearch.Record;
 import org.duniter.core.client.model.local.Peer;
 import org.duniter.core.service.CryptoService;
 import org.duniter.elasticsearch.client.Duniter4jClient;
@@ -31,6 +32,7 @@ import org.duniter.elasticsearch.model.SynchroResult;
 import org.duniter.elasticsearch.service.ServiceLocator;
 import org.duniter.elasticsearch.service.AbstractSynchroService;
 import org.duniter.elasticsearch.threadpool.ThreadPool;
+import org.duniter.elasticsearch.user.model.Message;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.common.inject.Inject;
 
@@ -90,8 +92,8 @@ public class SynchroService extends AbstractSynchroService {
                 MessageService.INDEX, MessageService.INBOX_TYPE,
                 sinceTime);
 
-        importChanges(result, peer, MessageService.INDEX, MessageService.INBOX_TYPE,  sinceTime);
-        importChanges(result, peer, MessageService.INDEX, MessageService.OUTBOX_TYPE,  sinceTime);
+        importChanges(result, peer, MessageService.INDEX, MessageService.INBOX_TYPE, sinceTime);
+        importChanges(result, peer, MessageService.INDEX, MessageService.OUTBOX_TYPE, sinceTime);
     }
 
     protected void importGroupChanges(SynchroResult result, Peer peer, long sinceTime) {