diff --git a/README.md b/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..fdf69259f9e01e0a4dc52ee9e635f3e3819b51da
--- /dev/null
+++ b/README.md
@@ -0,0 +1,51 @@
+keystore
+========
+
+KeyStore holds *unencrypted* secrets on behalf of users in memory for
+a short time (of the order of a SSO session lifespan). User secrets
+can be *opened* with a password (used to decrypt the key, which is
+stored encrypted in a database), *queried* by presenting a suitable
+authentication token, and *closed* (wiped and forgotten).
+
+The database can provide multiple versions of the encrypted key (to
+support multiple decryption passwords), in which case we'll try
+them all sequentially until one of them decrypts successfully with
+the provided password.
+
+In order to query the KeyStore, you need to present a valid SSO
+token for the user whose secrets you would like to obtain.
+
+# API
+
+The server exports an API over HTTP/HTTPS. All requests should be made
+using the POST method and a Content-Type of *application/json*. The
+request body should contain a JSON-encoded object. Responses will be
+similarly JSON-encoded.
+
+`/api/open` (*OpenRequest*)
+
+Retrieve the encrypted key for a user, decrypt it with the provided
+password, and store it in memory.
+
+OpenRequest is an object with the
+following attributes:
+
+* `username`
+* `password` to decrypt the user's key with
+* `ttl` (seconds) time after which the credentials are automatically
+  forgotten
+
+`/api/get` (*GetRequest*) -> *GetResponse*
+
+Retrieve the key for a user. GetRequest must contain the following
+attributes:
+
+* `username` whose key you wish to retrieve
+* `sso_ticket` with a valid SSO ticket for the *keystore* service
+
+If the request is successfully authenticated, GetResponse will contain
+a single attribute *key*.
+
+`/api/close` (*CloseRequest*)
+
+Forget the key for a given user.