diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,3 +1,12 @@
+## 0.1.3
+
+* Add the /modules/info route.
+* Add the /compose/metadata route.
+* Add the /compose/results route.
+* Fix a typo that was preventing the /compose/info route from working.
+* Add a new BDCS.API.Results module for returning various pieces of compose
+  results and doing error checking.
+
 ## 0.1.2
 
 * Fix building the documentation with haddock.
diff --git a/bdcs-api.cabal b/bdcs-api.cabal
--- a/bdcs-api.cabal
+++ b/bdcs-api.cabal
@@ -1,5 +1,5 @@
 name:                   bdcs-api
-version:                0.1.2
+version:                0.1.3
 synopsis:               BDCS API Server
 description:            This module provides an API server and library component that works with the BDCS
                         project.  It provides a web interface for clients to create, edit, and delete
@@ -43,6 +43,7 @@
                         BDCS.API.QueueStatus,
                         BDCS.API.Recipe,
                         BDCS.API.Recipes,
+                        BDCS.API.Results,
                         BDCS.API.Server,
                         BDCS.API.TOMLMediaType,
                         BDCS.API.Utils,
@@ -97,8 +98,19 @@
     other-modules:      Paths_bdcs_api
 
     hs-source-dirs:     src
+
     default-language:   Haskell2010
+
+    default-extensions: LambdaCase,
+                        MultiWayIf,
+                        OverloadedStrings,
+                        RecordWildCards
+
     ghc-options:        -Wall
+                        -Wincomplete-uni-patterns
+                        -Wincomplete-record-updates
+                        -Wredundant-constraints
+                        -Wcompat
 
 executable bdcs-api-server
     main-is:            bdcs-api-server.hs
@@ -106,9 +118,21 @@
     build-depends:      base >= 4.9 && < 5.0,
                         bdcs-api
     other-modules:      Cmdline
+
     default-language:   Haskell2010
-    ghc-options:        -Wall -threaded
 
+    default-extensions: LambdaCase,
+                        MultiWayIf,
+                        OverloadedStrings,
+                        RecordWildCards
+
+    ghc-options:        -threaded
+                        -Wall
+                        -Wincomplete-uni-patterns
+                        -Wincomplete-record-updates
+                        -Wredundant-constraints
+                        -Wcompat
+
 test-suite spec
   type:                 exitcode-stdio-1.0
   main-is:              Spec.hs
@@ -133,7 +157,19 @@
                         time,
                         wai >= 3.2.1 && < 3.3,
                         warp >= 3.2.11 && < 3.3
+
   default-language:     Haskell2010
 
+  default-extensions:   LambdaCase,
+                        MultiWayIf,
+                        OverloadedStrings,
+                        RecordWildCards
+
   -- Ignore warnings about unlisted modules, so we don't have to list every new test
-  ghc-options:          -Wall -Wno-unrecognised-warning-flags -Wno-missing-home-modules
+  ghc-options:          -Wall
+                        -Wno-unrecognised-warning-flags
+                        -Wno-missing-home-modules
+                        -Wincomplete-uni-patterns
+                        -Wincomplete-record-updates
+                        -Wredundant-constraints
+                        -Wcompat
diff --git a/src/BDCS/API/Compose.hs b/src/BDCS/API/Compose.hs
--- a/src/BDCS/API/Compose.hs
+++ b/src/BDCS/API/Compose.hs
@@ -16,9 +16,6 @@
 -- along with bdcs-api.  If not, see <http://www.gnu.org/licenses/>.
 
 {-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE LambdaCase #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE RecordWildCards #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 
 {-| BDCS API Compose-related types and functions
diff --git a/src/BDCS/API/ComposeConfig.hs b/src/BDCS/API/ComposeConfig.hs
--- a/src/BDCS/API/ComposeConfig.hs
+++ b/src/BDCS/API/ComposeConfig.hs
@@ -14,8 +14,6 @@
 --
 -- You should have received a copy of the GNU General Public License
 -- along with bdcs-api.  If not, see <http://www.gnu.org/licenses/>.
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE RecordWildCards   #-}
 
 module BDCS.API.ComposeConfig(
     ComposeConfig(..),
diff --git a/src/BDCS/API/Customization.hs b/src/BDCS/API/Customization.hs
--- a/src/BDCS/API/Customization.hs
+++ b/src/BDCS/API/Customization.hs
@@ -14,8 +14,6 @@
 --
 -- You should have received a copy of the GNU General Public License
 -- along with bdcs-api.  If not, see <http://www.gnu.org/licenses/>.
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE RecordWildCards   #-}
 
 {-| Customizations applies to the content of an export -}
 module BDCS.API.Customization(RecipeCustomization(..),
diff --git a/src/BDCS/API/Depsolve.hs b/src/BDCS/API/Depsolve.hs
--- a/src/BDCS/API/Depsolve.hs
+++ b/src/BDCS/API/Depsolve.hs
@@ -16,9 +16,6 @@
 -- along with bdcs-api.  If not, see <http://www.gnu.org/licenses/>.
 
 {-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE LambdaCase #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE RecordWildCards #-}
 
 module BDCS.API.Depsolve(PackageNEVRA(..),
                          mkPackageNEVRA,
diff --git a/src/BDCS/API/Error.hs b/src/BDCS/API/Error.hs
--- a/src/BDCS/API/Error.hs
+++ b/src/BDCS/API/Error.hs
@@ -14,8 +14,6 @@
 --
 -- You should have received a copy of the GNU General Public License
 -- along with bdcs-api.  If not, see <http://www.gnu.org/licenses/>.
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE RecordWildCards #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 
 {-| Error functions for use with "BDCS.API"
diff --git a/src/BDCS/API/QueueStatus.hs b/src/BDCS/API/QueueStatus.hs
--- a/src/BDCS/API/QueueStatus.hs
+++ b/src/BDCS/API/QueueStatus.hs
@@ -15,8 +15,6 @@
 -- You should have received a copy of the GNU General Public License
 -- along with bdcs-api.  If not, see <http://www.gnu.org/licenses/>.
 
-{-# LANGUAGE OverloadedStrings #-}
-
 module BDCS.API.QueueStatus(QueueStatus(..),
                             queueStatusEnded,
                             queueStatusFromText,
diff --git a/src/BDCS/API/Recipe.hs b/src/BDCS/API/Recipe.hs
--- a/src/BDCS/API/Recipe.hs
+++ b/src/BDCS/API/Recipe.hs
@@ -14,8 +14,6 @@
 --
 -- You should have received a copy of the GNU General Public License
 -- along with bdcs-api.  If not, see <http://www.gnu.org/licenses/>.
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE RecordWildCards   #-}
 
 {-| Recipe is used to store information about what packages are included in a composition.
 
diff --git a/src/BDCS/API/Recipes.hs b/src/BDCS/API/Recipes.hs
--- a/src/BDCS/API/Recipes.hs
+++ b/src/BDCS/API/Recipes.hs
@@ -14,9 +14,6 @@
 --
 -- You should have received a copy of the GNU General Public License
 -- along with bdcs-api.  If not, see <http://www.gnu.org/licenses/>.
-{-# LANGUAGE LambdaCase #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE RecordWildCards #-}
 
 {-| Git Recipe storage functions
 
diff --git a/src/BDCS/API/Results.hs b/src/BDCS/API/Results.hs
new file mode 100644
--- /dev/null
+++ b/src/BDCS/API/Results.hs
@@ -0,0 +1,62 @@
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+module BDCS.API.Results(guardReturnResults,
+                        returnImage,
+                        returnImageLocation,
+                        returnResults)
+ where
+
+import           BDCS.API.Compose(ComposeStatus(..), mkComposeStatus)
+import           BDCS.API.Config(ServerConfig(..))
+import           BDCS.API.Error(createAPIError)
+import           BDCS.API.QueueStatus(queueStatusEnded)
+import qualified Codec.Archive.Tar as Tar
+import qualified Control.Exception as CE
+import           Control.Monad(filterM)
+import           Control.Monad.Except(liftIO, runExceptT, throwError)
+import qualified Data.ByteString.Lazy as LBS
+import           Data.String.Conversions(cs)
+import           GHC.TypeLits(KnownSymbol)
+import           Servant
+import           System.Directory(doesFileExist)
+import           System.FilePath.Posix((</>))
+
+guardReturnResults :: ServerConfig -> String -> Handler ComposeStatus
+guardReturnResults ServerConfig{..} uuid = do
+    result <- liftIO $ runExceptT $ mkComposeStatus cfgResultsDir (cs uuid)
+    case result of
+        Left _                    -> throwError $ createAPIError err400 False [cs uuid ++ " is not a valid build UUID"]
+        Right s@ComposeStatus{..} ->
+            if not (queueStatusEnded csQueueStatus)
+            then throwError $ createAPIError err400 False ["Build " ++ cs uuid ++ " not in FINISHED or FAILED state."]
+            else return s
+
+returnImage :: ServerConfig -> String -> Handler (FilePath, LBS.ByteString)
+returnImage cfg@ServerConfig{..} uuid =
+    returnImageLocation cfg uuid >>= \case
+        Nothing -> throwError $ createAPIError err400 False ["Build " ++ cs uuid ++ " is missing image file."]
+        Just fn -> do contents <- liftIO $ LBS.readFile (cfgResultsDir </> fn)
+                      return (fn, contents)
+
+returnImageLocation :: ServerConfig -> String -> Handler (Maybe FilePath)
+returnImageLocation cfg@ServerConfig{..} uuid = do
+    ComposeStatus{..} <- guardReturnResults cfg (cs uuid)
+    liftIO $ readArtifactFile $ cfgResultsDir </> cs uuid
+ where
+    readArtifactFile :: FilePath -> IO (Maybe String)
+    readArtifactFile dir =
+        CE.catch (Just <$> readFile (dir </> "ARTIFACT"))
+                 (\(_ :: CE.IOException) -> return Nothing)
+
+returnResults :: KnownSymbol h => ServerConfig -> String -> Maybe FilePath -> [FilePath] -> Handler (Headers '[Header h String] LBS.ByteString)
+returnResults cfg@ServerConfig{..} uuid resultSuffix files = do
+    let composeResultsDir = cfgResultsDir </> cs uuid
+
+    ComposeStatus{..} <- guardReturnResults cfg uuid
+    files'            <- filterM (\f -> liftIO $ doesFileExist (composeResultsDir </> f)) files
+    tar               <- liftIO $ Tar.pack composeResultsDir files'
+
+    case resultSuffix of
+        Just suffix -> return $ addHeader ("attachment; filename=" ++ uuid ++ "-" ++ suffix ++ ".tar;") (Tar.write tar)
+        Nothing     -> return $ addHeader ("attachment; filename=" ++ uuid ++ ".tar;") (Tar.write tar)
diff --git a/src/BDCS/API/Server.hs b/src/BDCS/API/Server.hs
--- a/src/BDCS/API/Server.hs
+++ b/src/BDCS/API/Server.hs
@@ -16,10 +16,6 @@
 -- along with bdcs-api.  If not, see <http://www.gnu.org/licenses/>.
 {-# LANGUAGE DataKinds #-}
 {-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE LambdaCase #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE RecordWildCards   #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE TypeOperators #-}
 
diff --git a/src/BDCS/API/TOMLMediaType.hs b/src/BDCS/API/TOMLMediaType.hs
--- a/src/BDCS/API/TOMLMediaType.hs
+++ b/src/BDCS/API/TOMLMediaType.hs
@@ -14,7 +14,6 @@
 --
 -- You should have received a copy of the GNU General Public License
 -- along with bdcs-api.  If not, see <http://www.gnu.org/licenses/>.
-{-# LANGUAGE OverloadedStrings     #-}
 {-# LANGUAGE FlexibleInstances     #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 
diff --git a/src/BDCS/API/V0.hs b/src/BDCS/API/V0.hs
--- a/src/BDCS/API/V0.hs
+++ b/src/BDCS/API/V0.hs
@@ -18,10 +18,6 @@
 {-# LANGUAGE DuplicateRecordFields #-}
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE LambdaCase #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE RecordWildCards   #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE TypeOperators #-}
 {-# OPTIONS_HADDOCK ignore-exports, prune #-}
@@ -42,6 +38,7 @@
                Metadata(..),
                ModuleName(..),
                ModulesListResponse(..),
+               ModulesInfoResponse(..),
                PackageNEVRA(..),
                ProjectInfo(..),
                ProjectsDepsolveResponse(..),
@@ -67,9 +64,10 @@
 import           BDCS.API.Customization(processCustomization)
 import           BDCS.API.Depsolve
 import           BDCS.API.Error(APIResponse(..), createAPIError, tryIO)
-import           BDCS.API.QueueStatus(QueueStatus(..), queueStatusEnded, queueStatusText)
+import           BDCS.API.QueueStatus(QueueStatus(..), queueStatusText)
 import           BDCS.API.Recipe
 import           BDCS.API.Recipes
+import           BDCS.API.Results(returnImage, returnImageLocation, returnResults)
 import           BDCS.API.TOMLMediaType
 import           BDCS.API.Utils(GitLock(..), applyLimits, argify, caseInsensitive, caseInsensitiveT)
 import           BDCS.API.Workspace
@@ -81,7 +79,6 @@
 import           BDCS.Sources(findSources, getSource)
 import           BDCS.Utils.Either(maybeToEither)
 import           BDCS.Utils.Monad(concatMapM, mapMaybeM)
-import qualified Codec.Archive.Tar as Tar
 import qualified Control.Concurrent.ReadWriteLock as RWL
 import           Control.Concurrent.STM.TChan(writeTChan)
 import           Control.Concurrent.STM.TMVar(newEmptyTMVar, readTMVar)
@@ -183,6 +180,8 @@
                                   :> QueryParam "offset" Int
                                   :> QueryParam "limit" Int
                                   :> Get '[JSON] ModulesListResponse
+        :<|> "modules"  :> "info" :> Capture "module_names" String
+                                  :> Get '[JSON] ModulesInfoResponse
         :<|> "compose"  :> ReqBody '[JSON] ComposeBody
                         :> QueryParam "test" Int
                         :> Post '[JSON] ComposeResponse
@@ -192,7 +191,7 @@
         :<|> "compose"  :> "failed" :> Get '[JSON] ComposeFailedResponse
         :<|> "compose"  :> "status" :> Capture "uuids" String
                                     :> Get '[JSON] ComposeStatusResponse
-        :<|> "compose"  :> "info" :> Capture "uuid" String
+        :<|> "compose"  :> "info"   :> Capture "uuid" String
                                     :> Get '[JSON] ComposeInfoResponse
         :<|> "compose"  :> "cancel" :> Capture "uuid" String
                                     :> Delete '[JSON] APIResponse
@@ -202,6 +201,10 @@
                                     :> Get '[OctetStream] (Headers '[Header "Content-Disposition" String] LBS.ByteString)
         :<|> "compose"  :> "image"  :> Capture "uuid" String
                                     :> Get '[OctetStream] (Headers '[Header "Content-Disposition" String] LBS.ByteString)
+        :<|> "compose"  :> "metadata" :> Capture "uuid" String
+                                      :> Get '[OctetStream] (Headers '[Header "Content-Disposition" String] LBS.ByteString)
+        :<|> "compose"  :> "results" :> Capture "uuid" String
+                                     :> Get '[OctetStream] (Headers '[Header "Content-Disposition" String] LBS.ByteString)
 
 -- | Connect the V0API type to all of the handlers
 v0ApiServer :: ServerConfig -> Server V0API
@@ -222,6 +225,7 @@
              :<|> recipesFreezeH
              :<|> modulesListH
              :<|> modulesListFilteredH
+             :<|> modulesInfoH
              :<|> composeH
              :<|> composeTypesH
              :<|> composeQueueH
@@ -233,6 +237,8 @@
              :<|> composeDeleteH
              :<|> composeLogsH
              :<|> composeImageH
+             :<|> composeMetadataH
+             :<|> composeResultsH
   where
     projectsListH offset limit                       = projectsList cfg offset limit
     projectsInfoH project_names                      = projectsInfo cfg project_names
@@ -251,6 +257,7 @@
     recipesFreezeH recipes branch                    = recipesFreeze cfg branch recipes
     modulesListH offset limit                        = modulesList cfg offset limit "*"
     modulesListFilteredH module_names offset limit   = modulesList cfg offset limit module_names
+    modulesInfoH module_names                        = modulesInfo cfg (T.splitOn "," $ cs module_names)
     composeH body test                               = compose cfg body test
     composeTypesH                                    = composeTypes
     composeQueueH                                    = composeQueue cfg
@@ -262,6 +269,8 @@
     composeDeleteH uuids                             = composeDelete cfg (T.splitOn "," $ cs uuids)
     composeLogsH uuid                                = composeLogs cfg uuid
     composeImageH uuid                               = composeImage cfg (cs uuid)
+    composeMetadataH uuid                            = composeMetadata cfg (cs uuid)
+    composeResultsH uuid                             = composeResults cfg (cs uuid)
 
 -- | The JSON response for /blueprints/list
 data RecipesListResponse = RecipesListResponse {
@@ -1701,6 +1710,106 @@
     limit :: Int
     limit  = fromMaybe 20 mlimit
 
+-- | /api/v0/modules/info/<module_names>
+-- Return the module's dependencies, and the information about the module.
+--
+-- > {
+-- >   "modules": [
+-- >     {
+-- >       "dependencies": [
+-- >         {
+-- >           "arch": "noarch",
+-- >           "epoch": "0",
+-- >           "name": "basesystem",
+-- >           "release": "7.el7",
+-- >           "version": "10.0"
+-- >         },
+-- >         {
+-- >           "arch": "x86_64",
+-- >           "epoch": "0",
+-- >           "name": "bash",
+-- >           "release": "28.el7",
+-- >           "version": "4.2.46"
+-- >         },
+-- >         ...
+-- >       ],
+-- >       "description": "The GNU tar program saves ...",
+-- >       "homepage": "http://www.gnu.org/software/tar/",
+-- >       "name": "tar",
+-- >       "summary": "A GNU file archiving program",
+-- >       "upstream_vcs": "UPSTREAM_VCS"
+-- >     }
+-- >   ]
+-- > }
+
+data ModuleInfo = ModuleInfo {
+    miDependencies :: [PackageNEVRA],
+    miDescription :: T.Text,
+    miHomepage :: Maybe T.Text,
+    miName :: T.Text,
+    miSummary :: T.Text,
+    miUpstream :: Maybe T.Text
+} deriving (Show, Eq)
+
+instance ToJSON ModuleInfo where
+    toJSON ModuleInfo{..} = object [
+        "dependencies" .= miDependencies,
+        "description"  .= miDescription,
+        "homepage"     .= miHomepage,
+        "name"         .= miName,
+        "summary"      .= miSummary,
+        "upstream_vcs" .= miUpstream ]
+
+instance FromJSON ModuleInfo where
+    parseJSON = withObject "/modules/info module info" $ \o ->
+        ModuleInfo <$> o .: "dependencies"
+                   <*> o .: "description"
+                   <*> o .: "homepage"
+                   <*> o .: "name"
+                   <*> o .: "summary"
+                   <*> o .: "upstream_vcs"
+
+data ModulesInfoResponse = ModulesInfoResponse {
+    mirModules :: [ModuleInfo]
+} deriving (Show, Eq)
+
+instance ToJSON ModulesInfoResponse where
+    toJSON ModulesInfoResponse{..} = object [
+        "modules" .= mirModules ]
+
+instance FromJSON ModulesInfoResponse where
+    parseJSON = withObject "/modules/info response" $ \o ->
+        ModulesInfoResponse <$> o .: "modules"
+
+modulesInfo :: ServerConfig -> [T.Text] -> Handler ModulesInfoResponse
+modulesInfo cfg@ServerConfig{..} modules = do
+    projectInfos <- concatMap pipProjects <$> mapM getProjectsInfo modules
+    depResults   <- mapM getDependencies projectInfos
+    return ModulesInfoResponse { mirModules=map (\(pI, deps) -> addDependencies deps (projectInfoToModuleInfo pI))
+                                                (zip projectInfos depResults) }
+ where
+    addDependencies :: [PackageNEVRA] -> ModuleInfo -> ModuleInfo
+    addDependencies deps mI = mI { miDependencies=deps }
+
+    getDependencies :: ProjectInfo -> Handler [PackageNEVRA]
+    getDependencies ProjectInfo{..} = removeSelfDep piName . pdrProjects <$> projectsDepsolve cfg (cs piName)
+
+    getProjectsInfo :: T.Text -> Handler ProjectsInfoResponse
+    getProjectsInfo name = projectsInfo cfg (cs name)
+
+    removeSelfDep :: T.Text -> [PackageNEVRA] -> [PackageNEVRA]
+    removeSelfDep name nevras =
+        filter (\PackageNEVRA{..} -> pnName /= name) nevras
+
+    projectInfoToModuleInfo :: ProjectInfo -> ModuleInfo
+    projectInfoToModuleInfo ProjectInfo{..} =
+        ModuleInfo { miDependencies=[],
+                     miDescription=piDescription,
+                     miHomepage=piHomepage,
+                     miName=piName,
+                     miSummary=piSummary,
+                     miUpstream=piUpstream }
+
 data ComposeBody = ComposeBody {
     cbName :: T.Text,                                                   -- ^ Recipe name (from /blueprints/list)
     cbType :: T.Text,                                                   -- ^ Compose type (from /compose/types)
@@ -2102,8 +2211,9 @@
     -- Read the frozen.toml blueprint from the results directory
     readFrozenBlueprintFile :: FilePath -> ExceptT ServantErr IO Recipe
     readFrozenBlueprintFile dir = withExceptT (const frozen_error) $
-        tryIO (TIO.readFile (dir </> "compose.toml")) >>= ExceptT . return . parseRecipe
+        tryIO (TIO.readFile (dir </> "frozen.toml")) >>= ExceptT . return . parseRecipe
 
+
 data ComposeDeleteResponse = ComposeDeleteResponse {
     cdrErrors :: [String],
     cdrUuids  :: [UuidStatus]
@@ -2179,19 +2289,8 @@
 -- The mime type is set to 'application/x-tar' and the filename is set to
 -- UUID-logs.tar
 composeLogs :: KnownSymbol h => ServerConfig -> String -> Handler (Headers '[Header h String] LBS.ByteString)
-composeLogs ServerConfig{..} uuid = do
-    result <- liftIO $ runExceptT $ mkComposeStatus cfgResultsDir (cs uuid)
-    case result of
-        Left _                  -> throwError $ createAPIError err400 False ["compose_logs: " ++ cs uuid ++ " is not a valid build uuid"]
-        Right ComposeStatus{..} ->
-            if not (queueStatusEnded csQueueStatus)
-            then throwError $ createAPIError err400 False ["compose_logs: Build " ++ cs uuid ++ " not in FINISHED or FAILED state."]
-            else do
-                let composeResultsDir = cfgResultsDir </> cs uuid
-                    logFiles          = ["compose.log"]
-
-                tar <- liftIO $ Tar.pack composeResultsDir logFiles
-                return $ addHeader ("attachment; filename=" ++ uuid ++ "-logs.tar;") (Tar.write tar)
+composeLogs serverConf uuid =
+    returnResults serverConf uuid (Just "-logs") ["compose.log"]
 
 
 -- | /api/v0/compose/image/<uuid>
@@ -2199,20 +2298,41 @@
 -- Returns the output image from the build. The filename is set to the filename
 -- from the build with the UUID as a prefix. eg. UUID-root.tar.xz or UUID-boot.iso.
 composeImage :: KnownSymbol h => ServerConfig -> T.Text -> Handler (Headers '[Header h String] LBS.ByteString)
-composeImage ServerConfig{..} uuid = do
-    result <- liftIO $ runExceptT $ mkComposeStatus cfgResultsDir (cs uuid)
-    case result of
-        Left _                  -> throwError $ createAPIError err400 False ["compose_image: " ++ cs uuid ++ " is not a valid build uuid"]
-        Right ComposeStatus{..} ->
-            if not (queueStatusEnded csQueueStatus)
-            then throwError $ createAPIError err400 False ["compose_logs: Build " ++ cs uuid ++ " not in FINISHED or FAILED state."]
-            else liftIO (readArtifactFile $ cfgResultsDir </> cs uuid) >>= \case
-                Nothing -> throwError $ createAPIError err400 False ["compose_image: Build " ++ cs uuid ++ " is missing image file."]
-                Just fn -> do f <- liftIO $ LBS.readFile (cfgResultsDir </> fn)
-                              return $ addHeader ("attachment; filename=" ++ filename fn ++ ";") f
+composeImage serverConf uuid = do
+    (fn, contents) <- returnImage serverConf (cs uuid)
+    return $ addHeader ("attachment; filename=" ++ filename fn ++ ";") contents
  where
-    readArtifactFile :: FilePath -> IO (Maybe String)
-    readArtifactFile dir =
-        CE.catch (Just <$> readFile (dir </> "ARTIFACT"))
-                 (\(_ :: CE.IOException) -> return Nothing)
     filename fn = cs uuid ++ "-" ++ takeFileName fn
+
+
+-- | /api/v0/compose/metadata/<uuid>
+--
+-- Returns a .tar of the metadata used for the build. This includes all the
+-- information needed to reproduce the build, including the final blueprint
+-- populated with repository and package NEVRA.
+--
+-- The mime type is set to 'application/x-tar' and the filename is set to
+-- UUID-metadata.tar
+--
+-- The .tar is uncompressed, but is not large.
+composeMetadata :: KnownSymbol h => ServerConfig -> String -> Handler (Headers '[Header h String] LBS.ByteString)
+composeMetadata serverConf uuid =
+    returnResults serverConf uuid (Just "-metadata") ["blueprint.toml", "compose.toml", "frozen.toml"]
+
+
+-- | /api/v0/compose/results/<uuid>
+--
+-- Returns a .tar of the metadata, logs, and output image of the build. This
+-- includes all the information needed to reproduce the build, including the
+-- final kickstart populated with repository and package NEVRA. The output image
+-- is already in compressed form so the returned tar is not compressed.
+--
+-- The mime type is set to 'application/x-tar' and the filename is set to
+-- UUID.tar
+composeResults :: KnownSymbol h => ServerConfig -> String -> Handler (Headers '[Header h String] LBS.ByteString)
+composeResults serverConf uuid = do
+    imageLocation <- returnImageLocation serverConf uuid
+
+    case imageLocation of
+        Just loc -> returnResults serverConf uuid Nothing ["compose.log", "blueprint.toml", "compose.toml", "frozen.toml", takeFileName loc]
+        Nothing  -> throwError $ createAPIError err400 False ["Build " ++ cs uuid ++ " is missing image file."]
diff --git a/src/BDCS/API/Workspace.hs b/src/BDCS/API/Workspace.hs
--- a/src/BDCS/API/Workspace.hs
+++ b/src/BDCS/API/Workspace.hs
@@ -14,7 +14,6 @@
 --
 -- You should have received a copy of the GNU General Public License
 -- along with bdcs-api.  If not, see <http://www.gnu.org/licenses/>.
-{-# LANGUAGE OverloadedStrings #-}
 
 {-| Workspace functions - The workspace is a temporary storage location for Recipes.
 
diff --git a/tests/RecipeSpec.hs b/tests/RecipeSpec.hs
--- a/tests/RecipeSpec.hs
+++ b/tests/RecipeSpec.hs
@@ -14,8 +14,7 @@
 --
 -- You should have received a copy of the GNU General Public License
 -- along with bdcs-api.  If not, see <http://www.gnu.org/licenses/>.
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE QuasiQuotes       #-}
+{-# LANGUAGE QuasiQuotes #-}
 
 module RecipeSpec
   where
diff --git a/tests/RecipesSpec.hs b/tests/RecipesSpec.hs
--- a/tests/RecipesSpec.hs
+++ b/tests/RecipesSpec.hs
@@ -14,7 +14,6 @@
 --
 -- You should have received a copy of the GNU General Public License
 -- along with bdcs-api.  If not, see <http://www.gnu.org/licenses/>.
-{-# LANGUAGE OverloadedStrings #-}
 
 module RecipesSpec
   where
diff --git a/tests/ServerSpec.hs b/tests/ServerSpec.hs
--- a/tests/ServerSpec.hs
+++ b/tests/ServerSpec.hs
@@ -15,7 +15,6 @@
 -- You should have received a copy of the GNU General Public License
 -- along with bdcs-api.  If not, see <http://www.gnu.org/licenses/>.
 {-# LANGUAGE DataKinds #-}
-{-# LANGUAGE OverloadedStrings #-}
 
 module ServerSpec
   where
@@ -68,6 +67,7 @@
 getRecipesFreeze :: String -> Maybe String -> ClientM RecipesFreezeResponse
 getModulesList :: Maybe Int -> Maybe Int -> ClientM ModulesListResponse
 getModulesList' :: String -> Maybe Int -> Maybe Int -> ClientM ModulesListResponse
+getModulesInfo :: String -> ClientM ModulesInfoResponse
 getCompose :: ComposeBody -> Maybe Int -> ClientM ComposeResponse
 getComposeTypes :: ClientM ComposeTypesResponse
 getComposeQueue :: ClientM ComposeQueueResponse
@@ -79,14 +79,17 @@
 getComposeDelete :: String -> ClientM ComposeDeleteResponse
 getComposeLogs :: String -> ClientM (Headers '[Header "Content-Disposition" String] LBS.ByteString)
 getComposeImage :: String -> ClientM (Headers '[Header "Content-Disposition" String] LBS.ByteString)
+getComposeMetadata :: String -> ClientM (Headers '[Header "Content-Disposition" String] LBS.ByteString)
+getComposeResults :: String -> ClientM (Headers '[Header "Content-Disposition" String] LBS.ByteString)
 getStatus :<|> getProjectsList :<|> getProjectsInfo :<|> getProjectsDepsolve
           :<|> getRecipes :<|> getRecipesInfo :<|> getRecipesChanges
           :<|> postRecipesNew :<|> deleteRecipes :<|> postRecipesUndo
           :<|> postRecipesWorkspace :<|> deleteRecipesWorkspace :<|> postRecipesTag :<|> getRecipesDiff
           :<|> getRecipesDepsolve :<|> getRecipesFreeze :<|> getModulesList
-          :<|> getModulesList' :<|> getCompose :<|> getComposeTypes :<|> getComposeQueue
+          :<|> getModulesList' :<|> getModulesInfo :<|> getCompose :<|> getComposeTypes :<|> getComposeQueue
           :<|> getComposeQueueFinished :<|> getComposeQueueFailed :<|> getComposeStatus :<|> getComposeInfo
-          :<|> getComposeCancel :<|> getComposeDelete :<|> getComposeLogs :<|> getComposeImage = client proxyAPI
+          :<|> getComposeCancel :<|> getComposeDelete :<|> getComposeLogs :<|> getComposeImage
+          :<|> getComposeMetadata :<|> getComposeResults = client proxyAPI
 
 
 -- Test results, depends on the contents of the ./tests/recipes files.
diff --git a/tools/bdcs-api-server.hs b/tools/bdcs-api-server.hs
--- a/tools/bdcs-api-server.hs
+++ b/tools/bdcs-api-server.hs
@@ -1,6 +1,3 @@
-{-# LANGUAGE LambdaCase #-}
-{-# LANGUAGE RecordWildCards #-}
-
 -- Copyright (C) 2017 Red Hat, Inc.
 --
 -- This file is part of bdcs-api.
