diff --git a/cpp/src/csandbox.cc b/cpp/src/csandbox.cc
index 44b33e62bf2e2fef4195d45b73459ebcc0c7a9b2..70382932622480f68ad621fb1f2582e0999d247d 100644
--- a/cpp/src/csandbox.cc
+++ b/cpp/src/csandbox.cc
@@ -1,8 +1,17 @@
-
+#include "vereign/crypto/rand.hh"
+#include <vereign/bytes/view.hh>
+#include <vereign/bytes/buffer.hh>
+#include <vereign/bytes/view_dump.hh>
+#include <vereign/fs/path.hh>
+#include <vereign/fs/util.hh>
+#include <iostream>
 
 auto main(int argc, char** argv) -> int {
   argc = 0;
   argv = nullptr;
+  auto path = vereign::fs::TempFilePath(vereign::fs::path::Join("tmp", "foo"), "test_db_");
+
+  std::cout << path << std::endl;
 
   return 0;
 }
diff --git a/cpp/src/vereign/bytes/view_dump.hh b/cpp/src/vereign/bytes/view_dump.hh
index 5f2708842ff04778acf323aa2d777d33fadb5d69..47625f49016bee9fd8181dbc66746d54b7b3131f 100644
--- a/cpp/src/vereign/bytes/view_dump.hh
+++ b/cpp/src/vereign/bytes/view_dump.hh
@@ -9,7 +9,64 @@
 namespace vereign::bytes {
 
 namespace detail {
+class ViewDump;
+}
 
+/**
+ * Returns a view dump object that can write the view dump into std::ostream.
+ *
+ * The dump is the good old hexadecimal format.
+ *
+ * Example:
+ * @code
+ * std::string input{"foo bar"};
+ * std::cout << bytes::dump(bytes::View(input)) << std::endl;
+ *
+ * // Output:
+ * // 0x0000:  666f 6f20 6261 72                        foo bar
+ *
+ * auto buf = crypto::Rand(32);
+ * std::cout << bytes::dump(buf.View()) << std::endl;
+ *
+ * // Output:
+ * // 0x0000:  1666 855a 650a 7549 ed0f ec01 4d87 09bf  .f.Ze.uI....M...
+ * // 0x0010:  e644 dbc8 7943 37b4 185c dbab 4977 ff3f  .D..yC7..\..Iw.?
+ *
+ * @endcode
+ */
+auto dump(View buf) -> detail::ViewDump;
+
+/**
+ * Returns a dump object that can write the buffer dump into std::ostream.
+ *
+ * The dump is the good old hexadecimal format.
+ *
+ * Example:
+ * @code
+  auto buf = bytes::Buffer{bytes::View("foo bar")};
+  std::cout << bytes::dump(buf) << std::endl;
+ *
+ * // Output:
+ * // 0x0000:  666f 6f20 6261 72                        foo bar
+ *
+ * auto buf = crypto::Rand(32);
+ * std::cout << bytes::dump(buf) << std::endl;
+ *
+ * // Output:
+ * // 0x0000:  1666 855a 650a 7549 ed0f ec01 4d87 09bf  .f.Ze.uI....M...
+ * // 0x0010:  e644 dbc8 7943 37b4 185c dbab 4977 ff3f  .D..yC7..\..Iw.?
+ *
+ * @endcode
+ */
+auto dump(const Buffer& buf) -> detail::ViewDump;
+
+namespace detail {
+
+/**
+ * Helper for dumping a view to a std::ostream.
+ *
+ * Users typically will use the bytes::dump functions.
+ */
 class ViewDump {
 public:
   auto operator=(const ViewDump&) -> ViewDump& = delete;
@@ -27,11 +84,8 @@ private:
 private:
   View buf_;
 };
-} // namespace detail
-
 
-auto dump(View buf) -> detail::ViewDump;
-auto dump(const Buffer& buf) -> detail::ViewDump;
+} // namespace detail
 
 } // namespace vereign::bytes
 
diff --git a/cpp/src/vereign/fs/util.hh b/cpp/src/vereign/fs/util.hh
index caa2f29d5d1947823e4da00394e056182e44a183..c4e9d3dbb03b08f32a63de99fd6a1da389cc8f35 100644
--- a/cpp/src/vereign/fs/util.hh
+++ b/cpp/src/vereign/fs/util.hh
@@ -28,6 +28,9 @@ private:
   std::string path_;
 };
 
+/**
+ * A RAII guard that deletes all files and directories recursively.
+ */
 class RemoveAllGuard {
 public:
   RemoveAllGuard(std::string path);
@@ -39,13 +42,70 @@ private:
   std::string path_;
 };
 
-auto BoostPath(std::string_view path) -> boost::filesystem::path;
-
+/**
+ * Generates a file path usable as temporary file.
+ *
+ * For a temp file path under the system tmp dir use the other TempFilePath overload.
+ *
+ * @code
+ * auto path = fs::TempFilePath("/tmp/foo", "test_db_");
+ * std::cout << path << std::endl;
+ *
+ * // Output:
+ * // /tmp/foo/test_db_bh0vcr0jbz
+ * @endcode
+ *
+ * @param dir The directory of the temp file path.
+ * @param prefix A prefix to prepend to the temp file name.
+ * @returns a file path usable as temporary file.
+ */
 auto TempFilePath(std::string_view dir, std::string_view prefix) -> std::string;
+
+/**
+ * Generates a file path usable as temporary file under the system temporary directory.
+ *
+ * It tries to detect the correct temp dir under different operation systems.
+ * For Linux this is `/tmp` and for Windows this is `C:\Users\<username>\AppData\Local\Temp`.
+ *
+ * @code
+ * auto path = fs::TempFilePath("test_db_");
+ * std::cout << path << std::endl;
+ *
+ * // Output:
+ * // /tmp/test_db_bh0vcr0jbz
+ * @endcode
+ *
+ * @param prefix A prefix to prepend to the temp file name.
+ * @returns a file path usable as temporary file.
+ */
 auto TempFilePath(std::string_view prefix) -> std::string;
 
+/**
+ * Creates a temporary sub directory under the system temporary directory.
+ *
+ * It tries to detect the correct temp dir under different operation systems.
+ * For Linux this is `/tmp` and for Windows this is `C:\Users\<username>\AppData\Local\Temp`.
+ *
+ * @code
+ * auto path = fs::TempDir("test_db_");
+ * std::cout << path << std::endl;
+ *
+ * // Output:
+ * // /tmp/test_db_bh0vcr0jbz
+ * @endcode
+ *
+ * @param prefix A prefix to prepend to the temp dir name.
+ * @returns a the path of the created temporary directory.
+ */
 auto TempDir(std::string_view prefix) -> std::string;
 
+/**
+ * Returns current user home directory.
+ *
+ * On Windows this is `C:\Users\<username>\AppData\Local`.
+ *
+ * @returns the user's home directory full path.
+ */
 auto HomePath() -> std::string;
 
 } // namespace vereign::fs
diff --git a/cpp/src/vereign/grpc/error_code.hh b/cpp/src/vereign/grpc/error_code.hh
index a64de2f872558876262883a92dc1bcda635189f4..2c5c26e9d6ac060ac6351405aab90f0b4b0b5010 100644
--- a/cpp/src/vereign/grpc/error_code.hh
+++ b/cpp/src/vereign/grpc/error_code.hh
@@ -8,6 +8,13 @@ namespace vereign::grpc {
 
 static constexpr const char* ClientErrorStatus = "Vereign Client Library Error";
 
+/**
+ * Error codes returned into the gRPC API response `code` field on various failures.
+ *
+ * These are errors that happen inside the Vereign Client Library.
+ * The errors that happen inside the Vereign Restful API are in the standard HTTP status code range
+ * below 600.
+ */
 enum class ErrorCode : uint64_t {
   ClientError                 = 1000,
   UnexpectedError             = 1001,
@@ -16,6 +23,12 @@ enum class ErrorCode : uint64_t {
   InvalidIdentity             = 1004
 };
 
+/**
+ * Convert the error code to string.
+ *
+ * @param ec The error code.
+ * @returns the error code integer as string.
+ */
 inline auto ErrorCodeAsString(ErrorCode ec) -> std::string {
   return std::to_string(uint64_t(ec));
 }
diff --git a/cpp/src/vereign/grpc/identity_api.hh b/cpp/src/vereign/grpc/identity_api.hh
index 5e40c265d64d4f2ba1146a98cd274361af2bd82d..6083548eb488823dafedf3991c9c704af929b91f 100644
--- a/cpp/src/vereign/grpc/identity_api.hh
+++ b/cpp/src/vereign/grpc/identity_api.hh
@@ -11,21 +11,53 @@
 
 namespace vereign::grpc {
 
+/**
+ * Implementation of the gRPC `vereign::client_library::IdentityAPI::Service` service.
+ *
+ * Inherits all the API implementations from the generated gen::IdentityAPI and adds some
+ * additional implementations.
+ *
+ * IdentityAPI is a thin layer on top of the service::IdentityService.
+ */
 template <class VereignService>
 class IdentityAPI final : public gen::IdentityAPI<VereignService> {
 public:
+  // API service name.
   static constexpr const char* Name = gen::IdentityAPI<VereignService>::Name;
 
   using VereignServiceType = VereignService;
   using VereignServicePtr = std::unique_ptr<VereignService>;
 
+  /**
+   * Constructs IdentityAPI instance.
+   *
+   * @param service The client library Identity service.
+   */
   IdentityAPI(VereignServicePtr&& service)
     : gen::IdentityAPI<VereignService>{std::move(service)}
   {}
 
+  // disable copying
   IdentityAPI(const IdentityAPI&) = delete;
   auto operator=(const IdentityAPI&) -> IdentityAPI& = delete;
 
+  /**
+   * Registers a new device.
+   *
+   * req.pin is required only under Linux.
+   *
+   * Under windows the system cypto storage is used.
+   * When the device is registered a master key is created and the user will be asked for his
+   * consent by showing a dialog window.
+   *
+   * Unexpected error codes:
+   * - ErrorCode::ClientError Error that happen inside the Vereign Client Library
+   * - ErrorCode::UnexpectedError Should never happen.
+   *
+   * Error codes of interest:
+   * - ErrorCode::InvalidPinCode The pin code is invalid, currently during the registration an empty
+   *    pin code is considered invalid.
+   */
   auto LoginWithNewDevice(
     ::grpc::ServerContext* ctx,
     const client_library::LoginFormNewDevice* req,
@@ -55,6 +87,24 @@ public:
     return ::grpc::Status::OK;
   }
 
+  /**
+   * Login with already registered device.
+   *
+   * req.pin is required only under Linux.
+   *
+   * Under windows the system cypto storage is used.
+   * When the device is registered a master key is created and the user will be asked for his
+   * consent by showing a dialog window.
+   *
+   * Unexpected error codes:
+   * - ErrorCode::ClientError Error that happen inside the Vereign Client Library
+   * - ErrorCode::UnexpectedError Should never happen.
+   *
+   * Error codes of interest:
+   * - ErrorCode::DeviceNotRegistered The device is not registered.
+   * - ErrorCode::InvalidPinCode The pin code is invalid and the crypto storage cannot be unlocked.
+   * - ErrorCode::InvalidIdentity Under windows if for some reason the RSA master key has been changed.
+   */
   auto LoginWithPreviouslyAddedDevice(
     ::grpc::ServerContext* ctx,
     const client_library::LoginFormPreviousAddedDevice* req,
diff --git a/cpp/src/vereign/identity/provider.cc b/cpp/src/vereign/identity/provider.cc
index dd19a5f9b2c37f4c42ab6d181e7ee5e4c500b732..94f761b13126efb50a16b4c279bb1fd6dbd35416 100644
--- a/cpp/src/vereign/identity/provider.cc
+++ b/cpp/src/vereign/identity/provider.cc
@@ -1,6 +1,6 @@
-#include "vereign/crypto/digest.hh"
 #include <vereign/identity/provider.hh>
 
+#include <vereign/crypto/digest.hh>
 #include <vereign/crypto/bio.hh>
 #include <vereign/crypto/rsa.hh>
 #include <vereign/encoding/base64.hh>
diff --git a/cpp/src/vereign/identity/provider.hh b/cpp/src/vereign/identity/provider.hh
index 80e17200920a334a7efd5f99ab84a6088971cc94..60003b4afef49775a37c94d17943213b995b9ac2 100644
--- a/cpp/src/vereign/identity/provider.hh
+++ b/cpp/src/vereign/identity/provider.hh
@@ -7,20 +7,62 @@
 
 namespace vereign::identity {
 
+/**
+ * Identity provider that manages the locally stored user identity.
+ *
+ * All public methods are thread safe.
+ */
 class Provider {
 public:
+  /**
+   * Creates Provider instance.
+   *
+   * @param storage The crypto storage used for read/write identity properties.
+   */
   Provider(kvstore::CryptoStorage& storage);
 
+  /**
+   * Default constructor.
+   *
+   * Does nothing.
+   */
+  ~Provider();
+
   // disable copying
   Provider(const kvstore::Storage&) = delete;
   auto operator=(const kvstore::Storage&) -> Provider& = delete;
 
+  /**
+   * Replaces the current identity.
+   *
+   * @param pin Required only under Linux. The pin code used for derivation of the crypto storage
+   *    master key.
+   *
+   * @returns The base64 encoded PEM encoded identity public key.
+   */
   auto ResetIdentity(const std::string& pin) -> std::string;
+
+  /**
+   * Loads the local identity.
+   *
+   * @param pin Required only under Linux. The pin code used for derivation of the crypto storage
+   *    master key.
+   *
+   * @returns The base64 encoded PEM encoded identity public key.
+   */
   auto LoadIdentity(const std::string& pin) -> std::string;
+
+  /**
+   * Retrieve identity public key.
+   *
+   * @returns The base64 encoded PEM encoded identity public key.
+   */
   auto GetIdentityPublicKeyBase64() -> std::string;
-  auto GetDeviceHash() -> std::string;
 
-  ~Provider();
+  /**
+   * @returns base64 encoded SHA1 hash of the identity public key.
+   */
+  auto GetDeviceHash() -> std::string;
 
 private:
   std::mutex mu_;
diff --git a/cpp/src/vereign/kvstore/lock.hh b/cpp/src/vereign/kvstore/lock.hh
index 38d0d47da88f32e4d117c23530712080456192a6..1989b1dd0376353417224edfd29c249c1fae4108 100644
--- a/cpp/src/vereign/kvstore/lock.hh
+++ b/cpp/src/vereign/kvstore/lock.hh
@@ -6,12 +6,40 @@
 
 namespace vereign::kvstore {
 
+/**
+ * Lock guard used for lock/unlock Storage within a scope.
+ *
+ * When the Lock is constructed it locks the Storage, and when it is destroyed it unlock it.
+ */
 class Lock {
 public:
+  /**
+   * Creates a Lock and locks the Storage.
+   *
+   * @param storage The storage to lock.
+   * @throws LockError when the lock is held by another process.
+   */
   explicit Lock(Storage& storage);
+
+  /**
+   * Creates a Lock and locks the Storage.
+   *
+   * If the lock is not possible it retries `retry_count` and sleeps between retries `sleep_interval`.
+   *
+   * @param storage The storage to lock.
+   * @param retry_count How many times to retry if the lock is held by another process.
+   * @param sleep_interval How many time to sleep between retries.
+   *
+   * @throws LockError If the lock could not be held after `retry_count` retries.
+   */
   Lock(Storage& storage, int retry_count, std::chrono::milliseconds sleep_interval);
+
+  /**
+   * Unlocks the storage.
+   */
   ~Lock() noexcept;
 
+  // copying is disabled.
   Lock(const Lock&) = delete;
   auto operator=(const Lock&) -> Lock&  = delete;
 
diff --git a/cpp/src/vereign/kvstore/sqlite_storage.hh b/cpp/src/vereign/kvstore/sqlite_storage.hh
index b07f39f49921b46d4fb7620f8624fac51ffcc5ef..6f7d13992cb82dd6c1507e1f66183da9ca4a5012 100644
--- a/cpp/src/vereign/kvstore/sqlite_storage.hh
+++ b/cpp/src/vereign/kvstore/sqlite_storage.hh
@@ -6,23 +6,96 @@
 
 namespace vereign::kvstore {
 
+/**
+ * Sqlite implementation of the kvstore::Storage interface.
+ */
 class SqliteStorage : public Storage {
 public:
+  /**
+   * Creates SqliteStorage instance.
+   *
+   * @param db_path Full path to the sqlite database file.
+   */
   SqliteStorage(const std::string& db_path);
+
+  /**
+   * Closes the connection with the database.
+   */
   ~SqliteStorage() override;
 
+  // disable copying
   SqliteStorage(const SqliteStorage&) = delete;
   auto operator=(const SqliteStorage&) -> SqliteStorage& = delete;
 
+  /**
+   * Locks the storage.
+   *
+   * The lock must be recursive, meaning that may be called multiple times.
+   * Storage::Unlock must be called the same number of times the Storage::Lock was called.
+   *
+   * Use kvstore::Lock for lock guard and lock with retrials.
+   *
+   * @throws LockError when the lock is held by another process.
+   */
   void Lock() override;
+
+  /**
+   * Locks the storage.
+   *
+   * The lock must be recursive, meaning that may be called multiple times.
+   * Storage::Unlock must be called the same number of times the Storage::Lock was called.
+   *
+   * Use kvstore::Lock for lock guard and lock with retrials.
+   */
   void Unlock() override;
 
+  /**
+   * Deletes all the values in the storage.
+   *
+   * @throws sqlite::Error on failure.
+   */
   void DeleteAll() override;
 
+  /**
+   * Store bytes value into the storage.
+   *
+   * @param key The key under which the value will be stored.
+   * @param value The bytes that will be stored.
+   *
+   * @throws sqlite::Error on failure.
+   */
   void PutBytes(const std::string& key, bytes::View value) override;
+
+  /**
+   * Retrieve bytes value from the storage.
+   *
+   * @param key The key of the value that will be retrieved.
+   * @param value Buffer where the value will be returned.
+   *
+   * @throws ValueNotFoundError when the key does not exist.
+   * @throws sqlite::Error on failure.
+   */
   void GetBytes(const std::string& key, bytes::Buffer& value) override;
 
+  /**
+   * Store int64_t value into the storage.
+   *
+   * @param key The key under which the value will be stored.
+   * @param value The value that will be stored.
+   *
+   * @throws sqlite::Error on failure.
+   */
   void PutInt64(const std::string& key, int64_t value) override;
+
+  /**
+   * Retrieve int64_t value from the storage.
+   *
+   * @param key The key of the value that will be retrieved.
+   * @param value Buffer where the value will be returned.
+   *
+   * @throws ValueNotFoundError when the key does not exist.
+   * @throws sqlite::Error on failure.
+   */
   auto GetInt64(const std::string& key) -> int64_t override;
 
 private:
diff --git a/cpp/src/vereign/kvstore/storage.hh b/cpp/src/vereign/kvstore/storage.hh
index a190bd54fc573ff0512c80e10f7283cbd88e9542..2e8c55344f0c8481e924fb0c4673e263faa05585 100644
--- a/cpp/src/vereign/kvstore/storage.hh
+++ b/cpp/src/vereign/kvstore/storage.hh
@@ -5,21 +5,80 @@
 
 namespace vereign::kvstore {
 
+// The vereign RSA master key name.
 constexpr const auto VereignKeyName = std::string_view{"vereign_key"};
 
+/**
+ * Key/value storage interface.
+ */
 class Storage {
 public:
+  /**
+   * Locks the storage.
+   *
+   * The lock must be recursive, meaning that may be called multiple times.
+   * Storage::Unlock must be called the same number of times the Storage::Lock was called.
+   *
+   * Use kvstore::Lock for lock guard and lock with retrials.
+   *
+   * @throws LockError when the lock is held by another process.
+   */
   virtual void Lock() = 0;
+
+  /**
+   * Locks the storage.
+   *
+   * The lock must be recursive, meaning that may be called multiple times.
+   * Storage::Unlock must be called the same number of times the Storage::Lock was called.
+   *
+   * Use kvstore::Lock for lock guard and lock with retrials.
+   */
   virtual void Unlock() = 0;
 
+  /**
+   * Deletes all the values in the storage.
+   */
   virtual void DeleteAll() = 0;
 
+  /**
+   * Store bytes value into the storage.
+   *
+   * @param key The key under which the value will be stored.
+   * @param value The bytes that will be stored.
+   */
   virtual void PutBytes(const std::string& key, bytes::View value) = 0;
+
+  /**
+   * Retrieve bytes value from the storage.
+   *
+   * @param key The key of the value that will be retrieved.
+   * @param value Buffer where the value will be returned.
+   *
+   * @throws ValueNotFoundError when the key does not exist.
+   */
   virtual void GetBytes(const std::string& key, bytes::Buffer& value) = 0;
 
+  /**
+   * Store int64_t value into the storage.
+   *
+   * @param key The key under which the value will be stored.
+   * @param value The value that will be stored.
+   */
   virtual void PutInt64(const std::string& key, int64_t value) = 0;
+
+  /**
+   * Retrieve int64_t value from the storage.
+   *
+   * @param key The key of the value that will be retrieved.
+   * @param value Buffer where the value will be returned.
+   *
+   * @throws ValueNotFoundError when the key does not exist.
+   */
   virtual auto GetInt64(const std::string& key) -> int64_t = 0;
 
+  /**
+   * Destroy and cleanup.
+   */
   virtual ~Storage() = default;
 };
 
diff --git a/cpp/src/vereign/service/identity_service.hh b/cpp/src/vereign/service/identity_service.hh
index 51a77b4b5282505ecac78655698dfbd722af6544..11de3e0f5318535d3d7307d126aa19d590141ea6 100644
--- a/cpp/src/vereign/service/identity_service.hh
+++ b/cpp/src/vereign/service/identity_service.hh
@@ -23,24 +23,73 @@ using Result = restapi::PostResult<Request, Response>;
 
 class IdentityService : public gen::IdentityService {
 public:
+  /**
+   * Creates IdentityService instance.
+   *
+   * @param client_session HTTP client used for communicating with the Vereign Restful API.
+   * @param identity_provider Local identity provider (manager).
+   */
   IdentityService(
     restapi::ClientSession& client_session,
     identity::Provider& identity_provider
   );
 
+  // disable copying
   IdentityService(const IdentityService&) = delete;
   auto operator=(const IdentityService&) -> IdentityService& = delete;
 
+  /**
+   * Login with existing identity public key.
+   *
+   * This API is for test purposes only. It is not exposed under the gRPC API, and thus is not
+   * accessible by the integrators.
+   *
+   * **WARN: do not use this in production code**
+   */
   void LoginWithExistingPubKey(
     const client_library::LoginWithExistingPubKeyForm* req,
     client_library::EmptyResponse* resp
   );
 
+  /**
+   * Registers a new device.
+   *
+   * req.pin is required only under Linux.
+   *
+   * Under windows the system cypto storage is used.
+   * When the device is registered a master key is created and the user will be asked for his
+   * consent by showing a dialog window.
+   *
+   * @param req Login request.
+   * @param resp Operation response.
+   *
+   * @throws kvstore::InvalidPinCodeError Only under Linux. Thrown when the provided pin is invalid,
+   *    currently that is when the pin is empty.
+   */
   void LoginWithNewDevice(
     const client_library::LoginFormNewDevice* req,
     client_library::LoginFormNewDeviceResponse* resp
   );
 
+  /**
+   * Login with already registered device.
+   *
+   * req.pin is required only under Linux.
+   *
+   * Under windows the system cypto storage is used.
+   * When the device is registered a master key is created and the user will be asked for his
+   * consent by showing a dialog window.
+   *
+   * @param req Login request.
+   * @param resp Operation response.
+   *
+   * @throws kvstore::StorageNotInitializedError when the crypto storage is empty, meaning that
+   *    the device is not registered.
+   * @throws kvstore::InvalidPinCodeError under Linux, when the provided pin is invalid, meaning
+   *    that the pin does not match the pin used during the registration.
+   * @throws kvstore::InvalidIdentityError under windows, when for some reason the RSA master key
+   *    has been changed.
+   */
   void LoginWithPreviouslyAddedDevice(
     const client_library::LoginFormPreviousAddedDevice* req,
     client_library::EmptyResponse* resp