diff --git a/docs/source/protocol/msr.rst b/docs/source/protocol/msr.rst
index 112a7113ce33de8244fdda4c58fda7661ee134a0..12eb41eefaaf3fc24995b1dac69591a808860c62 100644
--- a/docs/source/protocol/msr.rst
+++ b/docs/source/protocol/msr.rst
@@ -14,7 +14,33 @@ These endpoints are intended for use by MSR.
 .. autofunction:: inventory_provider.routes.msr.access_services
 
 
-/msr/logical-system-peerings</name>
+/msr/bgp/logical-systems
 -------------------------------------
 
-.. autofunction:: inventory_provider.routes.msr.logical_system_peerings
\ No newline at end of file
+.. autofunction:: inventory_provider.routes.msr.get_logical_systems
+
+
+/msr/bgp/logical-system-peerings</name>
+------------------------------------------
+
+.. autofunction:: inventory_provider.routes.msr.logical_system_peerings
+
+
+/msr/bgp/groups
+-------------------------------------
+
+.. autofunction:: inventory_provider.routes.msr.get_peering_groups
+
+
+/msr/bgp/group-peerings</name>
+-------------------------------------
+
+.. autofunction:: inventory_provider.routes.msr.bgp_group_peerings
+
+
+helpers
+-------------------------------------
+
+.. autofunction:: inventory_provider.routes.msr._handle_peering_group_list_request
+
+.. autofunction:: inventory_provider.routes.msr._handle_peering_group_request
diff --git a/inventory_provider/routes/msr.py b/inventory_provider/routes/msr.py
index 58693b68a2ae1b80cffa33891ded878847ec1e78..62e25212e3291d23d0b5635c63ce9bba9cde1c35 100644
--- a/inventory_provider/routes/msr.py
+++ b/inventory_provider/routes/msr.py
@@ -38,8 +38,14 @@ ACCESS_SERVICES_LIST_SCHEMA = {
     "items": {"$ref": "#/definitions/service"}
 }
 
+PEERING_GROUP_LIST_SCHEMA = {
+    "$schema": "http://json-schema.org/draft-07/schema#",
+    "type": "array",
+    "items": {"type": "string"}
+
+}
 
-LOGICAL_SYSTEM_PEERING_LIST_SCHEMA = {
+PEERING_LIST_SCHEMA = {
     "$schema": "http://json-schema.org/draft-07/schema#",
     "definitions": {
         "peering-instance": {
@@ -50,13 +56,16 @@ LOGICAL_SYSTEM_PEERING_LIST_SCHEMA = {
                 "logical-system": {"type": "string"},
                 "group": {"type": "string"},
                 "hostname": {"type": "string"},
-                "remote-asn": {"type": "integer"}
+                "remote-asn": {"type": "integer"},
+                "local-asn": {"type": "integer"},
+                "instance": {"type": "string"}
             },
             # only vrr peerings have remote-asn
+            # only group peerings have local-asn or instance
+            # not all group peerings have 'description'
+            # and only vrr or vpn-proxy peerings are within a logical system
             "required": [
                 "address",
-                "description",
-                "logical-system",
                 "group",
                 "hostname"],
             "additionalProperties": False
@@ -114,30 +123,32 @@ def access_services():
     return jsonify(result)
 
 
-@routes.route("/logical-system-peerings", methods=['GET', 'POST'])
-@routes.route("/logical-system-peerings/<name>", methods=['GET', 'POST'])
-@common.require_accepts_json
-def logical_system_peerings(name=None):
+def _handle_peering_group_request(name, cache_key, group_key_base):
     """
-    Handler for `/msr/logical-system-peerings`
+    Common method for used by
+    :meth:`inventory_provider.routes.msr.logical_system_peerings` and
+    :meth:`inventory_provider.routes.msr.bgp_group_peerings`.
 
     This method will return a list of all peerings configured
-    for the requested logical-system name on any router, or for any
-    logical system if no parameter is given.
+    for the specified group `name on any router,
+    or for all group names if `name` None.
 
     The response will be formatted according to the following schema:
 
     .. asjson::
-       inventory_provider.routes.msr.LOGICAL_SYSTEM_PEERING_LIST_SCHEMA
+       inventory_provider.routes.msr.PEERING_LIST_SCHEMA
 
-    :return:
+    :param name: group/logical-system name, or None
+    :param cache_key: base cache key for this type of request
+    :param group_key_base: key above which the peerings are grouped
+    :return: a json list, formatted as above
     """
 
     r = common.get_current_redis()
 
-    def _get_all_ls_keys():
+    def _get_all_subkeys():
         keys = []
-        for k in r.scan_iter('juniper-peerings:logical-system:*', count=1000):
+        for k in r.scan_iter(f'{group_key_base}:*', count=1000):
             keys.append(k.decode('utf-8'))
         return keys
 
@@ -146,7 +157,6 @@ def logical_system_peerings(name=None):
         if value:
             yield from json.loads(value.decode('utf-8'))
 
-    cache_key = 'classifier-cache:msr:logical-system-peerings'
     if name:
         cache_key = f'{cache_key}:{name}'
 
@@ -156,9 +166,9 @@ def logical_system_peerings(name=None):
         items = json.loads(items.decode('utf-8'))
     else:
         if name:
-            items = _load_list_items(f'juniper-peerings:logical-system:{name}')
+            items = _load_list_items(f'{group_key_base}:{name}')
         else:
-            gen_list = list(map(_load_list_items, _get_all_ls_keys()))
+            gen_list = list(map(_load_list_items, _get_all_subkeys()))
             items = itertools.chain(*gen_list)
 
         items = list(items)
@@ -171,3 +181,117 @@ def logical_system_peerings(name=None):
         r.set(cache_key, json.dumps(items).encode('utf-8'))
 
     return jsonify(items)
+
+
+@routes.route("/bgp/logical-system-peerings", methods=['GET', 'POST'])
+@routes.route("/bgp/logical-system-peerings/<name>", methods=['GET', 'POST'])
+@common.require_accepts_json
+def logical_system_peerings(name=None):
+    """
+    Handler for `/msr/bgp/logical-system-peerings`
+
+    This method will return a list of all peerings configured
+    for the requested logical-system name on any router, or for any
+    logical system if no parameter is given.
+
+    :return: see :meth:`inventory_provider.routes.msr._handle_peering_group_request`
+    """  # noqa: E501
+    return _handle_peering_group_request(
+        name=name,
+        cache_key='classifier-cache:msr:logical-system-peerings',
+        group_key_base='juniper-peerings:logical-system')
+
+
+@routes.route("/bgp/group-peerings", methods=['GET', 'POST'])
+@routes.route("/bgp/group-peerings/<name>", methods=['GET', 'POST'])
+@common.require_accepts_json
+def bgp_group_peerings(name=None):
+    """
+    Handler for `/msr/bgp/group-peerings`
+
+    This method will return a list of all peerings configured
+    for the requested logical-system name on any router, or for any
+    logical system if no parameter is given.
+
+    :return: see :meth:`inventory_provider.routes.msr._handle_peering_group_request`
+    """  # noqa: E501
+    return _handle_peering_group_request(
+        name=name,
+        cache_key='classifier-cache:msr:group-peerings',
+        group_key_base='juniper-peerings:group')
+
+
+def _handle_peering_group_list_request(cache_key, group_key_base):
+    """
+    Common method for used by
+    :meth:`inventory_provider.routes.msr.get_logical_systems` and
+    :meth:`inventory_provider.routes.msr.get_peering_groups`.
+
+    This method will return a list of all immediate subkeys of
+     `group_key_base`.
+
+    The response will be formatted according to the following schema:
+
+    .. asjson::
+       inventory_provider.routes.msr.PEERING_GROUP_LIST_SCHEMA
+
+    :param cache_key: base cache key for this type of request
+    :param group_key_base: key above which the peerings are grouped
+    :return: a json list, formatted as above
+    """
+
+    r = common.get_current_redis()
+
+    def _get_all_subkeys():
+        for k in r.scan_iter(f'{group_key_base}:*', count=1000):
+            k = k.decode('utf-8')
+            yield k[len(group_key_base) + 1:]
+
+    names = r.get(cache_key)
+
+    if names:
+        names = json.loads(names.decode('utf-8'))
+    else:
+        names = list(_get_all_subkeys())
+        if not names:
+            return Response(
+                response='no groups found',
+                status=404,
+                mimetype="text/html")
+        names = sorted(names)
+
+        r.set(cache_key, json.dumps(names).encode('utf-8'))
+
+    return jsonify(names)
+
+
+@routes.route("/bgp/logical-systems", methods=['GET', 'POST'])
+@common.require_accepts_json
+def get_logical_systems():
+    """
+    Handler for `/msr/bgp/logical-systems`
+
+    Returns a list of logical system names for which peering
+    information is available.
+
+    :return: see :meth:`inventory_provider.routes.msr._handle_peering_group_list_request`
+    """  # noqa: E501
+    return _handle_peering_group_list_request(
+        cache_key='classifier-cache:msr:logical-systems',
+        group_key_base='juniper-peerings:logical-system')
+
+
+@routes.route("/bgp/groups", methods=['GET', 'POST'])
+@common.require_accepts_json
+def get_peering_groups():
+    """
+    Handler for `/msr/bgp/groups`
+
+    Returns a list of group names for which peering
+    information is available.
+
+    :return: see :meth:`inventory_provider.routes.msr._handle_peering_group_list_request`
+    """  # noqa: E501
+    return _handle_peering_group_list_request(
+        cache_key='classifier-cache:msr:peering-groups',
+        group_key_base='juniper-peerings:group')
diff --git a/test/test_msr_routes.py b/test/test_msr_routes.py
index a54695271cee86b1377ba8c8cd4aa57e2e33ac29..173cf1528a35ee8d051b17e1f6f6a7883d9a7e34 100644
--- a/test/test_msr_routes.py
+++ b/test/test_msr_routes.py
@@ -3,8 +3,8 @@ import jsonschema
 
 import pytest
 
-from inventory_provider.routes.msr \
-    import ACCESS_SERVICES_LIST_SCHEMA, LOGICAL_SYSTEM_PEERING_LIST_SCHEMA
+from inventory_provider.routes.msr import ACCESS_SERVICES_LIST_SCHEMA, \
+    PEERING_LIST_SCHEMA, PEERING_GROUP_LIST_SCHEMA
 
 DEFAULT_REQUEST_HEADERS = {
     "Content-type": "application/json",
@@ -26,25 +26,26 @@ def test_access_services(client):
 
 def test_logical_system_peerings_all(client):
     rv = client.get(
-        '/msr/logical-system-peerings',
+        '/msr/bgp/logical-system-peerings',
         headers=DEFAULT_REQUEST_HEADERS)
     assert rv.status_code == 200
     assert rv.is_json
     response_data = json.loads(rv.data.decode('utf-8'))
-    jsonschema.validate(response_data, LOGICAL_SYSTEM_PEERING_LIST_SCHEMA)
+    jsonschema.validate(response_data, PEERING_LIST_SCHEMA)
 
     assert response_data  # test data is non-empty
+    assert all('logical-system' in p for p in response_data)
 
 
 @pytest.mark.parametrize('name', ['VRR', 'VPN-PROXY'])
 def test_logical_system_peerings_specific(client, name):
     rv = client.get(
-        f'/msr/logical-system-peerings/{name}',
+        f'/msr/bgp/logical-system-peerings/{name}',
         headers=DEFAULT_REQUEST_HEADERS)
     assert rv.status_code == 200
     assert rv.is_json
     response_data = json.loads(rv.data.decode('utf-8'))
-    jsonschema.validate(response_data, LOGICAL_SYSTEM_PEERING_LIST_SCHEMA)
+    jsonschema.validate(response_data, PEERING_LIST_SCHEMA)
 
     assert response_data  # test data is non-empty
     assert all(p['logical-system'] == name for p in response_data)
@@ -59,6 +60,53 @@ def test_logical_system_peerings_specific(client, name):
 ])
 def test_logical_system_peerings_404(client, name):
     rv = client.get(
-        f'/msr/logical-system-peerings/{name}',
+        f'/msr/bgp/logical-system-peerings/{name}',
         headers=DEFAULT_REQUEST_HEADERS)
     assert rv.status_code == 404
+
+
+def test_group_peerings_all(client):
+    rv = client.get(
+        '/msr/bgp/group-peerings',
+        headers=DEFAULT_REQUEST_HEADERS)
+    assert rv.status_code == 200
+    assert rv.is_json
+    response_data = json.loads(rv.data.decode('utf-8'))
+    jsonschema.validate(response_data, PEERING_LIST_SCHEMA)
+
+    assert response_data  # test data is non-empty
+
+
+@pytest.mark.parametrize('name', ['BGPLU', 'eGEANT', 'eGEANT-mcast'])
+def test_group_peerings_specific(client, name):
+    rv = client.get(
+        f'/msr/bgp/group-peerings/{name}',
+        headers=DEFAULT_REQUEST_HEADERS)
+    assert rv.status_code == 200
+    assert rv.is_json
+    response_data = json.loads(rv.data.decode('utf-8'))
+    jsonschema.validate(response_data, PEERING_LIST_SCHEMA)
+
+    assert response_data  # test data is non-empty
+    assert all(p['group'] == name for p in response_data)
+
+
+@pytest.mark.parametrize('name', ['EGEANT', 'eGEANT mcast'])
+def test_group_peerings_404(client, name):
+    rv = client.get(
+        f'/msr/bgp/logical-system-peerings/{name}',
+        headers=DEFAULT_REQUEST_HEADERS)
+    assert rv.status_code == 404
+
+
+@pytest.mark.parametrize('uri', [
+    '/msr/bgp/logical-systems',
+    '/msr/bgp/groups'])
+def test_peerings_group_list(client, uri):
+    rv = client.get(uri, headers=DEFAULT_REQUEST_HEADERS)
+    assert rv.status_code == 200
+    assert rv.is_json
+    response_data = json.loads(rv.data.decode('utf-8'))
+    jsonschema.validate(response_data, PEERING_GROUP_LIST_SCHEMA)
+
+    assert response_data  # test data is non-empty
diff --git a/test/test_worker_utils.py b/test/test_worker_utils.py
index 1d49ffed06556d3f09a472a3d50cdcf8e57f0364..27727533628e63498d4e436c6c82b396f4f9a4e8 100644
--- a/test/test_worker_utils.py
+++ b/test/test_worker_utils.py
@@ -9,7 +9,7 @@ import jsonschema
 
 from inventory_provider.tasks import worker
 from inventory_provider.tasks import common
-from inventory_provider.routes.msr import LOGICAL_SYSTEM_PEERING_LIST_SCHEMA
+from inventory_provider.routes import msr
 
 
 def backend_db():
@@ -141,7 +141,7 @@ def test_build_juniper_peering_db(mocked_worker_module):
         "additionalProperties": False
     }
 
-    PEERING_LIST_SCHEMA = {
+    DETAILED_PEERING_LIST_SCHEMA = {
         "$schema": "http://json-schema.org/draft-07/schema#",
         "definitions": {
             "top-level-peering": TOP_LEVEL_PEERING_SCHEMA,
@@ -194,15 +194,16 @@ def test_build_juniper_peering_db(mocked_worker_module):
                 assert address == canonical
             continue
 
-        jsonschema.validate(value, PEERING_LIST_SCHEMA)
+        jsonschema.validate(value, DETAILED_PEERING_LIST_SCHEMA)
 
         if 'logical-system:' in key:
-            jsonschema.validate(value, LOGICAL_SYSTEM_PEERING_LIST_SCHEMA)
+            jsonschema.validate(value, msr.PEERING_LIST_SCHEMA)
             m = re.match(r'.*logical-system:(.+)$', key)
             assert all(p['logical-system'] == m.group(1) for p in value)
             found_logical_system = True
 
         if 'group:' in key:
+            jsonschema.validate(value, msr.PEERING_LIST_SCHEMA)
             m = re.match(r'.*group:(.+)$', key)
             assert all(p['group'] == m.group(1) for p in value)
             found_group = True