diff --git a/duniter4j-core-client/src/main/java/org/duniter/core/client/dao/PeerDao.java b/duniter4j-core-client/src/main/java/org/duniter/core/client/dao/PeerDao.java
index 55d28e88bf4830f2fed7baf141ae14faa9b6c313..6e4ee26b1c244aa72f47b4b829e44ae50b952704 100644
--- a/duniter4j-core-client/src/main/java/org/duniter/core/client/dao/PeerDao.java
+++ b/duniter4j-core-client/src/main/java/org/duniter/core/client/dao/PeerDao.java
@@ -44,7 +44,7 @@ public interface PeerDao extends EntityDao<String, Peer> {
 
     Long getMaxLastUpTime(String currencyId);
 
-    void updatePeersAsDown(String currencyId, long maxUpTime);
+    void updatePeersAsDown(String currencyId, long upTimeLimitInSec);
 
     boolean hasPeersUpWithApi(String currencyId, Set<EndpointApi> api);
 }
diff --git a/duniter4j-core-client/src/main/java/org/duniter/core/client/dao/mem/MemoryPeerDaoImpl.java b/duniter4j-core-client/src/main/java/org/duniter/core/client/dao/mem/MemoryPeerDaoImpl.java
index f9a3f1407fc274d8b49da029c1b6956aeea77636..5e85b4074c04461173275a55d07b5b63fd6d0f0d 100644
--- a/duniter4j-core-client/src/main/java/org/duniter/core/client/dao/mem/MemoryPeerDaoImpl.java
+++ b/duniter4j-core-client/src/main/java/org/duniter/core/client/dao/mem/MemoryPeerDaoImpl.java
@@ -130,13 +130,11 @@ public class MemoryPeerDaoImpl implements PeerDao {
     }
 
     @Override
-    public void updatePeersAsDown(String currencyId, long upTimeLimit) {
+    public void updatePeersAsDown(String currencyId, long upTimeLimitInSec) {
 
         getPeersByCurrencyId(currencyId).stream()
-                .filter(peer -> peer.getStats() != null && peer.getStats().getLastUpTime() <= upTimeLimit)
-                .forEach(peer -> {
-                    peer.getStats().setStatus(Peer.PeerStatus.DOWN);
-                });
+                .filter(peer -> peer.getStats() != null && peer.getStats().getLastUpTime() <= upTimeLimitInSec)
+                .forEach(peer -> peer.getStats().setStatus(Peer.PeerStatus.DOWN));
 
     }
 
diff --git a/duniter4j-core-client/src/main/java/org/duniter/core/client/model/bma/Endpoints.java b/duniter4j-core-client/src/main/java/org/duniter/core/client/model/bma/Endpoints.java
index f994af40c3c8345ae1e5073aa00406fdbcd1f05f..f96d15baaf50f46796454ea07c865dd030f2c4c9 100644
--- a/duniter4j-core-client/src/main/java/org/duniter/core/client/model/bma/Endpoints.java
+++ b/duniter4j-core-client/src/main/java/org/duniter/core/client/model/bma/Endpoints.java
@@ -34,10 +34,10 @@ import java.util.regex.Pattern;
  */
 public class Endpoints {
 
-    public static final String EP_END_REGEXP = "(?:[ ]+([a-z0-9-_]+[.][a-z0-9-_.]*))?(?:[ ]+([0-9.]+))?(?:[ ]+([0-9a-f:]+))?(?:[ ]+([0-9]+))(?:[ ]+(/[^/]+))?$";
+    public static final String EP_END_REGEXP = "(?: ([a-z_][a-z0-9-_.ÄŸÄž]*))?(?: ([0-9.]+))?(?: ([0-9a-f:]+))?(?: ([0-9]+))(?: (/[^/]+))?$";
     public static final String BMA_API_REGEXP = "^BASIC_MERKLED_API" + EP_END_REGEXP;
     public static final String BMAS_API_REGEXP = "^BMAS" + EP_END_REGEXP;
-    public static final String WS2P_API_REGEXP = "^WS2P[ ]+([a-z0-9]+)[ ]+" + EP_END_REGEXP;
+    public static final String WS2P_API_REGEXP = "^WS2P ([a-f0-9]{8})" + EP_END_REGEXP;
     public static final String OTHER_API_REGEXP = "^([A-Z_-]+)" + EP_END_REGEXP;
 
     private static Pattern bmaPattern = Pattern.compile(BMA_API_REGEXP);
@@ -104,9 +104,9 @@ public class Endpoints {
                     endpoint.ipv4 = word;
                 } else if (InetAddressUtils.isIPv6Address(word)) {
                     endpoint.ipv6 = word;
-                } else if (i == matcher.groupCount() || (i == matcher.groupCount() -1) && word.matches("\\d+")){
+                } else if ((i == matcher.groupCount() || i == matcher.groupCount() -1) && word.matches("^\\d+$")){
                     endpoint.port = Integer.parseInt(word);
-                } else if (word.startsWith("/")) {
+                } else if (i == matcher.groupCount() && word.startsWith("/")) {
                     endpoint.path = word;
                 } else {
                     endpoint.dns = word;
diff --git a/duniter4j-core-client/src/main/java/org/duniter/core/client/model/bma/NetworkPeerings.java b/duniter4j-core-client/src/main/java/org/duniter/core/client/model/bma/NetworkPeerings.java
new file mode 100644
index 0000000000000000000000000000000000000000..07a19749783467c0cfc2d49e98b4745bda23437a
--- /dev/null
+++ b/duniter4j-core-client/src/main/java/org/duniter/core/client/model/bma/NetworkPeerings.java
@@ -0,0 +1,110 @@
+package org.duniter.core.client.model.bma;
+
+/*
+ * #%L
+ * Duniter4j :: Core Client API
+ * %%
+ * Copyright (C) 2014 - 2017 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%
+ */
+
+import com.google.common.collect.Lists;
+import org.duniter.core.util.Preconditions;
+import org.duniter.core.util.StringUtils;
+import org.duniter.core.util.http.InetAddressUtils;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.regex.Matcher;
+
+/**
+ * Created by blavenie on 07/12/16.
+ */
+public class NetworkPeerings {
+
+    private NetworkPeerings() {
+       // helper class
+    }
+
+    public static NetworkPeering parse(String document) throws IOException {
+        Preconditions.checkNotNull(document);
+
+        try {
+
+            NetworkPeering result = new NetworkPeering();
+
+            String[] lines = document.trim().split("\n");
+
+            Preconditions.checkArgument(lines.length >= 7, "Invalid document");
+
+            int i = 0;
+            String line;
+            for (; i < 5; ) {
+                line = lines[i++].trim();
+                if (line.startsWith("Version: ")) {
+                    result.setVersion(line.substring(9));
+                } else if (line.startsWith("Type: ")) {
+                    String type = line.substring(6);
+                    Preconditions.checkArgument(Protocol.TYPE_PEER.equals(type), "Invalid type found in document. Expected: " + Protocol.TYPE_PEER);
+                } else if (line.startsWith("Currency: ")) {
+                    result.setCurrency(line.substring(10));
+                } else if (line.startsWith("PublicKey: ")) {
+                    result.setPubkey(line.substring(11));
+                } else if (line.startsWith("Block: ")) {
+                    result.setBlock(line.substring(7));
+                }
+            }
+            line = lines[i++].trim();
+            Preconditions.checkArgument("Endpoints:".equals(line), "Invalid document format. Missing line 'Endpoint:' !");
+            List<NetworkPeering.Endpoint> endpoints = Lists.newArrayList();
+            for (; i < lines.length - 1; ) {
+                line = lines[i++].trim();
+                NetworkPeering.Endpoint ep = Endpoints.parse(line);
+                Preconditions.checkNotNull(ep, "Unaparsable endpoint: " + line);
+                endpoints.add(ep);
+            }
+            result.setEndpoints(endpoints.toArray(new NetworkPeering.Endpoint[endpoints.size()]));
+
+            result.setSignature(lines[lines.length - 1]);
+
+            return result;
+        }
+        catch(Exception e) {
+            throw new IOException(e.getMessage());
+        }
+    }
+
+    public static void parseDefaultFormatEndPoint(Matcher matcher, NetworkPeering.Endpoint endpoint, int startGroup) {
+        for(int i=startGroup; i<=matcher.groupCount(); i++) {
+            String word = matcher.group(i);
+
+            if (StringUtils.isNotBlank(word)) {
+                if (InetAddressUtils.isIPv4Address(word)) {
+                    endpoint.ipv4 = word;
+                } else if (InetAddressUtils.isIPv6Address(word)) {
+                    endpoint.ipv6 = word;
+                } else if (i == matcher.groupCount() || (i == matcher.groupCount() -1) && word.matches("\\d+")){
+                    endpoint.port = Integer.parseInt(word);
+                } else if (word.startsWith("/")) {
+                    endpoint.path = word;
+                } else {
+                    endpoint.dns = word;
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/duniter4j-core-client/src/main/java/org/duniter/core/client/service/local/PeerServiceImpl.java b/duniter4j-core-client/src/main/java/org/duniter/core/client/service/local/PeerServiceImpl.java
index 4b12796e3b87c515ebdae695cbcd1d7970c2bc77..46873230fc2b4df211e40ab2d93baa00715ea3fe 100644
--- a/duniter4j-core-client/src/main/java/org/duniter/core/client/service/local/PeerServiceImpl.java
+++ b/duniter4j-core-client/src/main/java/org/duniter/core/client/service/local/PeerServiceImpl.java
@@ -195,25 +195,27 @@ public class PeerServiceImpl implements PeerService, InitializingBean {
     public void save(String currencyId, List<Peer> peers, boolean isFullUpList) {
 
         int peerDownTimeoutMs = config.getPeerUpMaxAge();
-        final long nowInSec = System.currentTimeMillis()/1000;
+        final long now = System.currentTimeMillis();
 
         if (CollectionUtils.isNotEmpty(peers)) {
             if (log.isDebugEnabled()) {
                 log.debug(String.format("[%s] Updating peers (%s endpoints found)", currencyId, peers.size()));
             }
 
-            // On each UP peers: set last UP time
-            peers.stream().map(Peer::getStats)
-                    .filter(Peer.Stats::isReacheable)
-                    .forEach(stats -> stats.setLastUpTime(nowInSec));
-
-            peers.forEach(this::save);
+            peers.forEach(peer -> {
+                // On each UP peers: set last UP time
+                if (peer.getStats() != null && peer.getStats().isReacheable()) {
+                    peer.getStats().setLastUpTime(now / 1000);
+                }
+                // Save
+                save(peer);
+            });
         }
 
         // Mark old peers as DOWN
         if (isFullUpList && peerDownTimeoutMs > 0) {
-            Date oldDate = new Date(nowInSec * 1000 - peerDownTimeoutMs);
-            peerDao.updatePeersAsDown(currencyId, oldDate.getTime() / 1000);
+            long maxUpTimeInMs = now - peerDownTimeoutMs;
+            peerDao.updatePeersAsDown(currencyId, maxUpTimeInMs / 1000);
         }
     }
 
diff --git a/duniter4j-core-client/src/test/java/org/duniter/core/client/model/bma/EndpointsTest.java b/duniter4j-core-client/src/test/java/org/duniter/core/client/model/bma/EndpointsTest.java
index d86ec9563618f36ed8afc3e4db06222e8189db54..5bebfa2e3895283849f55812e31565522c2fbe4e 100644
--- a/duniter4j-core-client/src/test/java/org/duniter/core/client/model/bma/EndpointsTest.java
+++ b/duniter4j-core-client/src/test/java/org/duniter/core/client/model/bma/EndpointsTest.java
@@ -8,10 +8,40 @@ public class EndpointsTest {
     @Test
     public void parse() throws Exception {
 
-        NetworkPeering.Endpoint ep = Endpoints.parse("GCHANGE_API data.gchange.fr 443");
+        NetworkPeering.Endpoint ep = Endpoints.parse("BASIC_MERKLED_API g1.duniter.fr 81.81.81.81 80");
         Assert.assertNotNull(ep);
+        Assert.assertEquals(EndpointApi.BASIC_MERKLED_API, ep.api);
+        Assert.assertEquals("g1.duniter.fr", ep.dns);
+        Assert.assertEquals("81.81.81.81", ep.ipv4);
+        Assert.assertNotNull(ep.port);
+        Assert.assertEquals(80, ep.port.intValue());
+        Assert.assertNull(ep.id);
+        Assert.assertNull(ep.path);
 
+        ep = Endpoints.parse("BMAS g1.duniter.fr 443");
+        Assert.assertNotNull(ep);
+        Assert.assertEquals(EndpointApi.BMAS, ep.api);
+        Assert.assertEquals("g1.duniter.fr", ep.dns);
+        Assert.assertNotNull(ep.port);
+        Assert.assertEquals(443, ep.port.intValue());
+        Assert.assertNull(ep.id);
+        Assert.assertNull(ep.path);
+
+        ep = Endpoints.parse("WS2P fb17fcd4 g1.duniter.fr 443 /ws2p");
+        Assert.assertNotNull(ep);
+        Assert.assertNotNull(ep.id);
+        Assert.assertNotNull(ep.path);
+        Assert.assertEquals(EndpointApi.WS2P, ep.api);
+        Assert.assertEquals("g1.duniter.fr", ep.dns);
+        Assert.assertNotNull(ep.port);
+        Assert.assertEquals(443, ep.port.intValue());
+
+        ep = Endpoints.parse("GCHANGE_API data.gchange.fr 443");
+        Assert.assertNotNull(ep);
         Assert.assertEquals(ep.api, EndpointApi.GCHANGE_API);
+        Assert.assertNull(ep.id);
+        Assert.assertNull(ep.path);
+
     }
 
 }
diff --git a/duniter4j-core-client/src/test/java/org/duniter/core/client/model/bma/NetworkPeeringsTest.java b/duniter4j-core-client/src/test/java/org/duniter/core/client/model/bma/NetworkPeeringsTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..c1217be30a3534e2be363031234add08c15a4d7a
--- /dev/null
+++ b/duniter4j-core-client/src/test/java/org/duniter/core/client/model/bma/NetworkPeeringsTest.java
@@ -0,0 +1,24 @@
+package org.duniter.core.client.model.bma;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class NetworkPeeringsTest {
+
+    @Test
+    public void parse() throws Exception {
+
+        String doc = "Version: 10\nType: Peer\nCurrency: g1\nPublicKey: 38MEAZN68Pz1DTvT3tqgxx4yQP6snJCQhPqEFxbDk4aE\nBlock: 162694-0000067CAF81B13E4BD7AE72A06F9981D80EB957E4D46C23A67B4DF734E258ED\nEndpoints:\nBMAS g1.duniter.fr 443\nES_CORE_API g1.data.duniter.fr 443\nES_USER_API g1.data.duniter.fr 443\nES_SUBSCRIPTION_API g1.data.duniter.fr 443\nBASIC_MERKLED_API g1.duniter.fr 80\nWS2P fb17fcd4 g1.duniter.fr 443 /ws2p\nU+obPZqDQ3WDDclyCrOhT80Dq/8sPZp0ng+hj4THPAaxKNQwc9cijNnfvwzSsQ/hZBJpZ6+Gzrzso+zprhNICQ==\n";
+
+        NetworkPeering peering = NetworkPeerings.parse(doc);
+        Assert.assertNotNull(peering);
+
+        Assert.assertEquals("g1", peering.getCurrency());
+        Assert.assertEquals("10", peering.getVersion());
+        Assert.assertEquals("38MEAZN68Pz1DTvT3tqgxx4yQP6snJCQhPqEFxbDk4aE", peering.getPubkey());
+        Assert.assertEquals("162694-0000067CAF81B13E4BD7AE72A06F9981D80EB957E4D46C23A67B4DF734E258ED", peering.getBlock());
+        Assert.assertEquals("U+obPZqDQ3WDDclyCrOhT80Dq/8sPZp0ng+hj4THPAaxKNQwc9cijNnfvwzSsQ/hZBJpZ6+Gzrzso+zprhNICQ==", peering.getSignature());
+        Assert.assertEquals(6, peering.getEndpoints().length);
+    }
+
+}