diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,12 @@
 
 ## [Unreleased]
 
+## [0.5.0] - 2020-11-06
+
+- Rewrite, cachix-api now serves as the base for cachix package but doesn't contain the full HTTP API anymore.
+  This is mainly to improve development feedback loop of the backend.
+  See https://app.cachix.org/api/v1/ for the full HTTP API spec.
+
 ## [0.4.0] - 2020-01-10
 
 - #249 Serve nar content
diff --git a/cachix-api.cabal b/cachix-api.cabal
--- a/cachix-api.cabal
+++ b/cachix-api.cabal
@@ -1,12 +1,13 @@
 cabal-version:      2.2
 name:               cachix-api
-version: 0.4.0
+version: 0.5.0
 synopsis:           Servant HTTP API specification for https://cachix.org
 homepage:           https://github.com/cachix/cachix#readme
 bug-reports:        https://github.com/cachix/cachix/issues
 author:             Domen Kožar
 maintainer:         domen@enlambda.com
 copyright:          2018 Domen Kožar
+category:           Nix
 license:            Apache-2.0
 license-file:       LICENSE
 build-type:         Simple
@@ -36,29 +37,29 @@
 library
   import:          defaults
   exposed-modules:
-    Cachix.Api
-    Cachix.Api.Error
-    Cachix.Api.Signing
-    Cachix.Api.Types
-    Cachix.Types.BinaryCacheAuthenticated
-    Cachix.Types.BinaryCacheCreate
+    Cachix.API
+    Cachix.API.Error
+    Cachix.API.Signing
+    Cachix.Types.BinaryCache
+    Cachix.Types.ByteStringStreaming
     Cachix.Types.ContentTypes
-    Cachix.Types.CreateToken
-    Cachix.Types.GitHubTeam
     Cachix.Types.NarFileName
+    Cachix.Types.NarInfo
     Cachix.Types.NarInfoCreate
+    Cachix.Types.NarInfoHash
+    Cachix.Types.NixCacheInfo
+    Cachix.Types.Permission
     Cachix.Types.Servant
     Cachix.Types.Session
     Cachix.Types.SigningKeyCreate
-    Cachix.Types.SwaggerOrphans
 
   hs-source-dirs:  src
   build-depends:
     , aeson
-    , base                  >=4.7    && <5
+    , base                 >=4.7    && <5
     , base16-bytestring
     , bytestring
-    , conduit               >=1.3.0
+    , conduit              >=1.3.0
     , cookie
     , cryptonite
     , deepseq
@@ -68,28 +69,18 @@
     , jose
     , lens
     , memory
+    , nix-narinfo
     , protolude
     , resourcet
-    , servant               >=0.14.1
+    , servant              >=0.14.1
     , servant-auth
     , servant-auth-server
-    , servant-auth-swagger
     , servant-client
-    , servant-swagger
     , string-conv
     , swagger2
     , text
+    , time
     , transformers
-
-executable cachix-gen-swagger
-  import:         defaults
-  main-is:        Main.hs
-  hs-source-dirs: cachix-gen-swagger
-  build-depends:
-    , aeson
-    , base        >=4.7 && <5
-    , cachix-api
-    , protolude
 
 test-suite cachix-api-test
   import:             defaults
diff --git a/cachix-gen-swagger/Main.hs b/cachix-gen-swagger/Main.hs
deleted file mode 100644
--- a/cachix-gen-swagger/Main.hs
+++ /dev/null
@@ -1,8 +0,0 @@
-module Main (main) where
-
-import Cachix.Api (swaggerDoc)
-import Data.Aeson (encode)
-import Protolude
-
-main :: IO ()
-main = print $ encode swaggerDoc
diff --git a/src/Cachix/API.hs b/src/Cachix/API.hs
new file mode 100644
--- /dev/null
+++ b/src/Cachix/API.hs
@@ -0,0 +1,132 @@
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE TypeOperators #-}
+
+module Cachix.API
+  ( api,
+    BinaryCacheAPI (..),
+    API,
+    CachixAuth,
+  )
+where
+
+import qualified Cachix.Types.BinaryCache as BinaryCache
+import qualified Cachix.Types.ByteStringStreaming as ByteStringStreaming
+import Cachix.Types.ContentTypes
+import Cachix.Types.NarFileName (NarFileName (..))
+import qualified Cachix.Types.NarInfo as NarInfo
+import qualified Cachix.Types.NarInfoCreate as NarInfoCreate
+import qualified Cachix.Types.NarInfoHash as NarInfoHash
+import qualified Cachix.Types.NixCacheInfo as NixCacheInfo
+import Cachix.Types.Servant (Head)
+import Cachix.Types.Session (Session)
+import qualified Cachix.Types.SigningKeyCreate as SigningKeyCreate
+import Control.Monad.Trans.Resource
+import Data.Conduit (ConduitT)
+import Protolude
+import Servant.API hiding (BasicAuth)
+import Servant.API.Generic
+import Servant.Auth
+
+type CachixAuth = Auth '[Cookie, JWT, BasicAuth] Session
+
+-- Nix CLI + Cachix CLI
+data BinaryCacheAPI route
+  = BinaryCacheAPI
+      { -- https://cache.nixos.org/nix-cache-info
+        nixCacheInfo ::
+          route
+            :- CachixAuth
+            :> "cache"
+            :> Capture "name" Text
+            :> "nix-cache-info"
+            :> Get '[XNixCacheInfo, JSON] NixCacheInfo.NixCacheInfo,
+        -- Hydra: src/lib/Hydra/View/NARInfo.pm
+        narinfo ::
+          route
+            :- CachixAuth
+            :> "cache"
+            :> Capture "name" Text
+            :> Capture "narinfohash" NarInfoHash.NarInfoHash
+            :> Get '[XNixNarInfo, JSON] NarInfo.CachixNarInfo,
+        narinfoHead ::
+          route
+            :- CachixAuth
+            :> "cache"
+            :> Capture "name" Text
+            :> Capture "narinfohash" NarInfoHash.NarInfoHash
+            :> Head,
+        -- Hydra: src/lib/Hydra/View/NixNAR.pm
+        nar ::
+          route
+            :- CachixAuth
+            :> "cache"
+            :> Capture "name" Text
+            :> "nar"
+            :> Capture "nar" NarFileName
+            :> StreamGet NoFraming XNixNar (ConduitT () ByteStringStreaming.ByteStringStreaming (ResourceT IO) ()),
+        -- cachix specific
+        getCache ::
+          route
+            :- CachixAuth
+            :> "cache"
+            :> Capture "name" Text
+            :> Get '[JSON] BinaryCache.BinaryCache,
+        narinfoBulk ::
+          route
+            :- CachixAuth
+            :> "cache"
+            :> Capture "name" Text
+            :> "narinfo"
+            :> Summary "Given a list of store hashes, return a list of those that are missing"
+            :> ReqBody '[JSON] [Text]
+            :> Post '[JSON] [Text],
+        narURL ::
+          route
+            :- CachixAuth
+            :> "cache"
+            :> Capture "name" Text
+            :> "narurl"
+            :> Capture "nar" NarFileName
+            :> Get '[JSON] Text,
+        createNarinfo ::
+          route
+            :- CachixAuth
+            :> "cache"
+            :> Capture "name" Text
+            :> Capture "narinfohash" NarInfoHash.NarInfoHash
+            :> ReqBody '[JSON] NarInfoCreate.NarInfoCreate
+            :> Post '[JSON] NoContent,
+        createNar ::
+          route
+            :- CachixAuth
+            :> "cache"
+            :> Capture "name" Text
+            :> "nar"
+            :> StreamBody NoFraming XNixNar (ConduitT () ByteStringStreaming.ByteStringStreaming (ResourceT IO) ())
+            :> Post '[JSON] NoContent,
+        serveNarContent ::
+          route
+            :- CachixAuth
+            :> "cache"
+            :> Capture "name" Text
+            :> "serve"
+            :> Capture "storehash" Text
+            :> CaptureAll "filepath" Text
+            :> Summary "Serve a file from a given store path"
+            :> Get '[XNixNar] (Headers '[Header "X-Content-Type-Options" Text] ByteStringStreaming.LazyByteStringStreaming),
+        createKey ::
+          route
+            :- CachixAuth
+            :> "cache"
+            :> Capture "name" Text
+            :> "key"
+            :> ReqBody '[JSON] SigningKeyCreate.SigningKeyCreate
+            :> Post '[JSON] NoContent
+      }
+  deriving (Generic)
+
+type API = "api" :> "v1" :> ToServantApi BinaryCacheAPI
+
+api :: Proxy API
+api = Proxy
diff --git a/src/Cachix/API/Error.hs b/src/Cachix/API/Error.hs
new file mode 100644
--- /dev/null
+++ b/src/Cachix/API/Error.hs
@@ -0,0 +1,25 @@
+module Cachix.API.Error
+  ( escalate,
+    escalateAs,
+  )
+where
+
+import Control.Monad.Catch (MonadThrow (throwM))
+import Protolude
+
+-- | Examples:
+--    > escalate . maybeToEither err404
+--
+--  | Note that exceptions gets handled by warp and logged (user sees just "Internal server")
+escalateAs ::
+  (Exception exc, MonadThrow m) =>
+  (l -> exc) ->
+  Either l a ->
+  m a
+escalateAs f = either (throwM . f) pure
+
+escalate ::
+  (Exception exc, MonadThrow m) =>
+  Either exc a ->
+  m a
+escalate = escalateAs identity
diff --git a/src/Cachix/API/Signing.hs b/src/Cachix/API/Signing.hs
new file mode 100644
--- /dev/null
+++ b/src/Cachix/API/Signing.hs
@@ -0,0 +1,45 @@
+module Cachix.API.Signing
+  ( fingerprint,
+    passthroughSizeSink,
+    passthroughHashSinkB16,
+    passthroughHashSink,
+  )
+where
+
+import Crypto.Hash
+import qualified Data.ByteArray as BA
+import Data.ByteArray.Encoding (Base (..), convertToBase)
+import qualified Data.ByteString as BS
+import Data.Conduit
+import qualified Data.Conduit.Combinators as CC
+import Data.IORef
+import qualified Data.Text as T
+import Protolude
+
+-- perl/lib/Nix/Manifest.pm:fingerprintPath
+-- NB: references must be sorted
+fingerprint :: Text -> Text -> Integer -> [Text] -> ByteString
+fingerprint storePath narHash narSize references =
+  toS $
+    T.intercalate
+      ";"
+      ["1", storePath, narHash, show narSize, T.intercalate "," references]
+
+-- Useful sinks for streaming nars
+sizeSink :: MonadIO m => ConduitT ByteString o m Integer
+sizeSink = CC.foldM (\p n -> return (p + fromIntegral (BS.length n))) 0
+
+hashSink :: MonadIO m => ConduitT ByteString o m (Context SHA256)
+hashSink = CC.foldM (\p n -> return (hashUpdate p n)) hashInit
+
+passthroughSizeSink :: MonadIO m => IORef Integer -> ConduitT ByteString ByteString m ()
+passthroughSizeSink ioref = passthroughSink sizeSink (liftIO . writeIORef ioref)
+
+passthroughHashSinkBase :: MonadIO m => (Digest SHA256 -> ByteString) -> IORef ByteString -> ConduitT ByteString ByteString m ()
+passthroughHashSinkBase f ioref = passthroughSink hashSink (liftIO . writeIORef ioref . f . hashFinalize)
+
+passthroughHashSink :: MonadIO m => IORef ByteString -> ConduitT ByteString ByteString m ()
+passthroughHashSink = passthroughHashSinkBase BA.convert
+
+passthroughHashSinkB16 :: MonadIO m => IORef ByteString -> ConduitT ByteString ByteString m ()
+passthroughHashSinkB16 = passthroughHashSinkBase (convertToBase Base16)
diff --git a/src/Cachix/Api.hs b/src/Cachix/Api.hs
deleted file mode 100644
--- a/src/Cachix/Api.hs
+++ /dev/null
@@ -1,235 +0,0 @@
-{-# LANGUAGE DataKinds #-}
-{-# LANGUAGE DeriveGeneric #-}
-{-# LANGUAGE TypeOperators #-}
-
-module Cachix.Api
-  ( servantApi,
-    swaggerDoc,
-    CachixAPI (..),
-    CachixServantAPI,
-    CachixAuth,
-    InstallAPI (..),
-    GitHubAPI (..),
-    BinaryCacheAPI (..),
-    BinaryCacheStreamingAPI (..),
-    BinaryCachStreamingServantAPI,
-    module Cachix.Api.Types,
-    module Cachix.Types.ContentTypes,
-    module Cachix.Types.NarFileName,
-  )
-where
-
-import Cachix.Api.Types
-import qualified Cachix.Types.BinaryCacheAuthenticated as BinaryCacheAuthenticated
-import qualified Cachix.Types.BinaryCacheCreate as BinaryCacheCreate
-import Cachix.Types.ContentTypes
-import qualified Cachix.Types.CreateToken as CreateToken
-import qualified Cachix.Types.GitHubTeam as GitHubTeam
-import Cachix.Types.NarFileName (NarFileName (..))
-import qualified Cachix.Types.NarInfoCreate as NarInfoCreate
-import Cachix.Types.Servant (Get302, Head, Post302)
-import Cachix.Types.Session (Session)
-import qualified Cachix.Types.SigningKeyCreate as SigningKeyCreate
-import Cachix.Types.SwaggerOrphans ()
-import Control.Lens
-import Control.Monad.Trans.Resource
-import Data.ByteString (ByteString)
-import qualified Data.ByteString.Lazy as BSL
-import Data.Conduit (ConduitT)
-import Data.Swagger hiding (Header)
-import Protolude
-import Servant.API hiding (BasicAuth)
-import Servant.API.Generic
-import Servant.Auth
-import Servant.Auth.Swagger ()
-import Servant.Swagger
-import Web.Cookie (SetCookie)
-
-type CachixAuth = Auth '[Cookie, JWT, BasicAuth] Session
-
-data BinaryCacheAPI route
-  = BinaryCacheAPI
-      { get ::
-          route
-            :- CachixAuth
-            :> Get '[JSON] BinaryCache,
-        create ::
-          route
-            :- CachixAuth
-            :> ReqBody '[JSON] BinaryCacheCreate.BinaryCacheCreate
-            :> Post '[JSON] NoContent,
-        delete ::
-          route
-            :- CachixAuth
-            :> Delete '[JSON] NoContent,
-        -- https://cache.nixos.org/nix-cache-info
-        nixCacheInfo ::
-          route
-            :- CachixAuth
-            :> "nix-cache-info"
-            :> Get '[XNixCacheInfo, JSON] NixCacheInfo,
-        -- Hydra: src/lib/Hydra/View/NARInfo.pm
-        narinfo ::
-          route
-            :- CachixAuth
-            :> Capture "narinfo" NarInfoC
-            :> Get '[XNixNarInfo, JSON] NarInfo,
-        narinfoHead ::
-          route
-            :- CachixAuth
-            :> Capture "narinfo" NarInfoC
-            :> Head,
-        narinfoBulk ::
-          route
-            :- CachixAuth
-            :> "narinfo"
-            :> Summary "Given a list of store hashes, return a list of those that are missing"
-            :> ReqBody '[JSON] [Text]
-            :> Post '[JSON] [Text],
-        createNarinfo ::
-          route
-            :- Capture "narinfo" NarInfoC
-            :> ReqBody '[JSON] NarInfoCreate.NarInfoCreate
-            :> Post '[JSON] NoContent,
-        createKey ::
-          route
-            :- CachixAuth
-            :> "key"
-            :> ReqBody '[JSON] SigningKeyCreate.SigningKeyCreate
-            :> Post '[JSON] NoContent
-      }
-  deriving (Generic)
-
--- | Streaming endpoints
-data BinaryCacheStreamingAPI route
-  = BinaryCacheStreamingAPI
-      { -- Hydra: src/lib/Hydra/View/NixNAR.pm
-        nar ::
-          route
-            :- CachixAuth
-            :> "nar"
-            :> Capture "nar" NarFileName
-            :> StreamGet NoFraming OctetStream (ConduitT () ByteString (ResourceT IO) ()),
-        createNar ::
-          route
-            :- "nar"
-            :> StreamBody NoFraming XNixNar (ConduitT () ByteString (ResourceT IO) ())
-            :> Post '[JSON] NoContent,
-        serveNarContent ::
-          route
-            :- CachixAuth
-            :> "serve"
-            :> Capture "storehash" Text
-            :> CaptureAll "filepath" Text
-            :> Summary "Serve a file from a given store path"
-            :> Get '[OctetStream] (Headers '[Header "X-Content-Type-Options" Text] BSL.ByteString)
-      }
-  deriving (Generic)
-
-data InstallAPI route
-  = InstallAPI
-      { installGetLatest ::
-          route
-            :- Summary "Redirects to a tarball containing nix expression to build the latest version of cachix cli"
-            :> Get302 '[JSON] '[],
-        installGetVersion ::
-          route
-            :- Summary "Redirects to a tarball containing nix expression to build given version of cachix cli"
-            :> Capture "version" Text
-            :> Get302 '[JSON] '[]
-      }
-  deriving (Generic)
-
-data GitHubAPI route
-  = GitHubAPI
-      { githubOrganizations ::
-          route
-            :- CachixAuth
-            :> "orgs"
-            :> Get '[JSON] [Text],
-        githubTeams ::
-          route
-            :- CachixAuth
-            :> "orgs"
-            :> Capture "org" Text
-            :> "teams"
-            :> Get '[JSON] [GitHubTeam.GitHubTeam]
-      }
-  deriving (Generic)
-
-data CachixAPI route
-  = CachixAPI
-      { logout ::
-          route
-            :- "logout"
-            :> CachixAuth
-            :> Post302 '[JSON]
-                 '[ Header "Set-Cookie" SetCookie,
-                    Header "Set-Cookie" SetCookie
-                  ],
-        login ::
-          route
-            :- "login"
-            :> Get302 '[JSON] '[],
-        loginCallback ::
-          route
-            :- "login"
-            :> "callback"
-            :> QueryParam "code" Text
-            :> QueryParam "state" Text
-            :> Get302 '[JSON]
-                 '[ Header "Set-Cookie" SetCookie,
-                    Header "Set-Cookie" SetCookie
-                  ],
-        user ::
-          route
-            :- CachixAuth
-            :> "user"
-            :> Get '[JSON] User,
-        createToken ::
-          route
-            :- CachixAuth
-            :> "token"
-            :> ReqBody '[JSON] CreateToken.CreateToken
-            :> Post '[JSON] Text,
-        caches ::
-          route
-            :- CachixAuth
-            :> "cache"
-            :> Get '[JSON] [BinaryCacheAuthenticated.BinaryCacheAuthenticated],
-        cache ::
-          route
-            :- "cache"
-            :> Capture "name" Text
-            :> ToServantApi BinaryCacheAPI,
-        install ::
-          route
-            :- "install"
-            :> ToServantApi InstallAPI,
-        github ::
-          route
-            :- "github"
-            :> ToServantApi GitHubAPI
-      }
-  deriving (Generic)
-
-type CachixServantAPI = "api" :> "v1" :> ToServantApi CachixAPI
-
-type BinaryCachStreamingServantAPI =
-  "api" :> "v1" :> "cache" :> Capture "name" Text :> ToServantApi BinaryCacheStreamingAPI
-
-servantApi :: Proxy CachixServantAPI
-servantApi = Proxy
-
-swaggerDoc :: Swagger
-swaggerDoc =
-  toSwagger servantApi
-    & info
-    . title
-    .~ "cachix.org API"
-    & info
-    . version
-    .~ "1.0"
-    & info
-    . description
-    ?~ "TODO"
diff --git a/src/Cachix/Api/Error.hs b/src/Cachix/Api/Error.hs
deleted file mode 100644
--- a/src/Cachix/Api/Error.hs
+++ /dev/null
@@ -1,26 +0,0 @@
-module Cachix.Api.Error
-  ( escalate,
-    escalateAs,
-  )
-where
-
-import Control.Exception (Exception)
-import Control.Monad.Catch (MonadThrow (throwM))
-import Protolude
-
--- | Examples:
---    > escalate . maybeToEither err404
---
---  | Note that exceptions gets handled by warp and logged (user sees just "Internal server")
-escalateAs ::
-  (Exception exc, MonadThrow m) =>
-  (l -> exc) ->
-  Either l a ->
-  m a
-escalateAs f = either (throwM . f) pure
-
-escalate ::
-  (Exception exc, MonadThrow m) =>
-  Either exc a ->
-  m a
-escalate = escalateAs identity
diff --git a/src/Cachix/Api/Signing.hs b/src/Cachix/Api/Signing.hs
deleted file mode 100644
--- a/src/Cachix/Api/Signing.hs
+++ /dev/null
@@ -1,47 +0,0 @@
-module Cachix.Api.Signing
-  ( fingerprint,
-    passthroughSizeSink,
-    passthroughHashSinkB16,
-    passthroughHashSink,
-  )
-where
-
-import Control.Monad.IO.Class (MonadIO, liftIO)
-import Crypto.Hash
-import qualified Data.ByteArray as BA
-import Data.ByteArray.Encoding (Base (..), convertToBase)
-import qualified Data.ByteString as BS
-import Data.ByteString (ByteString)
-import Data.Conduit
-import qualified Data.Conduit.Combinators as CC
-import Data.IORef
-import qualified Data.Text as T
-import Protolude
-
--- perl/lib/Nix/Manifest.pm:fingerprintPath
--- NB: references must be sorted
-fingerprint :: Text -> Text -> Integer -> [Text] -> ByteString
-fingerprint storePath narHash narSize references =
-  toS $
-    T.intercalate
-      ";"
-      ["1", storePath, narHash, show narSize, T.intercalate "," references]
-
--- Useful sinks for streaming nars
-sizeSink :: MonadIO m => ConduitT ByteString o m Integer
-sizeSink = CC.foldM (\p n -> return (p + fromIntegral (BS.length n))) 0
-
-hashSink :: MonadIO m => ConduitT ByteString o m (Context SHA256)
-hashSink = CC.foldM (\p n -> return (hashUpdate p n)) hashInit
-
-passthroughSizeSink :: MonadIO m => IORef Integer -> ConduitT ByteString ByteString m ()
-passthroughSizeSink ioref = passthroughSink sizeSink (liftIO . writeIORef ioref)
-
-passthroughHashSinkBase :: MonadIO m => (Digest SHA256 -> ByteString) -> IORef ByteString -> ConduitT ByteString ByteString m ()
-passthroughHashSinkBase f ioref = passthroughSink hashSink (liftIO . writeIORef ioref . f . hashFinalize)
-
-passthroughHashSink :: MonadIO m => IORef ByteString -> ConduitT ByteString ByteString m ()
-passthroughHashSink = passthroughHashSinkBase BA.convert
-
-passthroughHashSinkB16 :: MonadIO m => IORef ByteString -> ConduitT ByteString ByteString m ()
-passthroughHashSinkB16 = passthroughHashSinkBase (convertToBase Base16)
diff --git a/src/Cachix/Api/Types.hs b/src/Cachix/Api/Types.hs
deleted file mode 100644
--- a/src/Cachix/Api/Types.hs
+++ /dev/null
@@ -1,90 +0,0 @@
-module Cachix.Api.Types where
-
-import Control.DeepSeq (NFData)
-import Data.Aeson (FromJSON, ToJSON)
-import Data.Swagger (ToParamSchema, ToSchema)
-import Data.Text (dropEnd, takeEnd)
-import Protolude
-import Servant.API
-
-data NixCacheInfo
-  = NixCacheInfo
-      { storeDir :: Text,
-        wantMassQuery :: Integer,
-        priority :: Integer
-      }
-  deriving (Generic, Show, FromJSON, ToJSON, ToSchema)
-
--- narinfo url includes storePath hash and .narinfo suffix
-data NarInfo
-  = NarInfo
-      { -- | absolute path of the derivation in nix store
-        storePath :: Text,
-        -- | relative url (to current domain) to download nar file
-        url :: Text,
-        -- | name of the compression algorithm, eg. xz
-        compression :: Text,
-        -- | sha256 hash of the compressed nar file
-        -- NOTE: to compute use "nix-hash --type sha256 --flat"
-        fileHash :: Text,
-        -- | file size of compressed nar file
-        -- NOTE: du -b
-        fileSize :: Integer,
-        -- | sha256 hash of the decompressed nar file
-        -- NOTE: to compute use "nix-hash --type sha256 --flat --base32"
-        narHash :: Text,
-        -- | file size of decompressed nar file
-        -- NOTE: du -b
-        narSize :: Integer,
-        -- | immediate dependencies of the storePath
-        -- NOTE: nix-store -q --references
-        references :: [Text],
-        -- | relative store path (to nix store root) of the deriver
-        -- NOTE: nix-store -q --deriver
-        deriver :: Text,
-        -- | signature of fields: storePath, narHash, narSize, refs
-        sig :: Text
-      }
-  deriving (Generic, Show, FromJSON, ToJSON, ToSchema)
-
-data BinaryCache
-  = BinaryCache
-      { name :: Text,
-        uri :: Text,
-        isPublic :: Bool,
-        publicSigningKeys :: [Text],
-        githubUsername :: Text
-      }
-  deriving (Show, Generic, FromJSON, ToJSON, ToSchema, NFData)
-
-newtype BinaryCacheError
-  = BinaryCacheError
-      { error :: Text
-      }
-  deriving (Generic, FromJSON, ToJSON)
-
--- | Store path hash
-newtype NarInfoC = NarInfoC Text deriving (Generic, ToSchema, ToParamSchema)
-
-instance FromHttpApiData NarInfoC where
-  parseUrlPiece s =
-    if takeEnd 8 s == ".narinfo"
-      then Right $ NarInfoC (dropEnd 8 s)
-      else Left ""
-
-instance ToHttpApiData NarInfoC where
-  toUrlPiece (NarInfoC n) = n <> ".narinfo"
-
-data User
-  = User
-      { fullname :: Maybe Text,
-        username :: Text,
-        email :: Maybe Text,
-        hasOrgsAcccess :: Bool,
-        activeSubscription :: SubscriptionType,
-        subscriptionAccountId :: Maybe Text
-      }
-  deriving (Generic, FromJSON, ToJSON, ToSchema)
-
-data SubscriptionType = Community | Starter | Basic | Pro
-  deriving (Generic, FromJSON, ToJSON, ToSchema, Show, Read)
diff --git a/src/Cachix/Types/BinaryCache.hs b/src/Cachix/Types/BinaryCache.hs
new file mode 100644
--- /dev/null
+++ b/src/Cachix/Types/BinaryCache.hs
@@ -0,0 +1,17 @@
+module Cachix.Types.BinaryCache where
+
+import Cachix.Types.Permission (Permission)
+import Data.Aeson (FromJSON, ToJSON)
+import Data.Swagger (ToSchema)
+import Protolude
+
+data BinaryCache
+  = BinaryCache
+      { name :: Text,
+        uri :: Text,
+        isPublic :: Bool,
+        publicSigningKeys :: [Text],
+        githubUsername :: Text,
+        permission :: Permission
+      }
+  deriving (Show, Generic, FromJSON, ToJSON, ToSchema, NFData)
diff --git a/src/Cachix/Types/BinaryCacheAuthenticated.hs b/src/Cachix/Types/BinaryCacheAuthenticated.hs
deleted file mode 100644
--- a/src/Cachix/Types/BinaryCacheAuthenticated.hs
+++ /dev/null
@@ -1,22 +0,0 @@
-module Cachix.Types.BinaryCacheAuthenticated
-  ( BinaryCacheAuthenticated (..),
-  )
-where
-
-import Data.Aeson
-  ( FromJSON,
-    ToJSON,
-  )
-import Data.Swagger
-import Protolude
-
--- | Binary Cache response content when user is authenticated
-data BinaryCacheAuthenticated
-  = BinaryCacheAuthenticated
-      { name :: Text,
-        uri :: Text,
-        publicSigningKeys :: [Text],
-        isPublic :: Bool,
-        totalFileSize :: Integer
-      }
-  deriving (Show, Generic, FromJSON, ToJSON, ToSchema)
diff --git a/src/Cachix/Types/BinaryCacheCreate.hs b/src/Cachix/Types/BinaryCacheCreate.hs
deleted file mode 100644
--- a/src/Cachix/Types/BinaryCacheCreate.hs
+++ /dev/null
@@ -1,20 +0,0 @@
-module Cachix.Types.BinaryCacheCreate
-  ( BinaryCacheCreate (..),
-  )
-where
-
-import Data.Aeson
-  ( FromJSON,
-    ToJSON,
-  )
-import Data.Swagger
-import Protolude
-
-data BinaryCacheCreate
-  = BinaryCacheCreate
-      { publicSigningKey :: Maybe Text,
-        isPublic :: Bool,
-        githubOrganization :: Maybe Text,
-        githubTeamId :: Maybe Int
-      }
-  deriving (Show, Generic, FromJSON, ToJSON, ToSchema)
diff --git a/src/Cachix/Types/ByteStringStreaming.hs b/src/Cachix/Types/ByteStringStreaming.hs
new file mode 100644
--- /dev/null
+++ b/src/Cachix/Types/ByteStringStreaming.hs
@@ -0,0 +1,15 @@
+module Cachix.Types.ByteStringStreaming where
+
+import qualified Data.ByteString.Lazy as LBS
+import Data.Swagger (NamedSchema (..), ToSchema (..), binarySchema)
+import Protolude
+
+newtype ByteStringStreaming = ByteStringStreaming ByteString
+
+instance ToSchema ByteStringStreaming where
+  declareNamedSchema _ = pure $ NamedSchema (Just "ByteString") binarySchema
+
+newtype LazyByteStringStreaming = LazyByteStringStreaming LBS.ByteString
+
+instance ToSchema LazyByteStringStreaming where
+  declareNamedSchema _ = pure $ NamedSchema (Just "lazyByteString") binarySchema
diff --git a/src/Cachix/Types/ContentTypes.hs b/src/Cachix/Types/ContentTypes.hs
--- a/src/Cachix/Types/ContentTypes.hs
+++ b/src/Cachix/Types/ContentTypes.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 
 module Cachix.Types.ContentTypes
@@ -7,9 +8,11 @@
   )
 where
 
-import Cachix.Api.Types
+import qualified Cachix.Types.ByteStringStreaming as ByteStringStreaming
+import qualified Cachix.Types.NarInfo as NarInfo
+import qualified Cachix.Types.NixCacheInfo as NixCacheInfo
 import qualified Data.ByteString.Lazy as BSL
-import Data.Typeable (Typeable)
+import Data.Coerce (coerce)
 import qualified Network.HTTP.Media as M
 import Protolude
 import Servant.API
@@ -27,16 +30,22 @@
   contentType _ = "text" M.// "x-nix-narinfo"
 
 instance Accept XNixNar where
-  contentType _ = "application" M.// "x-nix-nar"
+  contentType _ = "application" M.// "octet-stream"
 
-instance MimeUnrender XNixCacheInfo NixCacheInfo where
+instance MimeUnrender XNixCacheInfo NixCacheInfo.NixCacheInfo where
   mimeUnrender _ _ = Left "TODO"
 
-instance MimeUnrender XNixNarInfo NarInfo where
+instance MimeUnrender XNixNarInfo NarInfo.CachixNarInfo where
   mimeUnrender _ _ = Left "TODO"
 
-instance MimeRender XNixNar ByteString where
-  mimeRender _ = BSL.fromStrict
+instance MimeRender XNixNar ByteStringStreaming.ByteStringStreaming where
+  mimeRender _ = BSL.fromStrict . coerce
 
-instance MimeUnrender XNixNar ByteString where
-  mimeUnrender _ = Right . BSL.toStrict
+instance MimeUnrender XNixNar ByteStringStreaming.ByteStringStreaming where
+  mimeUnrender _ = Right . coerce . BSL.toStrict
+
+instance MimeUnrender XNixNar ByteStringStreaming.LazyByteStringStreaming where
+  mimeUnrender _ = Right . coerce
+
+instance MimeRender XNixNar ByteStringStreaming.LazyByteStringStreaming where
+  mimeRender _ = coerce
diff --git a/src/Cachix/Types/CreateToken.hs b/src/Cachix/Types/CreateToken.hs
deleted file mode 100644
--- a/src/Cachix/Types/CreateToken.hs
+++ /dev/null
@@ -1,17 +0,0 @@
-module Cachix.Types.CreateToken
-  ( CreateToken (..),
-  )
-where
-
-import Data.Aeson
-  ( FromJSON,
-    ToJSON,
-  )
-import Data.Swagger
-import Protolude
-
-data CreateToken
-  = CreateToken
-      { description :: Text
-      }
-  deriving (Show, Generic, FromJSON, ToJSON, ToSchema)
diff --git a/src/Cachix/Types/GitHubTeam.hs b/src/Cachix/Types/GitHubTeam.hs
deleted file mode 100644
--- a/src/Cachix/Types/GitHubTeam.hs
+++ /dev/null
@@ -1,18 +0,0 @@
-module Cachix.Types.GitHubTeam
-  ( GitHubTeam (..),
-  )
-where
-
-import Data.Aeson
-  ( FromJSON,
-    ToJSON,
-  )
-import Data.Swagger
-import Protolude
-
-data GitHubTeam
-  = GitHubTeam
-      { id :: Int,
-        name :: Text
-      }
-  deriving (Generic, FromJSON, ToJSON, ToSchema)
diff --git a/src/Cachix/Types/NarFileName.hs b/src/Cachix/Types/NarFileName.hs
--- a/src/Cachix/Types/NarFileName.hs
+++ b/src/Cachix/Types/NarFileName.hs
@@ -3,11 +3,12 @@
   )
 where
 
-import Data.Text (dropEnd, takeEnd)
+import Data.Swagger (ToParamSchema (..))
+import qualified Data.Text as T
 import Protolude
 import Servant.API
 
--- | <hash>.nar.xz file
+-- | <hash>.nar.<extension> file
 data NarFileName
   = NarFileName
       { contentHash :: Text,
@@ -17,9 +18,13 @@
 
 instance FromHttpApiData NarFileName where
   parseUrlPiece s =
-    if takeEnd 7 s == ".nar.xz"
-      then Right $ NarFileName (dropEnd 7 s) "xz"
-      else Left "Wrong extension"
+    case T.splitOn "." s of
+      [filename, "nar", ext] ->
+        Right $ NarFileName filename ext
+      _ -> Left $ "Wrong nar filename: " <> s
 
 instance ToHttpApiData NarFileName where
   toUrlPiece narfilename = contentHash narfilename <> ".nar." <> extension narfilename
+
+instance ToParamSchema NarFileName where
+  toParamSchema _ = toParamSchema (Proxy :: Proxy Text)
diff --git a/src/Cachix/Types/NarInfo.hs b/src/Cachix/Types/NarInfo.hs
new file mode 100644
--- /dev/null
+++ b/src/Cachix/Types/NarInfo.hs
@@ -0,0 +1,22 @@
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE StandaloneDeriving #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+
+module Cachix.Types.NarInfo
+  ( CachixNarInfo,
+    NarInfo (..),
+  )
+where
+
+import Data.Aeson (FromJSON, ToJSON)
+import Data.Swagger (ToSchema)
+import Data.Text (Text)
+import Nix.NarInfo (NarInfo (..))
+
+deriving instance ToSchema CachixNarInfo
+
+deriving instance ToJSON CachixNarInfo
+
+deriving instance FromJSON CachixNarInfo
+
+type CachixNarInfo = NarInfo Text Text Text
diff --git a/src/Cachix/Types/NarInfoCreate.hs b/src/Cachix/Types/NarInfoCreate.hs
--- a/src/Cachix/Types/NarInfoCreate.hs
+++ b/src/Cachix/Types/NarInfoCreate.hs
@@ -27,7 +27,7 @@
         cFileSize :: Integer,
         cReferences :: [Text],
         cDeriver :: Text,
-        cSig :: Text
+        cSig :: Maybe Text
       }
   deriving (Generic, Show, FromJSON, ToJSON, ToSchema)
 
diff --git a/src/Cachix/Types/NarInfoHash.hs b/src/Cachix/Types/NarInfoHash.hs
new file mode 100644
--- /dev/null
+++ b/src/Cachix/Types/NarInfoHash.hs
@@ -0,0 +1,22 @@
+module Cachix.Types.NarInfoHash
+  ( NarInfoHash (..),
+  )
+where
+
+import Data.Swagger (ToParamSchema, ToSchema)
+import Data.Text (dropEnd, takeEnd)
+import Protolude
+import Servant.API
+
+-- | Store path hash
+newtype NarInfoHash = NarInfoHash {unnarinfohash :: Text}
+  deriving (Generic, ToSchema, ToParamSchema)
+
+instance FromHttpApiData NarInfoHash where
+  parseUrlPiece s =
+    if takeEnd 8 s == ".narinfo"
+      then Right $ NarInfoHash (dropEnd 8 s)
+      else Left ""
+
+instance ToHttpApiData NarInfoHash where
+  toUrlPiece (NarInfoHash n) = n <> ".narinfo"
diff --git a/src/Cachix/Types/NixCacheInfo.hs b/src/Cachix/Types/NixCacheInfo.hs
new file mode 100644
--- /dev/null
+++ b/src/Cachix/Types/NixCacheInfo.hs
@@ -0,0 +1,13 @@
+module Cachix.Types.NixCacheInfo where
+
+import Data.Aeson (FromJSON, ToJSON)
+import Data.Swagger (ToSchema)
+import Protolude
+
+data NixCacheInfo
+  = NixCacheInfo
+      { storeDir :: Text,
+        wantMassQuery :: Integer,
+        priority :: Integer
+      }
+  deriving (Generic, Show, FromJSON, ToJSON, ToSchema)
diff --git a/src/Cachix/Types/Permission.hs b/src/Cachix/Types/Permission.hs
new file mode 100644
--- /dev/null
+++ b/src/Cachix/Types/Permission.hs
@@ -0,0 +1,8 @@
+module Cachix.Types.Permission where
+
+import Data.Aeson (FromJSON, ToJSON)
+import Data.Swagger (ToSchema)
+import Protolude
+
+data Permission = Read | Write | Admin
+  deriving (Generic, Show, FromJSON, ToJSON, ToSchema, NFData, Eq, Ord)
diff --git a/src/Cachix/Types/Servant.hs b/src/Cachix/Types/Servant.hs
--- a/src/Cachix/Types/Servant.hs
+++ b/src/Cachix/Types/Servant.hs
@@ -14,9 +14,9 @@
 import Servant.API
 
 -- Location header as per https://github.com/haskell-servant/servant/issues/117#issuecomment-381398666
-type Get302 (cts :: [*]) (hs :: [*]) = Verb 'GET 302 cts (Headers (Header "Location" Text ': hs) NoContent)
+type Get302 (cts :: [Type]) (hs :: [Type]) = Verb 'GET 302 cts (Headers (Header "Location" Text ': hs) NoContent)
 
-type Post302 (cts :: [*]) (hs :: [*]) = Verb 'POST 302 cts (Headers (Header "Location" Text ': hs) NoContent)
+type Post302 (cts :: [Type]) (hs :: [Type]) = Verb 'POST 302 cts (Headers (Header "Location" Text ': hs) NoContent)
 
 -- TODO: allow empty CT with HEAD
 type Head = Verb 'HEAD 200 '[JSON] NoContent
diff --git a/src/Cachix/Types/SwaggerOrphans.hs b/src/Cachix/Types/SwaggerOrphans.hs
deleted file mode 100644
--- a/src/Cachix/Types/SwaggerOrphans.hs
+++ /dev/null
@@ -1,23 +0,0 @@
-{-# OPTIONS_GHC -fno-warn-orphans #-}
-{-# LANGUAGE DataKinds #-}
-{-# LANGUAGE CPP #-}
-{-# LANGUAGE TypeOperators #-}
-{-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-module Cachix.Types.SwaggerOrphans
-  where
-
-import Protolude
-import Data.Conduit (ConduitT)
-import Data.Swagger (ToSchema(..))
-
--- TODO: upstream to servant-conduit
-instance ToSchema i => ToSchema (ConduitT i o m r) where
-  declareNamedSchema _ = declareNamedSchema (Proxy :: Proxy i)
-  -- TODO: Proxy o
-
--- https://github.com/haskell-servant/servant/pull/1090
-#if !MIN_VERSION_servant_client(0,16,0)
-instance NFData NoContent
-#endif
diff --git a/test/Main.hs b/test/Main.hs
--- a/test/Main.hs
+++ b/test/Main.hs
@@ -2,7 +2,6 @@
 
 import Protolude
 import qualified Spec
-import Test.Hspec.Formatters
 import Test.Hspec.Runner
 
 main :: IO ()
