diff --git a/inventory_provider/routes/msr.py b/inventory_provider/routes/msr.py
index e5e4fa9af4ccca6bc57d8cef7cd601dc2f302d0f..0bb6a65c68f23bf45ceac35c979f391c85ef563d 100644
--- a/inventory_provider/routes/msr.py
+++ b/inventory_provider/routes/msr.py
@@ -4,18 +4,13 @@ MSR Support Endpoints
 
 These endpoints are intended for use by MSR.
 
-.. contents:: :local:
-
-/msr/access-services
----------------------------------
-
-.. autofunction:: inventory_provider.routes.msr.access_services
 
+.. contents:: :local:
 
-/msr/gws-indirect
+/poller/access-services
 ---------------------------------
 
-.. autofunction:: inventory_provider.routes.msr.gws_indirect
+.. autofunction::inventory_provider.routes.msr.get_access_services
 
 
 /msr/bgp/logical-systems
@@ -68,36 +63,11 @@ from flask import Blueprint, Response, request
 
 from inventory_provider.routes import common
 from inventory_provider.routes.common import _ignore_cache_or_retrieve
+from inventory_provider.routes.poller import get_services
 
 routes = Blueprint('msr-query-routes', __name__)
 
 
-ACCESS_SERVICES_LIST_SCHEMA = {
-    '$schema': 'http://json-schema.org/draft-07/schema#',
-
-    'definitions': {
-        'service': {
-            'type': 'object',
-            'properties': {
-                'id': {'type': 'integer'},
-                'name': {'type': 'string'},
-                'customer': {'type': 'string'},
-                'speed': {'type': 'integer'},
-                'pop': {'type': 'string'},
-                'hostname': {'type': 'string'},
-                'interface': {'type': 'string'},
-            },
-            'required': [
-                'id', 'name', 'customer', 'speed',
-                'pop', 'hostname', 'interface'],
-            'additionalProperties': False
-        }
-    },
-
-    'type': 'array',
-    'items': {'$ref': '#/definitions/service'}
-}
-
 PEERING_GROUP_LIST_SCHEMA = {
     '$schema': 'http://json-schema.org/draft-07/schema#',
     'type': 'array',
@@ -141,111 +111,6 @@ def after_request(resp):
     return common.after_request(resp)
 
 
-@routes.route('/access-services', methods=['GET', 'POST'])
-@common.require_accepts_json
-def access_services():
-    """
-    Handler for `/msr/access-services`.
-
-    This method is in development, not yet used.
-
-    The response will be formatted according to the following schema:
-
-    .. asjson::
-       inventory_provider.routes.msr.ACCESS_SERVICES_LIST_SCHEMA
-
-    :return:
-    """
-    redis = common.get_current_redis()
-
-    def _services():
-        for k in redis.scan_iter('ims:services:access_services:*'):
-            service = redis.get(k.decode('utf-8')).decode('utf-8')
-            service = json.loads(service)
-
-            yield {
-                'id': service['id'],
-                'name': service['name'],
-                'customer': service['project'],
-                'speed': service['speed_value'],
-                'pop': service['here']['pop']['name'],
-                'hostname': common.ims_equipment_to_hostname(
-                    service['here']['equipment']),
-                'interface': service['here']['port']
-            }
-
-    cache_key = 'classifier-cache:msr:access-services'
-
-    result = _ignore_cache_or_retrieve(request, cache_key, redis)
-
-    if not result:
-        result = list(_services())
-
-        if not result:
-            return Response(
-                response='no access services found',
-                status=404,
-                mimetype='text/html')
-
-        # cache this data for the next call
-        result = json.dumps(result)
-        redis.set(cache_key, result.encode('utf-8'))
-
-    return Response(result, mimetype='application/json')
-
-
-@routes.route('/gws-indirect', methods=['GET', 'POST'])
-@common.require_accepts_json
-def gws_indirect():
-    """
-    Handler for `/msr/gws-indirect`.
-
-    This method is in development, not yet used.
-
-    The response will be formatted according to the following schema:
-
-    .. asjson::
-       inventory_provider.routes.msr.ACCESS_SERVICES_LIST_SCHEMA
-
-    :return:
-    """
-    redis = common.get_current_redis()
-
-    def _services():
-        for k in redis.scan_iter('ims:services:gws_indirect:*'):
-            service = redis.get(k.decode('utf-8')).decode('utf-8')
-            service = json.loads(service)
-            yield {
-                'id': service['id'],
-                'name': service['name'],
-                'customer': service['project'],
-                'speed': service['speed_value'],
-                'pop': service['here']['pop']['name'],
-                'hostname': common.ims_equipment_to_hostname(
-                    service['here']['equipment']),
-                'interface': service['here']['port']
-            }
-
-    cache_key = 'classifier-cache:msr:gws-indirect'
-
-    result = _ignore_cache_or_retrieve(request, cache_key, redis)
-
-    if not result:
-        result = list(_services())
-
-        if not result:
-            return Response(
-                response='no gws indirect services found',
-                status=404,
-                mimetype='text/html')
-
-        # cache this data for the next call
-        result = json.dumps(result)
-        redis.set(cache_key, result.encode('utf-8'))
-
-    return Response(result, mimetype='application/json')
-
-
 def _handle_peering_group_request(name, cache_key, group_key_base):
     """
     Common method for used by
@@ -449,3 +314,16 @@ def get_peering_routing_instances():
     return _handle_peering_group_list_request(
         cache_key='classifier-cache:msr:routing-instances',
         group_key_base='juniper-peerings:routing-instance')
+
+
+@routes.route('/access-services', methods=['GET', 'POST'])
+@common.require_accepts_json
+def get_access_services():
+    """
+    Handler for `/msr/access-services`
+
+    Same as `/poller/services/geant_ip`
+
+    cf. :meth:`inventory_provider.routes.poller.get_services`
+    """
+    return get_services(service_type='geant_ip')
diff --git a/inventory_provider/routes/poller.py b/inventory_provider/routes/poller.py
index 4be62cbfc5e12d3161af63e2c38c2daa1b0c4e28..7abdfd892425723a05a7682dd4c2b8c283a31ae9 100644
--- a/inventory_provider/routes/poller.py
+++ b/inventory_provider/routes/poller.py
@@ -29,6 +29,19 @@ These endpoints are intended for use by BRIAN.
 
 .. autofunction:: inventory_provider.routes.poller.gws_direct
 
+
+/poller/gws/direct
+---------------------------------
+
+.. autofunction:: inventory_provider.routes.poller.gws_indirect
+
+
+/poller/services</type>
+---------------------------------
+
+.. autofunction:: inventory_provider.routes.poller.get_services
+
+
 """
 import json
 import logging
@@ -203,6 +216,33 @@ GWS_DIRECT_DATA_SCHEMA = {
 }
 
 
+SERVICES_LIST_SCHEMA = {
+    '$schema': 'http://json-schema.org/draft-07/schema#',
+
+    'definitions': {
+        'service': {
+            'type': 'object',
+            'properties': {
+                'id': {'type': 'integer'},
+                'name': {'type': 'string'},
+                'customer': {'type': 'string'},
+                'speed': {'type': 'integer'},
+                'pop': {'type': 'string'},
+                'hostname': {'type': 'string'},
+                'interface': {'type': 'string'},
+            },
+            'required': [
+                'id', 'name', 'customer', 'speed',
+                'pop', 'hostname', 'interface'],
+            'additionalProperties': False
+        }
+    },
+
+    'type': 'array',
+    'items': {'$ref': '#/definitions/service'}
+}
+
+
 @routes.after_request
 def after_request(resp):
     return common.after_request(resp)
@@ -623,7 +663,7 @@ def gws_direct():
        inventory_provider.routes.poller.GWS_DIRECT_DATA_SCHEMA
 
     WARNING: interface tags in the `gws-direct` section of the config data
-    should be unique for each nren/isp/hostname combination.  i.e. if there
+    should be unique for each nren/isp combination.  i.e. if there
     are multiple community strings in use for a particular host, then please
     keep the interface tags unique.
 
@@ -662,3 +702,83 @@ def gws_direct():
         r.set(cache_key, result.encode('utf-8'))
 
     return Response(result, mimetype="application/json")
+
+
+@routes.route('/services', methods=['GET', 'POST'])
+@routes.route('/services/<service_type>', methods=['GET', 'POST'])
+@common.require_accepts_json
+def get_services(service_type=None):
+    """
+    Handler for `/poller/services/type`.
+
+    The response will be formatted according to the following schema:
+
+    .. asjson::
+       inventory_provider.routes.poller.SERVICES_LIST_SCHEMA
+
+    :return:
+    """
+    def _services():
+        key_pattern = f'ims:services:{service_type}:*' \
+            if service_type else 'ims:services:*'
+
+        for doc in common.load_json_docs(
+                config_params=current_app.config['INVENTORY_PROVIDER_CONFIG'],
+                key_pattern=key_pattern,
+                num_threads=20):
+            yield doc['value']
+
+    def _operational(s):
+        return s['status'].lower() == 'operational'
+
+    def _format_services(s):
+        return {
+            'id': s['id'],
+            'name': s['name'],
+            'customer': s['project'],
+            'speed': s['speed_value'],
+            'pop': s['here']['pop']['name'],
+            'hostname': common.ims_equipment_to_hostname(
+                s['here']['equipment']),
+            'interface': s['here']['port']
+        }
+
+    cache_key = f'classifier-cache:poller:services:{service_type}' \
+        if service_type else 'classifier-cache:poller:services:all'
+
+    redis = common.get_current_redis()
+    result = _ignore_cache_or_retrieve(request, cache_key, redis)
+
+    if not result:
+        result = _services()
+        result = filter(_operational, result)
+        result = map(_format_services, result)
+        result = list(result)
+
+        if not result:
+            message = f'no {service_type} services found' \
+                    if service_type else 'no services found'
+            return Response(
+                response=message,
+                status=404,
+                mimetype='text/html')
+
+        # cache this data for the next call
+        result = json.dumps(result)
+        redis.set(cache_key, result.encode('utf-8'))
+
+    return Response(result, mimetype='application/json')
+
+
+@routes.route("/gws/indirect", methods=['GET', 'POST'])
+@common.require_accepts_json
+def gws_indirect():
+    """
+    Handler for `/poller/gws/indirect`
+
+    Same as `/poller/services/gws_indirect`
+
+    cf. :meth:`inventory_provider.routes.poller.get_services`
+    :return:
+    """
+    return get_services(service_type='geant_ip')
diff --git a/inventory_provider/tasks/worker.py b/inventory_provider/tasks/worker.py
index 6a0187ac524020376da05b9b5a0f89e567697349..a1b1fcae1c23f188acd6a698337d60b6abb7a0fd 100644
--- a/inventory_provider/tasks/worker.py
+++ b/inventory_provider/tasks/worker.py
@@ -829,7 +829,8 @@ def update_circuit_hierarchy_and_port_id_services(self, use_current=False):
                     },
                     'speed_value': v['calculated-speed'],
                     'speed_unit': 'n/a',
-                    'status': v['status']
+                    'status': v['status'],
+                    'type': v['service_type']
                 }))
 
     rp.execute()
diff --git a/tox.ini b/tox.ini
index 8d569cbc25d09e7397d4dc13d97de759cdcbf228..df546ecad30c9407e17e3b07f1a406f4ab962978 100644
--- a/tox.ini
+++ b/tox.ini
@@ -14,7 +14,7 @@ commands =
     coverage run --source inventory_provider --omit='inventory_provider/routes/ims*,inventory_provider/db/ims*,inventory_provider/tasks/ims*' -m py.test {posargs}
     coverage xml
     coverage html
-    coverage report --fail-under 75
+    coverage report --fail-under 70 
     # coverage report --fail-under 80
     flake8
     sphinx-build -M html docs/source docs/build