diff --git a/duniterpy/__init__.py b/duniterpy/__init__.py
index 91b5f3ceb47f78bc6ab0e1fe21e50e42536b225e..c2952a61267c1d241325bcea04039666862b1c55 100644
--- a/duniterpy/__init__.py
+++ b/duniterpy/__init__.py
@@ -16,7 +16,6 @@
 # Caner Candan <caner@candan.fr>, http://caner.candan.fr
 #
 
-MANAGED_API=["BASIC_MERKLED_API", "BMAS", "WS2P"]
 
 __author__      = 'Caner Candan & inso & vit'
 __version__     = '0.42.0'
diff --git a/duniterpy/documents/constants.py b/duniterpy/documents/constants.py
index 994009013d489b308cf15748c1efbe082904f76e..86c8127316c9f2fea27e0e4499dd120c27499bf6 100644
--- a/duniterpy/documents/constants.py
+++ b/duniterpy/documents/constants.py
@@ -11,5 +11,7 @@ block_uid_regex = "{block_id_regex}-{block_hash_regex}".format(block_id_regex=bl
 conditions_regex = "(&&|\|\|| |[()]|(SIG\({pubkey_regex}\)|(XHX\({hash_regex}\))))*"\
     .format(pubkey_regex=pubkey_regex, hash_regex=hash_regex)
 ipv4_regex = '(?:(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])'
-ipv6_regex = '(?:(?:[0-9A-Fa-f]{1,4}:){6}(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|(?:(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))|::(?:[0-9A-Fa-f]{1,4}:){5}(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|(?:(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))|(?:[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){4}(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|(?:(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))|(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){3}(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|(?:(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))|(?:(?:[0-9A-Fa-f]{1,4}:){,2}[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){2}(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|(?:(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))|(?:(?:[0-9A-Fa-f]{1,4}:){,3}[0-9A-Fa-f]{1,4})?::[0-9A-Fa-f]{1,4}:(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|(?:(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))|(?:(?:[0-9A-Fa-f]{1,4}:){,4}[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|(?:(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))|(?:(?:[0-9A-Fa-f]{1,4}:){,5}[0-9A-Fa-f]{1,4})?::[0-9A-Fa-f]{1,4}|(?:(?:[0-9A-Fa-f]{1,4}:){,6}[0-9A-Fa-f]{1,4})?::)'
+ipv6_regex = '(?:(?:[0-9A-Fa-f]{1,4}:){6}(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|(?:(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))|::(?:[0-9A-Fa-f]{1,4}:){5}(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|(?:(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))|(?:[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){4}(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|(?:(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))|(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){3}(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|(?:(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))|(?:(?:[0-9A-Fa-f]{1,4}:){,2}[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){2}(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|(?:(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))|(?:(?:[0-9A-Fa-f]{1,4}:){,3}[0-9A-Fa-f]{1,4})?::[0-9A-Fa-f]{1,4}:(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|(?:(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))|(?:(?:[0-9A-Fa-f]{1,4}:){,4}[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|(?:(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))|(?:(?:[0-9A-Fa-f]{1,4}:){,5}[0-9A-Fa-f]{1,4})?::[0-9A-Fa-f]{1,4}|(?:(?:[0-9A-Fa-f]{1,4}:){,6}[0-9A-Fa-f]{1,4})?::)(?:%.+)?'
 ws2pid_regex = "[0-9a-f]{8}"
+host_regex = "[a-z0-9-_.]*(?:.[a-zA-Z])?"
+path_regex = "[/\w \.-]*/?"
diff --git a/duniterpy/documents/peer.py b/duniterpy/documents/peer.py
index 0793e7fb8c2a4ffa4d49c22c82279c06cc5147b0..2b548c6fc621277bf1a682fc607507f96c364625 100644
--- a/duniterpy/documents/peer.py
+++ b/duniterpy/documents/peer.py
@@ -3,8 +3,7 @@ import re
 from ..api.bma import ConnectionHandler
 from .document import Document, MalformedDocumentError
 from . import BlockUID
-from .. import MANAGED_API
-from .constants import block_hash_regex, pubkey_regex, ipv4_regex, ipv6_regex, ws2pid_regex
+from .constants import block_hash_regex, pubkey_regex, ipv4_regex, ipv6_regex, ws2pid_regex, host_regex, path_regex
 
 
 class Peer(Document):
@@ -99,14 +98,9 @@ def endpoint(value):
     elif isinstance(value, WS2PEndpoint):
         return value
     elif isinstance(value, str):
-        for api in MANAGED_API:
-            if value.startswith(api):
-                if api == "BASIC_MERKLED_API":
-                    return BMAEndpoint.from_inline(value)
-                if api == "BMAS":
-                    return SecuredBMAEndpoint.from_inline(value)
-                if api == "WS2P":
-                    return WS2PEndpoint.from_inline(value)
+        for api, cls in MANAGED_API.items():
+            if value.startswith(api + " "):
+                return cls.from_inline(value)
         return UnknownEndpoint.from_inline(value)
     else:
         raise TypeError("Cannot convert {0} to endpoint".format(value))
@@ -141,7 +135,7 @@ class UnknownEndpoint(Endpoint):
             properties = inline.split()[1:]
             return cls(api, properties)
         except IndexError:
-            return None
+            raise MalformedDocumentError(inline)
 
     def inline(self):
         doc = self.api
@@ -163,9 +157,10 @@ class UnknownEndpoint(Endpoint):
 
 
 class BMAEndpoint(Endpoint):
-    API = "BMA"
-    re_inline = re.compile('^BASIC_MERKLED_API(?: ([a-z0-9-_.]*(?:.[a-zA-Z])))?(?: ({ipv4_regex}))?(?: ({ipv6_regex}))?(?: ([0-9]+))$'.format(ipv4_regex=ipv4_regex,
-                                                                                                                                              ipv6_regex=ipv6_regex))
+    API = "BASIC_MERKLED_API"
+    re_inline = re.compile('^BASIC_MERKLED_API(?: ({host_regex}))?(?: ({ipv4_regex}))?(?: ({ipv6_regex}))?(?: ([0-9]+))$'.format(host_regex=host_regex,
+                                                                                                                                 ipv4_regex=ipv4_regex,
+                                                                                                                                 ipv6_regex=ipv6_regex))
 
     def __init__(self, server, ipv4, ipv6, port):
         self.server = server
@@ -178,7 +173,7 @@ class BMAEndpoint(Endpoint):
         m = BMAEndpoint.re_inline.match(inline)
         str_re = BMAEndpoint.re_inline.pattern
         if m is None:
-            raise MalformedDocumentError("BMAEndpoint")
+            raise MalformedDocumentError(BMAEndpoint.API)
         server = m.group(1)
         ipv4 = m.group(2)
         ipv6 = m.group(3)
@@ -186,7 +181,7 @@ class BMAEndpoint(Endpoint):
         return cls(server, ipv4, ipv6, port)
 
     def inline(self):
-        return "BASIC_MERKLED_API{DNS}{IPv4}{IPv6}{PORT}" \
+        return BMAEndpoint.API + "{DNS}{IPv4}{IPv6}{PORT}" \
                     .format(DNS=(" {0}".format(self.server) if self.server else ""),
                             IPv4=(" {0}".format(self.ipv4) if self.ipv4 else ""),
                             IPv6=(" {0}".format(self.ipv6) if self.ipv6 else ""),
@@ -221,8 +216,10 @@ class BMAEndpoint(Endpoint):
 
 class SecuredBMAEndpoint(BMAEndpoint):
     API = "BMAS"
-    re_inline = re.compile('^BMAS(?: ([a-z0-9-_.]*(?:.[a-zA-Z])))?(?: ({ipv4_regex}))?(?: ({ipv6_regex}))? ([0-9]+)(?: ([/\w \.-]*)/?)?$'.format(ipv4_regex=ipv4_regex,
-                                                                                                                                                 ipv6_regex=ipv6_regex))
+    re_inline = re.compile('^BMAS(?: ({host_regex}))?(?: ({ipv4_regex}))?(?: ({ipv6_regex}))? ([0-9]+)(?: ({path_regex}))?$'.format(host_regex=host_regex,
+                                                                                                                                   ipv4_regex=ipv4_regex,
+                                                                                                                                   ipv6_regex=ipv6_regex,
+                                                                                                                                   path_regex=path_regex))
 
     def __init__(self, server, ipv4, ipv6, port, path):
         super().__init__(server, ipv4, ipv6, port)
@@ -232,7 +229,7 @@ class SecuredBMAEndpoint(BMAEndpoint):
     def from_inline(cls, inline):
         m = SecuredBMAEndpoint.re_inline.match(inline)
         if m is None:
-            raise MalformedDocumentError("BMAS")
+            raise MalformedDocumentError(SecuredBMAEndpoint.API)
         server = m.group(1)
         ipv4 = m.group(2)
         ipv6 = m.group(3)
@@ -244,7 +241,7 @@ class SecuredBMAEndpoint(BMAEndpoint):
 
     def inline(self):
         inlined = [str(info) for info in (self.server, self.ipv4, self.ipv6, self.port, self.path) if info]
-        return "BMAS " + " ".join(inlined)
+        return SecuredBMAEndpoint.API + " " + " ".join(inlined)
 
     def conn_handler(self, session=None, proxy=None):
         """
@@ -263,28 +260,34 @@ class SecuredBMAEndpoint(BMAEndpoint):
 
 class WS2PEndpoint(Endpoint):
     API = "WS2P"
-    re_inline = re.compile('^WS2P ({ws2pid_regex}) ((?:[a-z0-9-_.]*(?:.[a-zA-Z]))|(?:{ipv4_regex})) ([0-9]+)?$'.format(ws2pid_regex=ws2pid_regex,
+    re_inline = re.compile('^WS2P ({ws2pid_regex}) ((?:{host_regex})|(?:{ipv4_regex})) ([0-9]+)?(?: ({path_regex}))?$'.format(ws2pid_regex=ws2pid_regex,
+                                                                                                                 host_regex=host_regex,
                                                                                                                  ipv4_regex=ipv4_regex,
-                                                                                                                 ipv6_regex=ipv6_regex))
+                                                                                                                 ipv6_regex=ipv6_regex,
+                                                                                                                 path_regex=path_regex))
 
-    def __init__(self, ws2pid, server, port):
+    def __init__(self, ws2pid, server, port, path):
         self.ws2pid = ws2pid
         self.server = server
         self.port = port
+        self.path = path
 
     @classmethod
     def from_inline(cls, inline):
         m = WS2PEndpoint.re_inline.match(inline)
         if m is None:
-            raise MalformedDocumentError("WS2P")
+            raise MalformedDocumentError(WS2PEndpoint.API)
         ws2pid = m.group(1)
         server = m.group(2)
         port = int(m.group(3))
-        return cls(ws2pid, server, port)
+        path = m.group(4)
+        if not path:
+            path = ""
+        return cls(ws2pid, server, port, path)
 
     def inline(self):
-        inlined = [str(info) for info in (self.ws2pid, self.server,self.port)]
-        return "WS2P " + " ".join(inlined)
+        inlined = [str(info) for info in (self.ws2pid, self.server, self.port, self.path) if info]
+        return WS2PEndpoint.API + " " + " ".join(inlined)
 
     def conn_handler(self, session=None, proxy=None):
         """
@@ -293,7 +296,7 @@ class WS2PEndpoint(Endpoint):
         :param aiohttp.ClientSession session: AIOHTTP client session instance
         :rtype: ConnectionHandler
         """
-        yield ConnectionHandler("https", "wss", self.server, self.port, "", proxy, session)
+        yield ConnectionHandler("https", "wss", self.server, self.port, self.path, proxy, session)
 
     def __str__(self):
         return self.inline()
@@ -301,9 +304,109 @@ class WS2PEndpoint(Endpoint):
     def __eq__(self, other):
         if isinstance(other, WS2PEndpoint):
             return self.server == other.server and self.ws2pid == other.ws2pid \
-                    and self.port == other.port
+                    and self.port == other.port and self.path == other.path
+        else:
+            return False
+
+    def __hash__(self):
+        return hash((self.ws2pid, self.server, self.port, self.path))
+
+
+class ESUserEndpoint(Endpoint):
+    API = "ES_USER_API"
+    re_inline = re.compile('^ES_USER_API ((?:{host_regex})|(?:{ipv4_regex})) ([0-9]+)$'.format(ws2pid_regex=ws2pid_regex,
+                                                                                             host_regex=host_regex,
+                                                                                             ipv4_regex=ipv4_regex))
+
+    def __init__(self, server, port):
+        self.server = server
+        self.port = port
+
+    @classmethod
+    def from_inline(cls, inline):
+        m = ESUserEndpoint.re_inline.match(inline)
+        if m is None:
+            raise MalformedDocumentError(ESUserEndpoint.API)
+        server = m.group(1)
+        port = int(m.group(2))
+        return cls(server, port)
+
+    def inline(self):
+        inlined = [str(info) for info in (self.server, self.port) if info]
+        return ESUserEndpoint.API + " " + " ".join(inlined)
+
+    def conn_handler(self, session=None, proxy=None):
+        """
+        Return connection handler instance for the endpoint
+
+        :param aiohttp.ClientSession session: AIOHTTP client session instance
+        :rtype: ConnectionHandler
+        """
+        yield ConnectionHandler("https", "wss", self.server, self.port, "", proxy, session)
+
+    def __str__(self):
+        return self.inline()
+
+    def __eq__(self, other):
+        if isinstance(other, ESUserEndpoint):
+            return self.server == other.server and self.port == other.port
         else:
             return False
 
     def __hash__(self):
-        return hash((self.ws2pid, self.server, self.port))
\ No newline at end of file
+        return hash((self.server, self.port))
+
+
+class ESSubscribtionEndpoint(Endpoint):
+    API = "ES_SUBSCRIPTION_API"
+    re_inline = re.compile('^ES_SUBSCRIPTION_API ((?:{host_regex})|(?:{ipv4_regex})) ([0-9]+)$'.format(ws2pid_regex=ws2pid_regex,
+                                                                                                      host_regex=host_regex,
+                                                                                                      ipv4_regex=ipv4_regex))
+
+    def __init__(self, server, port):
+        self.server = server
+        self.port = port
+
+    @classmethod
+    def from_inline(cls, inline):
+        m = ESSubscribtionEndpoint.re_inline.match(inline)
+        if m is None:
+            raise MalformedDocumentError(ESSubscribtionEndpoint.API)
+        server = m.group(1)
+        port = int(m.group(2))
+        return cls(server, port)
+
+    def inline(self):
+        inlined = [str(info) for info in (self.server, self.port) if info]
+        return ESSubscribtionEndpoint.API + " " + " ".join(inlined)
+
+    def conn_handler(self, session=None, proxy=None):
+        """
+        Return connection handler instance for the endpoint
+
+        :param aiohttp.ClientSession session: AIOHTTP client session instance
+        :rtype: ConnectionHandler
+        """
+        yield ConnectionHandler("https", "wss", self.server, self.port, "", proxy, session)
+
+    def __str__(self):
+        return self.inline()
+
+    def __eq__(self, other):
+        if isinstance(other, ESSubscribtionEndpoint):
+            return self.server == other.server and self.port == other.port
+        else:
+            return False
+
+    def __hash__(self):
+        return hash((ESSubscribtionEndpoint.API, self.server, self.port))
+
+
+
+MANAGED_API={
+    BMAEndpoint.API: BMAEndpoint,
+    SecuredBMAEndpoint.API: SecuredBMAEndpoint,
+    WS2PEndpoint.API: WS2PEndpoint,
+    ESUserEndpoint.API: ESUserEndpoint,
+    ESSubscribtionEndpoint.API: ESSubscribtionEndpoint
+}