diff --git a/docs/source/interface.rst b/docs/source/interface.rst
index 0dcccabc1590e6974aeb6a7147cc5e7389123907..1b3c8543d576e1fc6d10dfbd47307ecfcdae958e 100644
--- a/docs/source/interface.rst
+++ b/docs/source/interface.rst
@@ -42,3 +42,15 @@ The ``stage`` property indicates how far into redemption the plugin has proceede
 The ``of`` property indicates how many steps the process involves in total.
 The ``stage-name`` property gives a human-meaningful description of the current stage.
 The ``stage-entered-time`` property gives the timestamp for the start of the current staged.
+
+``GET /storage-plugins/privatestorageio-satauthz-v1/payment-reference-number``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This endpoint allows an external agent to retrieve the status of all payment reference numbers.
+This endpoint accepts no request body.
+
+The response is **OK** with ``application/json`` content-type response body like::
+
+  {"payment-reference-numbers": [<payment reference status object>, ...]}
+
+The elements of the list are objects like the one returned by issuing a **GET** to a child of this collection resource.
diff --git a/src/_secureaccesstokenauthorizer/model.py b/src/_secureaccesstokenauthorizer/model.py
index 915481bb646619f754a582a371165f4e8385261d..2e852c42f1f1e365eba39e4ff945b3774e9fb0c0 100644
--- a/src/_secureaccesstokenauthorizer/model.py
+++ b/src/_secureaccesstokenauthorizer/model.py
@@ -19,9 +19,11 @@ the storage plugin.
 
 from os import (
     makedirs,
+    listdir,
 )
 from errno import (
     EEXIST,
+    ENOENT,
 )
 from json import (
     loads,
@@ -59,6 +61,11 @@ class PaymentReferenceStore(object):
     def _config_key(self, prn):
         return u"{}/{}.prn+json".format(self._CONFIG_DIR, prn)
 
+    def _prn(self, config_key):
+        if config_key.endswith(u".prn+json"):
+            return config_key[:-len(u".prn+json")]
+        raise ValueError("{} does not look like a config key".format(config_key))
+
     def _read_pr_json(self, prn):
         private_config_item = self._config_key(prn)
         try:
@@ -93,6 +100,22 @@ class PaymentReferenceStore(object):
         except KeyError:
             self._write_pr_json(prn, PaymentReference(prn).to_json())
 
+    def list(self):
+        # XXX Need an API to be able to avoid touching the filesystem directly
+        # here.
+        container = self.node_config.get_private_path(self._CONFIG_DIR)
+        try:
+            children = listdir(container)
+        except EnvironmentError as e:
+            if ENOENT != e.errno:
+                raise
+            children = []
+        return list(
+            PaymentReference(self._prn(config_key))
+            for config_key
+            in children
+        )
+
 
 @attr.s
 class PaymentReference(object):
@@ -111,7 +134,11 @@ class PaymentReference(object):
 
 
     def to_json(self):
-        return dumps(self.to_json_v1())
+        return dumps(self.marshal())
+
+
+    def marshal(self):
+        return self.to_json_v1()
 
 
     def to_json_v1(self):
diff --git a/src/_secureaccesstokenauthorizer/resource.py b/src/_secureaccesstokenauthorizer/resource.py
index f76f0a6fabf072f45af6cba8120f16cd396edd6b..49b37f5b8b9038d352ac469749d289da75389523 100644
--- a/src/_secureaccesstokenauthorizer/resource.py
+++ b/src/_secureaccesstokenauthorizer/resource.py
@@ -21,7 +21,7 @@ In the future it should also allow users to read statistics about token usage.
 """
 
 from json import (
-    loads,
+    loads, dumps,
 )
 
 from twisted.web.http import (
@@ -106,6 +106,17 @@ class _PaymentReferenceNumberCollection(Resource):
         return b""
 
 
+    def render_GET(self, request):
+        request.responseHeaders.setRawHeaders(u"content-type", [u"application/json"])
+        return dumps({
+            u"payment-reference-numbers": list(
+                prn.marshal()
+                for prn
+                in self._store.list()
+            ),
+        })
+
+
     def getChild(self, segment, request):
         prn = segment
         try:
diff --git a/src/_secureaccesstokenauthorizer/tests/strategies.py b/src/_secureaccesstokenauthorizer/tests/strategies.py
index 7da47c2b72185eacd304f0ca27bf69597f15dcc9..4af061defb0f2d34a3912078e55dfd76e580d205 100644
--- a/src/_secureaccesstokenauthorizer/tests/strategies.py
+++ b/src/_secureaccesstokenauthorizer/tests/strategies.py
@@ -170,6 +170,8 @@ def payment_reference_numbers():
         max_size=32,
     ).map(
         urlsafe_b64encode,
+    ).map(
+        lambda prn: prn.decode("ascii"),
     )
 
 
diff --git a/src/_secureaccesstokenauthorizer/tests/test_client_resource.py b/src/_secureaccesstokenauthorizer/tests/test_client_resource.py
index 30b58c0004da7053b6a84b4d587a66cc7c3cb759..32c8c7731c91c576aac8a54874f7cd07e41bbcc6 100644
--- a/src/_secureaccesstokenauthorizer/tests/test_client_resource.py
+++ b/src/_secureaccesstokenauthorizer/tests/test_client_resource.py
@@ -60,6 +60,7 @@ from hypothesis.strategies import (
     one_of,
     just,
     fixed_dictionaries,
+    lists,
     integers,
     binary,
     text,
@@ -352,6 +353,66 @@ class PaymentReferenceNumberTests(TestCase):
             ),
         )
 
+    @given(tahoe_configs_with_client_config, lists(payment_reference_numbers(), unique=True))
+    def test_list_prns(self, get_config, prns):
+        """
+        A ``GET`` to the ``PaymentReferenceNumberCollection`` itself returns a
+        list of existing payment reference numbers.
+        """
+        # Hypothesis causes our test case instances to be re-used many times
+        # between setUp and tearDown.  Avoid re-using the same temporary
+        # directory for every Hypothesis iteration because this test leaves
+        # state behind that invalidates future iterations.
+        tempdir = self.useFixture(TempDir())
+        root = from_configuration(
+            get_config(tempdir.join(b"tahoe.ini"), b"tub.port"),
+        )
+
+        agent = RequestTraversalAgent(root)
+
+        for prn in prns:
+            producer = FileBodyProducer(
+                BytesIO(dumps({u"payment-reference-number": prn})),
+                cooperator=uncooperator(),
+            )
+            putting = agent.request(
+                b"PUT",
+                b"http://127.0.0.1/payment-reference-number",
+                bodyProducer=producer,
+            )
+            self.assertThat(
+                putting,
+                succeeded(
+                    ok_response(),
+                ),
+            )
+
+        getting = agent.request(
+            b"GET",
+            b"http://127.0.0.1/payment-reference-number",
+        )
+
+        self.assertThat(
+            getting,
+            succeeded(
+                MatchesAll(
+                    ok_response(headers=application_json()),
+                    AfterPreprocessing(
+                        json_content,
+                        succeeded(
+                            Equals({
+                                u"payment-reference-numbers": list(
+                                    {u"version": 1, u"number": prn}
+                                    for prn
+                                    in prns
+                                ),
+                            }),
+                        ),
+                    ),
+                ),
+            ),
+        )
+
 
 def application_json():
     return AfterPreprocessing(
diff --git a/src/_secureaccesstokenauthorizer/tests/test_model.py b/src/_secureaccesstokenauthorizer/tests/test_model.py
index 2b875b94856ba167f961e2a8e9750755dd4b1501..1159133d7a6fe8d0fd8834ad423af7e7b0e94551 100644
--- a/src/_secureaccesstokenauthorizer/tests/test_model.py
+++ b/src/_secureaccesstokenauthorizer/tests/test_model.py
@@ -45,6 +45,9 @@ from hypothesis import (
     given,
     assume,
 )
+from hypothesis.strategies import (
+    lists,
+)
 
 from ..model import (
     StoreDirectoryError,
@@ -115,6 +118,30 @@ class PaymentReferenceStoreTests(TestCase):
         )
 
 
+    @given(tahoe_configs(), lists(payment_reference_numbers()))
+    def test_list(self, get_config, prns):
+        """
+        ``PaymentReferenceStore.list`` returns a ``list`` containing a
+        ``PaymentReference`` object for each payment reference number
+        previously added.
+        """
+        tempdir = self.useFixture(TempDir())
+        nodedir = tempdir.join(b"node")
+        config = get_config(nodedir, b"tub.port")
+        store = PaymentReferenceStore(config)
+
+        for prn in prns:
+            store.add(prn)
+
+        self.assertThat(
+            store.list(),
+            AfterPreprocessing(
+                lambda refs: set(ref.number for ref in refs),
+                Equals(set(prns)),
+            ),
+        )
+
+
     @given(tahoe_configs(), payment_reference_numbers(), payment_reference_numbers())
     def test_unwriteable_store_directory(self, get_config, prn_a, prn_b):
         """