diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -31,3 +31,6 @@
 ```
 qrpipe read "nametag.png"
 ```
+
+## Library
+The library can be used via the exported functions `createQRCode`, `byteStringToQR` and `readQRString`, plus their signed counterparts. 
diff --git a/qr-imager.cabal b/qr-imager.cabal
--- a/qr-imager.cabal
+++ b/qr-imager.cabal
@@ -1,5 +1,5 @@
 name:                qr-imager
-version:             0.1.2.1
+version:             0.2.0.0
 synopsis:            Library to generate QR codes from bytestrings and objects
 description:         Please see README.md
 homepage:            https://github.com/vmchale/QRImager#readme
diff --git a/src/Data/QRCodes.hs b/src/Data/QRCodes.hs
--- a/src/Data/QRCodes.hs
+++ b/src/Data/QRCodes.hs
@@ -2,11 +2,13 @@
 {-# LANGUAGE FlexibleContexts #-}
 
 -- | Module providing several functions for creating QR codes and their signed counterparts
-module Data.QRCodes ( createSecureQRCode
+module Data.QRCodes (-- * Functions on objects
+                      createSecureQRCode
                     , createQRCode
+                    -- * Functions for `ByteStrings`
                     , byteStringToQR
                     , byteStringToQRSec
-                    -- * functions to read in QR codes with the Zbar library
+                    -- * functions to read QR codes
                     , readQRString
                     , readQRStrSec
                     ) where
@@ -25,15 +27,20 @@
 import Data.QRCodes.Signature
 import Data.QRCodes.Image
 
--- | Creates a signed QR code from a strict bytestring
-byteStringToQRSec :: BS.ByteString -> FilePath -> IO ()
-byteStringToQRSec string filepath = (flip byteStringToQR filepath) =<< (((fmap preserveUpper) . mkSig) string)
+-- | Creates a signed QR code from a strict bytestring and path to keyfile/path where the keyfile should be generated.
+-- Note that QR codes may only contain a small number of characters, so encrypting can sometimes make an object too big to encode.
+--
+-- > byteStringToQRSec (BS.pack "hello") ".key.hk" "qrcode.png"
+byteStringToQRSec :: BS.ByteString -> FilePath -> FilePath -> IO ()
+byteStringToQRSec string keyfile filepath = (flip byteStringToQR filepath) =<< (((fmap preserveUpper) . (flip mkSig keyfile)) string)
 
 -- | Creates a signed QR code from an object that is part of the ToJSON class
-createSecureQRCode :: (ToJSON a) => a -> FilePath -> IO ()
+createSecureQRCode :: (ToJSON a) => a -> FilePath -> FilePath -> IO ()
 createSecureQRCode object = byteStringToQRSec (toStrict $ encode object)
 
 -- | Creates a QR code from an object that is part of the ToJSON class
+--
+-- > createQRCode userRecord "user-231.png"
 createQRCode :: (ToJSON a) => a -> FilePath -> IO ()
 createQRCode object filepath = let input = toStrict $ encode object in byteStringToQR input filepath
 
@@ -45,11 +52,15 @@
     writePng filepath (encodePng qrMatrix)
 
 -- | given a filepath, read the QR code as a string in all lowercase
+--
+-- > readQRString "picture.jpg"
 readQRString :: FilePath -> IO String
 readQRString filepath = (map toLower) . init . (drop 8 . view _2) <$> readCreateProcessWithExitCode (shell $ "zbarimg " ++ filepath) ""
 
--- | given a filepath pointing to a QR code, get the contents & verify signature
-readQRStrSec :: FilePath -> IO String
-readQRStrSec filepath = do
+-- | given a filepath pointing to a QR code, get the contents & verify signature with the keyfile
+--
+-- > readQRStrSec "output.png" ".key.hk"
+readQRStrSec :: FilePath -> FilePath -> IO String
+readQRStrSec filepath keyfile = do
     enc <- (map toLower) . init . (drop 8) . (view _2) <$> readCreateProcessWithExitCode (shell $ "zbarimg " ++ filepath) ""
-    (fmap $ liftEither show) . checkSig . resolveUpper $ (BS.pack) enc
+    (fmap $ liftEither show) . (flip checkSig keyfile) . resolveUpper $ (BS.pack) enc
diff --git a/src/Data/QRCodes/Exe.hs b/src/Data/QRCodes/Exe.hs
--- a/src/Data/QRCodes/Exe.hs
+++ b/src/Data/QRCodes/Exe.hs
@@ -1,5 +1,5 @@
 -- | Parse options applicatively and read or write secure or non-secure QR codes.
-module Data.QRCodes.Exe (exec) where
+module Data.QRCodes.Exe where
 
 import Options.Applicative
 import qualified Data.ByteString as B
@@ -28,20 +28,20 @@
 act :: Prog -> IO ()
 act (Prog Output True True filepath) = do
     pipeIn <- B.getContents
-    byteStringToQRSec pipeIn filepath
-    readQRStrSec filepath >>= print
+    byteStringToQRSec pipeIn ".key.hk" filepath
+    readQRStrSec filepath ".key.hk" >>= print
 act (Prog Output False True filepath) = do
     pipeIn <- B.getContents
     byteStringToQR pipeIn filepath
     readQRString filepath >>= print
 act (Prog Output True False filepath) = do
     pipeIn <- B.getContents
-    byteStringToQRSec pipeIn filepath
+    byteStringToQRSec pipeIn ".key.hk" filepath
 act (Prog Output False False filepath) = do
     pipeIn <- B.getContents
     byteStringToQR pipeIn filepath
 act (Prog Input True _ filepath) = do
-    readQRStrSec filepath >>= print
+    readQRStrSec filepath ".key.hk" >>= print
 act (Prog Input False _ filepath) = do
     readQRString filepath >>= print
 
diff --git a/src/Data/QRCodes/Signature.hs b/src/Data/QRCodes/Signature.hs
--- a/src/Data/QRCodes/Signature.hs
+++ b/src/Data/QRCodes/Signature.hs
@@ -1,3 +1,4 @@
+-- | Functions associated with signing the JSON records
 module Data.QRCodes.Signature where
 
 import Jose.Jws
@@ -9,24 +10,24 @@
 import Jose.Jwa (JwsAlg (RS256))
 import Data.QRCodes.Utils
 
--- | Verify a signed token
-checkSig :: BS.ByteString -> IO (Either JwtError BS.ByteString)
-checkSig tok = do
-    key <- read <$> readFile ".key.hk" :: IO (Cr.PublicKey, Cr.PrivateKey)
+-- | Verify a signed token with a key from a given filepath
+checkSig :: BS.ByteString -> FilePath -> IO (Either JwtError BS.ByteString)
+checkSig tok filepath = do
+    key <- read <$> readFile filepath :: IO (Cr.PublicKey, Cr.PrivateKey)
     let jws = rsaDecode (view _1 key) tok
     return $ fmap (view _2) jws
 
--- | Sign a token (note that we must pass in a processed token since there is no uppercase/lowercase here)
-mkSig :: BS.ByteString -> IO BS.ByteString
-mkSig string = do
-    switch <- doesFileExist ".key.hk"
+-- | Sign a token (note that we must pass in a processed token since there is no uppercase/lowercase here) with a key from a given filepath
+mkSig :: BS.ByteString -> FilePath -> IO BS.ByteString
+mkSig string filepath = do
+    switch <- doesFileExist filepath
     if not switch then do
         putStrLn "generating key..."
         key <- Cr.generate 256 0x10001
-        writeFile ".key.hk" (show key)
+        writeFile filepath (show key)
     else
         return ()
-    key' <- read <$> readFile ".key.hk" :: IO (Cr.PublicKey, Cr.PrivateKey)
+    key' <- read <$> readFile filepath :: IO (Cr.PublicKey, Cr.PrivateKey)
     signedToken <- rsaEncode RS256 (view _2 key') string
     let signed = fmap unJwt signedToken
     liftEither id (return <$> signed)
diff --git a/src/Data/QRCodes/Utils.hs b/src/Data/QRCodes/Utils.hs
--- a/src/Data/QRCodes/Utils.hs
+++ b/src/Data/QRCodes/Utils.hs
@@ -1,3 +1,4 @@
+-- | Miscellaneous helper functions that don't fit anywhere else
 module Data.QRCodes.Utils where
 
 import qualified Data.ByteString.Char8 as BS
@@ -14,9 +15,11 @@
 resolveUpper = lift rU
     where rU = foldr (.) id (map (\s -> replace (s : "!") ((pure . toUpper) s)) ['a'..'z'])
 
+-- | given a function on strings, make it act on byteStrings
 lift :: (String -> String) -> (BS.ByteString -> BS.ByteString)
 lift f = BS.pack . f . BS.unpack
 
+-- | helper function to life Either values to IO in our case
 liftEither :: (Show b, Monad m) => (t -> m a) -> Either b t -> m a
 liftEither = either (error . show)
 
