diff --git a/inventory_provider/routes/neteng.py b/inventory_provider/routes/neteng.py
index 29f8abcd9c963c06ac40fed5063d32f401435a28..f171fa9d4d340f084817c46c1cc2619d78896d7b 100644
--- a/inventory_provider/routes/neteng.py
+++ b/inventory_provider/routes/neteng.py
@@ -12,9 +12,20 @@ These endpoints are intended for use by neteng tools.
 
 .. autofunction:: inventory_provider.routes.neteng.get_location
 
+/neteng/pops
+---------------------------------
+
+.. autofunction:: inventory_provider.routes.neteng.get_pop_names
+
+/neteng/pop/name
+---------------------------------
+
+.. autofunction:: inventory_provider.routes.neteng.get_pop_location
+
 """
 import json
 import logging
+import re
 import threading
 
 from flask import Blueprint, Response, jsonify
@@ -25,6 +36,12 @@ routes = Blueprint('neteng-query-routes', __name__)
 logger = logging.getLogger(__name__)
 _subnet_lookup_semaphore = threading.Semaphore()
 
+STRING_LIST_SCHEMA = {
+    '$schema': 'http://json-schema.org/draft-07/schema#',
+    'type': 'array',
+    'items': {'type': 'string'}
+}
+
 
 @routes.after_request
 def after_request(resp):
@@ -35,9 +52,9 @@ def after_request(resp):
 @common.require_accepts_json
 def get_location(equipment):
     """
-    Handler for `/neteng/location/equipment-name`
+    Handler for `/neteng/location/<equipment-name>`
 
-    This method will pop location information for the IMS node
+    This method will return pop location information for the IMS node
     with name = `equipment-name`.
 
     404 is returned if the IMS node name is not known.
@@ -66,3 +83,66 @@ def get_location(equipment):
             mimetype='text/html')
 
     return jsonify(value[0])
+
+
+@routes.route('/pops', methods=['GET', 'POST'])
+@common.require_accepts_json
+def get_pop_names():
+    """
+    Handler for `/neteng/pops`
+
+    This method will return a list of defined pop
+    names.  Elements from this list can be used
+    with `/neteng/pop`.
+
+    .. asjson::
+        inventory_provider.routes.neteng.STRING_LIST_SCHEMA
+
+    :return: as above
+    """
+
+    def _pops():
+        r = common.get_current_redis()
+        for k in r.scan_iter('ims:pop:*', count=1000):
+            k = k.decode('utf-8')
+            m = re.match('^ims:pop:(.+)$', k)
+            yield m.group(1)
+
+    return jsonify(sorted(list(_pops())))
+
+
+@routes.route('/pop/<name>', methods=['GET', 'POST'])
+@common.require_accepts_json
+def get_pop_location(name):
+    """
+    Handler for `/neteng/pop/<name>`
+
+    This method will return location information for the POP
+    with name = `name` in IMS.
+
+    404 is returned if the POP name is not known.
+    Otherwise the return value will be formatted as:
+
+    .. asjson::
+        inventory_provider.db.ims_data.POP_LOCATION_SCHEMA
+
+    :return: as above
+    """
+
+    r = common.get_current_redis()
+
+    value = r.get(f'ims:pop:{name}')
+    if not value:
+        return Response(
+            response='no location information available for "{pop}"',
+            status=404,
+            mimetype='text/html')
+
+    value = json.loads(value.decode('utf-8'))
+    if not value:
+        return Response(
+            response='unexpected empty cached data for "{name}"',
+            status=500,
+            mimetype='text/html')
+
+    return jsonify(value)
diff --git a/test/data/router-info.json b/test/data/router-info.json
index 11cf50f26a517892c3177aaebce341a8dd8207d0..2f118d9e38d0562b5521cf06e4673610dd114d00 100644
Binary files a/test/data/router-info.json and b/test/data/router-info.json differ
diff --git a/test/test_neteng_routes.py b/test/test_neteng_routes.py
index 1e95322a3be4cd43a83caeea12c2a9f6d35e034e..ceaa92c7735f6c9393563b0cc52d63db3a5ce5e9 100644
--- a/test/test_neteng_routes.py
+++ b/test/test_neteng_routes.py
@@ -2,7 +2,9 @@ import json
 import jsonschema
 import pytest
 
-from inventory_provider.db.ims_data import NODE_LOCATION_SCHEMA
+from inventory_provider.db.ims_data \
+    import NODE_LOCATION_SCHEMA, POP_LOCATION_SCHEMA
+from inventory_provider.routes.neteng import STRING_LIST_SCHEMA
 
 
 @pytest.mark.parametrize('equipment_name', [
@@ -25,3 +27,35 @@ def test_location_not_found(client, mocked_redis):
         '/neteng/location/BOGUS.EQUIPMENT.NAME',
         headers={'Accept': ['application/json']})
     assert rv.status_code == 404
+
+
+def test_get_pops(client, mocked_redis):
+    rv = client.get(
+        '/neteng/pops',
+        headers={'Accept': ['application/json']})
+    assert rv.status_code == 200
+    jsonschema.validate(
+        json.loads(rv.data.decode('utf-8')),
+        STRING_LIST_SCHEMA)
+
+
+@pytest.mark.parametrize('pop_name', [
+    'AMSTERDAM', 'VIENNA', 'LONDON', 'LONDON 2'
+])
+def test_pop_location(client, mocked_redis, pop_name):
+    rv = client.post(
+        f'/neteng/pop/{pop_name}',
+        headers={'Accept': ['application/json']})
+    assert rv.status_code == 200
+    jsonschema.validate(
+        json.loads(rv.data.decode('utf-8')),
+        POP_LOCATION_SCHEMA)
+    s = json.loads(rv.data.decode('utf-8'))
+    print(s)
+
+
+def test_pop_not_found(client, mocked_redis):
+    rv = client.post(
+        '/neteng/pop/BOGUS.POP.NAME',
+        headers={'Accept': ['application/json']})
+    assert rv.status_code == 404