diff --git a/docs/source/interface.rst b/docs/source/interface.rst
index afb2cc7ad6f70123620e622c9394fd38acbf505c..8b035cfac0813dacf423da714102b7e39f4b0529 100644
--- a/docs/source/interface.rst
+++ b/docs/source/interface.rst
@@ -115,7 +115,7 @@ The elements of the list are objects like the one returned by issuing a **GET**
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 This endpoint allows an external agent to retrieve unused unblinded tokens present in the node's database.
-Unblinded tokens are returned in ascending text sorted order.
+Unblinded tokens are returned in a stable order.
 This order matches the order in which tokens will be used by the system.
 This endpoint accepts several query arguments:
 
@@ -138,3 +138,19 @@ If it has run,
 
  * ``when``: associated with an ISO8601 datetime string giving the approximate time the process ran
  * ``count``: associated with a number giving the number of passes which would need to be spent to renew leases on all stored objects seen during the lease maintenance activity
+
+``POST /storage-plugins/privatestorageio/zkapauthz-v1/unblinded-token``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This endpoint allows an external agent to insert new unblinded tokens into the node's database.
+This allows for restoration of previously backed-up tokens in case the node is lost.
+Tokens inserted with this API will be used after any tokens already in the database and in the order they appear in the given list.
+
+The request body must be ``application/json`` encoded and contain an object like::
+
+  { "unblinded-tokens": [<unblinded token string>, ...]
+  }
+
+The response is **OK** with ``application/json`` content-type response body like::
+
+  { }
diff --git a/src/_zkapauthorizer/model.py b/src/_zkapauthorizer/model.py
index 873197710f6c6eaa073faba8b0b6b7b20769985d..8615b43955dd64b54a7ea0b2827bb283f6fc02e7 100644
--- a/src/_zkapauthorizer/model.py
+++ b/src/_zkapauthorizer/model.py
@@ -308,10 +308,35 @@ class VoucherStore(object):
             in refs
         )
 
+    def _insert_unblinded_tokens(self, cursor, unblinded_tokens):
+        """
+        Helper function to really insert unblinded tokens into the database.
+        """
+        cursor.executemany(
+            """
+            INSERT INTO [unblinded-tokens] VALUES (?)
+            """,
+            list(
+                (token,)
+                for token
+                in unblinded_tokens
+            ),
+        )
+
+    @with_cursor
+    def insert_unblinded_tokens(self, cursor, unblinded_tokens):
+        """
+        Store some unblinded tokens, for example as part of a backup-restore
+        process.
+
+        :param list[unicode] unblinded_tokens: The unblinded tokens to store.
+        """
+        self._insert_unblinded_tokens(cursor, unblinded_tokens)
+
     @with_cursor
     def insert_unblinded_tokens_for_voucher(self, cursor, voucher, public_key, unblinded_tokens):
         """
-        Store some unblinded tokens.
+        Store some unblinded tokens received from redemption of a voucher.
 
         :param unicode voucher: The voucher associated with the unblinded
             tokens.  This voucher will be marked as redeemed to indicate it
@@ -343,12 +368,10 @@ class VoucherStore(object):
         )
         if cursor.rowcount == 0:
             raise ValueError("Cannot insert tokens for unknown voucher; add voucher first")
-        cursor.executemany(
-            """
-            INSERT INTO [unblinded-tokens] VALUES (?)
-            """,
+        self._insert_unblinded_tokens(
+            cursor,
             list(
-                (t.unblinded_token,)
+                t.unblinded_token
                 for t
                 in unblinded_tokens
             ),
diff --git a/src/_zkapauthorizer/resource.py b/src/_zkapauthorizer/resource.py
index b09b58ab672e5443a062e3cc68bd6ae8dfeec8ca..1e2f5ae68ec0b3dd94113ab4ada929286df86594 100644
--- a/src/_zkapauthorizer/resource.py
+++ b/src/_zkapauthorizer/resource.py
@@ -27,7 +27,9 @@ from itertools import (
     islice,
 )
 from json import (
-    loads, dumps,
+    loads,
+    load,
+    dumps,
 )
 from zope.interface import (
     Attribute,
@@ -181,6 +183,16 @@ class _UnblindedTokenCollection(Resource):
             u"lease-maintenance-spending": self._lease_maintenance_activity(),
         })
 
+    def render_POST(self, request):
+        """
+        Store some unblinded tokens.
+        """
+        application_json(request)
+        unblinded_tokens = load(request.content)[u"unblinded-tokens"]
+        self._store.insert_unblinded_tokens(unblinded_tokens)
+        return dumps({})
+
+
     def _lease_maintenance_activity(self):
         activity = self._store.get_latest_lease_maintenance_activity()
         if activity is None:
diff --git a/src/_zkapauthorizer/tests/test_client_resource.py b/src/_zkapauthorizer/tests/test_client_resource.py
index 423f4950de7cadac563576da99496f0c47f18c4b..f6d2abde71ebfdb238ce37477f4f0af4f657e926 100644
--- a/src/_zkapauthorizer/tests/test_client_resource.py
+++ b/src/_zkapauthorizer/tests/test_client_resource.py
@@ -146,6 +146,7 @@ from .strategies import (
     client_dummyredeemer_configurations,
     client_nonredeemer_configurations,
     client_errorredeemer_configurations,
+    unblinded_tokens,
     vouchers,
     requests,
 )
@@ -305,6 +306,54 @@ class UnblindedTokenTests(TestCase):
         self.useFixture(CaptureTwistedLogs())
 
 
+    @given(
+        tahoe_configs(),
+        vouchers(),
+        lists(unblinded_tokens(), unique=True, min_size=1, max_size=1000),
+    )
+    def test_post(self, get_config, voucher, unblinded_tokens):
+        """
+        When the unblinded token collection receives a **POST**, the unblinded
+        tokens in the request body are inserted into the system and an OK
+        response is generated.
+        """
+        tempdir = self.useFixture(TempDir())
+        config = get_config(tempdir.join(b"tahoe"), b"tub.port")
+        root = root_from_config(config, datetime.now)
+
+
+        agent = RequestTraversalAgent(root)
+        producer = FileBodyProducer(
+            BytesIO(dumps({u"unblinded-tokens": list(
+                token.unblinded_token
+                for token
+                in unblinded_tokens
+            )})),
+            cooperator=uncooperator(),
+        )
+        requesting = agent.request(
+            b"POST",
+            b"http://127.0.0.1/unblinded-token",
+            bodyProducer=producer,
+        )
+        self.assertThat(
+            requesting,
+            succeeded(
+                ok_response(headers=application_json()),
+            ),
+        )
+
+        stored_tokens = root.controller.store.backup()[u"unblinded-tokens"]
+
+        self.assertThat(
+            stored_tokens,
+            Equals(list(
+                token.unblinded_token
+                for token
+                in unblinded_tokens
+            )),
+        )
+
     @given(tahoe_configs(), vouchers(), integers(min_value=0, max_value=100))
     def test_get(self, get_config, voucher, num_tokens):
         """