diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,12 @@
 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
+## 0.8.2.0 - 2024-02-12
+
+### Added
+
+ - Experimental OpenAPI 3 generation
+
 ## 0.8.1.0 - 2023-06-28
 
 ### Added
diff --git a/hercules-ci-api.cabal b/hercules-ci-api.cabal
--- a/hercules-ci-api.cabal
+++ b/hercules-ci-api.cabal
@@ -1,6 +1,6 @@
 cabal-version:      2.2
 name:               hercules-ci-api
-version:            0.8.1.0
+version:            0.8.2.0
 synopsis:           Hercules CI API definition with Servant
 homepage:           https://github.com/hercules-ci/hercules-ci-agent#readme
 bug-reports:        https://github.com/hercules-ci/hercules-ci-agent/issues
@@ -155,8 +155,10 @@
     , lens-aeson
     , memory
     , network-uri
+    , openapi3
     , profunctors
     , servant                  >=0.14.1
+    , servant-openapi3
     , servant-auth
     , servant-auth-swagger
     , servant-swagger
@@ -185,10 +187,12 @@
     , lens
     , memory
     , network-uri
+    , openapi3
     , profunctors
     , servant                  >=0.14.1
     , servant-auth
     , servant-auth-swagger
+    , servant-openapi3
     , servant-swagger
     , servant-swagger-ui-core
     , string-conv
diff --git a/hercules-gen-swagger/Main.hs b/hercules-gen-swagger/Main.hs
--- a/hercules-gen-swagger/Main.hs
+++ b/hercules-gen-swagger/Main.hs
@@ -5,8 +5,17 @@
 
 import Data.Aeson (encode)
 import Data.String.Conv (toS)
-import Hercules.API (swagger)
+import Hercules.API (openapi3, swagger)
+import System.Environment (getArgs)
+import System.IO (hPutStrLn, stderr)
 import Prelude
 
 main :: IO ()
-main = putStrLn $ toS $ encode swagger
+main = do
+  args <- getArgs
+  case args of
+    ["--experimental-openapi3"] -> putStrLn $ toS $ encode openapi3
+    [] -> putStrLn $ toS $ encode swagger
+    _ -> do
+      hPutStrLn stderr "Usage: hercules-gen-swagger [--experimental-openapi3] > swagger.json"
+      error $ "Unknown arguments" <> show args
diff --git a/src/Hercules/API.hs b/src/Hercules/API.hs
--- a/src/Hercules/API.hs
+++ b/src/Hercules/API.hs
@@ -25,11 +25,15 @@
 
     -- * Utilities
     noContent,
+
+    -- * Experimental
+    openapi3,
   )
 where
 
 import Control.Lens
 import Control.Monad
+import Data.OpenApi qualified as O3
 import Data.Proxy (Proxy (..))
 import Data.Swagger hiding (Header)
 import Hercules.API.Accounts (AccountsAPI)
@@ -53,6 +57,7 @@
 import Servant.API
 import Servant.Auth
 import Servant.Auth.Swagger ()
+import Servant.OpenApi qualified as SO3
 import Servant.Swagger
 import Servant.Swagger.UI.Core (SwaggerSchemaUI)
 
@@ -112,7 +117,7 @@
 
 swagger :: Swagger
 swagger =
-  toSwagger api'
+  toSwagger apiWithJWT
     & info
       . title
       .~ "Hercules CI API"
@@ -134,9 +139,15 @@
     & withTags clientOrganizations "organization" "Organizations and billing operations"
     & withTags clientClientInfo "client" "Ad hoc endpoints for the frontend and perhaps some client-side use cases"
   where
-    api' = (servantClientApi @(Auth '[JWT] ()))
-    withTags f tag desc = applyTagsFor (subOperations (clientApiProxy f) api') [tag & description ?~ desc]
+    withTags f tag desc = applyTagsFor (subOperations (clientApiProxy f) apiWithJWT) [tag & description ?~ desc]
 
+apiWithJWT :: Proxy (ClientServantAPI (Auth '[JWT] ()))
+apiWithJWT = servantClientApi @(Auth '[JWT] ())
+
+-- | NOTE: this has not been tested yet.
+openapi3 :: O3.OpenApi
+openapi3 = SO3.toOpenApi apiWithJWT
+
 clientApiProxy :: (ClientAPI (Auth '[JWT] ()) AsApi -> a) -> Proxy ("api" :> "v1" :> a)
 clientApiProxy _ = Proxy
 
@@ -144,5 +155,5 @@
 -- compiler that rightfully warns about throwing away a do notation
 -- result. By specialising, we make sure that we still get warnings
 -- if the result type changes in the future. (We'll get an error)
-noContent :: Functor m => m Servant.API.NoContent -> m ()
+noContent :: (Functor m) => m Servant.API.NoContent -> m ()
 noContent = void
diff --git a/src/Hercules/API/Accounts/Account.hs b/src/Hercules/API/Accounts/Account.hs
--- a/src/Hercules/API/Accounts/Account.hs
+++ b/src/Hercules/API/Accounts/Account.hs
@@ -3,17 +3,18 @@
 
 module Hercules.API.Accounts.Account where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Forge.Forge (Forge)
 import Hercules.API.Organizations.Organization qualified as Organization
 import Hercules.API.Prelude
 
 data AccountType = User | Organization
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
 
 data MembershipRole = Member | Admin
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
 
 data Account = Account
   { id :: Id Account,
@@ -43,4 +44,4 @@
     installationIsSelection :: Maybe Bool
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Accounts/AccountInstallationStatus.hs b/src/Hercules/API/Accounts/AccountInstallationStatus.hs
--- a/src/Hercules/API/Accounts/AccountInstallationStatus.hs
+++ b/src/Hercules/API/Accounts/AccountInstallationStatus.hs
@@ -3,6 +3,7 @@
 
 module Hercules.API.Accounts.AccountInstallationStatus where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Accounts.Account (Account)
 import Hercules.API.Forge.Forge (Forge)
 import Hercules.API.Prelude
@@ -14,4 +15,4 @@
     secondsSinceInstallationWebHookComplete :: Maybe Int
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Accounts/AccountSettings.hs b/src/Hercules/API/Accounts/AccountSettings.hs
--- a/src/Hercules/API/Accounts/AccountSettings.hs
+++ b/src/Hercules/API/Accounts/AccountSettings.hs
@@ -3,6 +3,7 @@
 
 module Hercules.API.Accounts.AccountSettings where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Prelude
 
 data AccountSettings = AccountSettings
@@ -10,4 +11,4 @@
     enableNewRepos :: Bool
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Accounts/AccountSettingsPatch.hs b/src/Hercules/API/Accounts/AccountSettingsPatch.hs
--- a/src/Hercules/API/Accounts/AccountSettingsPatch.hs
+++ b/src/Hercules/API/Accounts/AccountSettingsPatch.hs
@@ -3,10 +3,11 @@
 
 module Hercules.API.Accounts.AccountSettingsPatch where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Prelude
 
 data AccountSettingsPatch = AccountSettingsPatch
   { enableNewRepos :: Maybe Bool
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Accounts/CLIAuthorizationRequest.hs b/src/Hercules/API/Accounts/CLIAuthorizationRequest.hs
--- a/src/Hercules/API/Accounts/CLIAuthorizationRequest.hs
+++ b/src/Hercules/API/Accounts/CLIAuthorizationRequest.hs
@@ -3,6 +3,7 @@
 
 module Hercules.API.Accounts.CLIAuthorizationRequest where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Prelude
 
 data CLIAuthorizationRequest = CLIAuthorizationRequest
@@ -10,4 +11,4 @@
     creationTime :: UTCTime
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Accounts/CLIAuthorizationRequestCreate.hs b/src/Hercules/API/Accounts/CLIAuthorizationRequestCreate.hs
--- a/src/Hercules/API/Accounts/CLIAuthorizationRequestCreate.hs
+++ b/src/Hercules/API/Accounts/CLIAuthorizationRequestCreate.hs
@@ -3,10 +3,11 @@
 
 module Hercules.API.Accounts.CLIAuthorizationRequestCreate where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Prelude
 
 data CLIAuthorizationRequestCreate = CLIAuthorizationRequestCreate
   { description :: Text
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Accounts/CLIAuthorizationRequestCreateResponse.hs b/src/Hercules/API/Accounts/CLIAuthorizationRequestCreateResponse.hs
--- a/src/Hercules/API/Accounts/CLIAuthorizationRequestCreateResponse.hs
+++ b/src/Hercules/API/Accounts/CLIAuthorizationRequestCreateResponse.hs
@@ -3,6 +3,7 @@
 
 module Hercules.API.Accounts.CLIAuthorizationRequestCreateResponse where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Prelude
 
 data CLIAuthorizationRequestCreateResponse = CLIAuthorizationRequestCreateResponse
@@ -10,4 +11,4 @@
     browserURL :: Text
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Accounts/CLIAuthorizationRequestStatus.hs b/src/Hercules/API/Accounts/CLIAuthorizationRequestStatus.hs
--- a/src/Hercules/API/Accounts/CLIAuthorizationRequestStatus.hs
+++ b/src/Hercules/API/Accounts/CLIAuthorizationRequestStatus.hs
@@ -3,6 +3,7 @@
 
 module Hercules.API.Accounts.CLIAuthorizationRequestStatus where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Prelude
 
 data CLIAuthorization = CLIAuthorization
@@ -10,14 +11,14 @@
     userIdentities :: [Text]
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
 
 data CLIAuthorizationStatus = Pending () | Granted CLIAuthorization
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
 
 data CLIAuthorizationRequestStatus = CLIAuthorizationRequestStatus
   { status :: CLIAuthorizationStatus
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Accounts/CLIToken.hs b/src/Hercules/API/Accounts/CLIToken.hs
--- a/src/Hercules/API/Accounts/CLIToken.hs
+++ b/src/Hercules/API/Accounts/CLIToken.hs
@@ -4,6 +4,7 @@
 
 module Hercules.API.Accounts.CLIToken where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Accounts.Account (Account)
 import Hercules.API.Prelude
 
@@ -14,4 +15,4 @@
     userId :: Id Account
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Accounts/CLITokensResponse.hs b/src/Hercules/API/Accounts/CLITokensResponse.hs
--- a/src/Hercules/API/Accounts/CLITokensResponse.hs
+++ b/src/Hercules/API/Accounts/CLITokensResponse.hs
@@ -3,6 +3,7 @@
 
 module Hercules.API.Accounts.CLITokensResponse where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Accounts.CLIToken (CLIToken)
 import Hercules.API.Prelude
 
@@ -10,4 +11,4 @@
   { cliTokens :: [CLIToken]
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Accounts/NotificationSettings.hs b/src/Hercules/API/Accounts/NotificationSettings.hs
--- a/src/Hercules/API/Accounts/NotificationSettings.hs
+++ b/src/Hercules/API/Accounts/NotificationSettings.hs
@@ -4,6 +4,7 @@
 
 module Hercules.API.Accounts.NotificationSettings where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Accounts.SimpleAccount (SimpleAccount)
 import Hercules.API.Forge.SimpleForge (SimpleForge)
 import Hercules.API.Prelude
@@ -12,21 +13,21 @@
   = Ignore
   | All
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
 
 data NotificationSetting = NotificationSetting
   { notificationLevel :: Maybe NotificationLevel,
     notificationEmail :: Maybe Text
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
 
 data NotificationAccountOverride = NotificationSettingsOverride
   { account :: SimpleAccount,
     setting :: NotificationSetting
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
 
 data AuthorizedEmail = AuthorizedEmail
   { address :: Text,
@@ -34,7 +35,7 @@
     source :: Maybe SimpleForge
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
 
 data NotificationSettings = NotificationSettings
   { authorizedEmails :: [AuthorizedEmail],
@@ -42,4 +43,4 @@
     accountOverrides :: [NotificationAccountOverride]
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Accounts/NotificationSettingsPatch.hs b/src/Hercules/API/Accounts/NotificationSettingsPatch.hs
--- a/src/Hercules/API/Accounts/NotificationSettingsPatch.hs
+++ b/src/Hercules/API/Accounts/NotificationSettingsPatch.hs
@@ -3,6 +3,7 @@
 
 module Hercules.API.Accounts.NotificationSettingsPatch where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Accounts.Account (Account)
 import Hercules.API.Accounts.NotificationSettings (NotificationSetting)
 import Hercules.API.Prelude
@@ -12,4 +13,4 @@
     accountOverrides :: Map (Id Account) NotificationSetting
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Accounts/SimpleAccount.hs b/src/Hercules/API/Accounts/SimpleAccount.hs
--- a/src/Hercules/API/Accounts/SimpleAccount.hs
+++ b/src/Hercules/API/Accounts/SimpleAccount.hs
@@ -3,6 +3,7 @@
 
 module Hercules.API.Accounts.SimpleAccount where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Accounts.Account (Account, AccountType)
 import Hercules.API.Forge.SimpleForge (SimpleForge)
 import Hercules.API.Prelude
@@ -16,4 +17,4 @@
     site :: SimpleForge
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Agents/AgentSession.hs b/src/Hercules/API/Agents/AgentSession.hs
--- a/src/Hercules/API/Agents/AgentSession.hs
+++ b/src/Hercules/API/Agents/AgentSession.hs
@@ -3,6 +3,7 @@
 
 module Hercules.API.Agents.AgentSession where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Agents.ClusterJoinToken
   ( ClusterJoinToken,
   )
@@ -29,4 +30,4 @@
     labels :: Labels
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Agents/ClusterJoinToken.hs b/src/Hercules/API/Agents/ClusterJoinToken.hs
--- a/src/Hercules/API/Agents/ClusterJoinToken.hs
+++ b/src/Hercules/API/Agents/ClusterJoinToken.hs
@@ -3,6 +3,7 @@
 
 module Hercules.API.Agents.ClusterJoinToken where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Accounts.Account (Account)
 import Hercules.API.Prelude
 
@@ -14,4 +15,4 @@
     description :: Text
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Agents/CreateClusterJoinToken.hs b/src/Hercules/API/Agents/CreateClusterJoinToken.hs
--- a/src/Hercules/API/Agents/CreateClusterJoinToken.hs
+++ b/src/Hercules/API/Agents/CreateClusterJoinToken.hs
@@ -3,6 +3,7 @@
 
 module Hercules.API.Agents.CreateClusterJoinToken where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Prelude
 
 -- The owner account that the token applies to is in the path.
@@ -10,4 +11,4 @@
   { description :: Text
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Agents/FullClusterJoinToken.hs b/src/Hercules/API/Agents/FullClusterJoinToken.hs
--- a/src/Hercules/API/Agents/FullClusterJoinToken.hs
+++ b/src/Hercules/API/Agents/FullClusterJoinToken.hs
@@ -3,6 +3,7 @@
 
 module Hercules.API.Agents.FullClusterJoinToken where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Agents.ClusterJoinToken
   ( ClusterJoinToken,
   )
@@ -13,4 +14,4 @@
     token :: Text
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Attribute.hs b/src/Hercules/API/Attribute.hs
--- a/src/Hercules/API/Attribute.hs
+++ b/src/Hercules/API/Attribute.hs
@@ -16,6 +16,7 @@
 import Data.Aeson qualified as A
 import Data.Aeson.Lens
 import Data.Function ((&))
+import Data.OpenApi qualified as O3
 import Data.Proxy (Proxy (Proxy))
 import Data.Swagger (ToParamSchema (..))
 import Data.Text qualified as T
@@ -30,7 +31,7 @@
   | DependenciesOnly
   | Effect
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
 
 -- | An arbitrary ordering
 deriving instance Ord AttributeType
@@ -43,14 +44,16 @@
   deriving (Generic, Show, Eq)
   deriving anyclass (NFData, ToJSON)
 
-instance FromJSON a => FromJSON (Attribute a) where
+instance (FromJSON a) => FromJSON (Attribute a) where
   parseJSON v = A.parseJSON (fixup v)
     where
       fixup :: A.Value -> A.Value
       fixup = _Object . at "typ" %~ (<|> Just (A.String "Regular"))
 
-deriving instance ToSchema a => ToSchema (Attribute a)
+deriving instance (ToSchema a) => ToSchema (Attribute a)
 
+deriving instance (O3.ToSchema a) => O3.ToSchema (Attribute a)
+
 deriving instance Functor Attribute
 
 deriving instance Foldable Attribute
@@ -72,6 +75,9 @@
 instance ToHttpApiData AttributePath where
   toUrlPiece = toUrlPiece . attributePathToString . fromAttributePath
 
+instance O3.ToParamSchema AttributePath where
+  toParamSchema _ = O3.toParamSchema (Proxy :: Proxy Text)
+
 ----------------------------------------
 
 attributePathToString :: [Text] -> Text
@@ -91,7 +97,8 @@
       ( let h = T.head t
          in (h >= 'a' && h <= 'z')
               || (h >= 'A' && h <= 'Z')
-              || h == '_'
+              || h
+              == '_'
       ) =
       False
 isNixSimpleId t =
@@ -100,9 +107,12 @@
         (c >= 'a' && c <= 'z')
           || (c >= 'A' && c <= 'Z')
           || (c >= '0' && c <= '9')
-          || c == '_'
-          || c == '\''
-          || c == '-'
+          || c
+          == '_'
+          || c
+          == '\''
+          || c
+          == '-'
     )
     t
 
diff --git a/src/Hercules/API/BillingStatus.hs b/src/Hercules/API/BillingStatus.hs
--- a/src/Hercules/API/BillingStatus.hs
+++ b/src/Hercules/API/BillingStatus.hs
@@ -8,6 +8,7 @@
   )
 where
 
+import Data.OpenApi qualified as O3
 import Data.Swagger
 import Hercules.API.Prelude
 
@@ -19,7 +20,7 @@
   | External
   | Enterprise
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
 
 toText :: BillingStatus -> Text
 toText Community = "Community"
diff --git a/src/Hercules/API/Build/AgentRequirements.hs b/src/Hercules/API/Build/AgentRequirements.hs
--- a/src/Hercules/API/Build/AgentRequirements.hs
+++ b/src/Hercules/API/Build/AgentRequirements.hs
@@ -3,6 +3,7 @@
 
 module Hercules.API.Build.AgentRequirements where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Prelude
 
 data AgentRequirements = AgentRequirements
@@ -10,4 +11,4 @@
     requiredSystemFeatures :: [Text]
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Build/DerivationEvent.hs b/src/Hercules/API/Build/DerivationEvent.hs
--- a/src/Hercules/API/Build/DerivationEvent.hs
+++ b/src/Hercules/API/Build/DerivationEvent.hs
@@ -6,6 +6,7 @@
 module Hercules.API.Build.DerivationEvent where
 
 import Data.Aeson.Types (FromJSON (..), ToJSON (..), genericParseJSON, genericToEncoding, genericToJSON)
+import Data.OpenApi qualified as O3
 import Hercules.API.Accounts.SimpleAccount (SimpleAccount)
 import Hercules.API.Build.DerivationEvent.BuiltOutput
 import Hercules.API.Prelude
@@ -23,7 +24,7 @@
   | Built DerivationEventBuilt
   | HasCancelled DerivationEventHasCancelled
   | HasCancelledForReset DerivationEventHasCancelledForReset
-  deriving (Generic, Show, Eq, NFData, ToSchema)
+  deriving (Generic, Show, Eq, NFData, ToSchema, O3.ToSchema)
 
 instance FromJSON DerivationEvent where
   parseJSON = genericParseJSON schemaCompatibleOptions
@@ -52,13 +53,13 @@
     requeuedForAgent :: Maybe Text
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
 
 data DerivationEventDependencyFailed = DerivationEventDependencyFailed
   { time :: UTCTime
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
 
 data DerivationEventStarted = DerivationEventStarted
   { time :: UTCTime,
@@ -67,55 +68,55 @@
     streamable :: Bool
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
 
 data DerivationEventReset = DerivationEventReset
   { time :: UTCTime
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
 
 data DerivationEventFailed = DerivationEventFailed
   { time :: UTCTime,
     technicalError :: Maybe Text
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
 
 data DerivationEventSucceeded = DerivationEventSucceeded
   { time :: UTCTime
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
 
 data DerivationEventCancelled = DerivationEventCancelled
   { time :: UTCTime
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
 
 data DerivationEventForceCancelled = DerivationEventForceCancelled
   { time :: UTCTime,
     byUser :: Maybe SimpleAccount
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
 
 data DerivationEventBuilt = DerivationEventBuilt
   { time :: UTCTime,
     outputs :: [BuiltOutput]
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
 
 data DerivationEventHasCancelledForReset = DerivationEventHasCancelledForReset
   { time :: UTCTime
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
 
 data DerivationEventHasCancelled = DerivationEventHasCancelled
   { time :: UTCTime
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Build/DerivationEvent/BuiltOutput.hs b/src/Hercules/API/Build/DerivationEvent/BuiltOutput.hs
--- a/src/Hercules/API/Build/DerivationEvent/BuiltOutput.hs
+++ b/src/Hercules/API/Build/DerivationEvent/BuiltOutput.hs
@@ -3,6 +3,7 @@
 
 module Hercules.API.Build.DerivationEvent.BuiltOutput where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Prelude
 
 data BuiltOutput = BuiltOutput
@@ -12,4 +13,4 @@
     size :: Int64
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Build/DerivationInfo.hs b/src/Hercules/API/Build/DerivationInfo.hs
--- a/src/Hercules/API/Build/DerivationInfo.hs
+++ b/src/Hercules/API/Build/DerivationInfo.hs
@@ -3,6 +3,7 @@
 
 module Hercules.API.Build.DerivationInfo where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Build.DerivationEvent (DerivationEvent)
 import Hercules.API.Build.DerivationInfo.DerivationInput (DerivationInput)
 import Hercules.API.Build.DerivationInfo.DerivationOutput (DerivationOutput)
@@ -26,4 +27,4 @@
     dummy :: Maybe DerivationEvent -- TODO: remove and update/fix codegen
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Build/DerivationInfo/DerivationInput.hs b/src/Hercules/API/Build/DerivationInfo/DerivationInput.hs
--- a/src/Hercules/API/Build/DerivationInfo/DerivationInput.hs
+++ b/src/Hercules/API/Build/DerivationInfo/DerivationInput.hs
@@ -3,6 +3,7 @@
 
 module Hercules.API.Build.DerivationInfo.DerivationInput where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Derivation (DerivationStatus)
 import Hercules.API.Prelude
 
@@ -13,4 +14,4 @@
     outputPath :: Text
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Build/DerivationInfo/DerivationOutput.hs b/src/Hercules/API/Build/DerivationInfo/DerivationOutput.hs
--- a/src/Hercules/API/Build/DerivationInfo/DerivationOutput.hs
+++ b/src/Hercules/API/Build/DerivationInfo/DerivationOutput.hs
@@ -3,6 +3,7 @@
 
 module Hercules.API.Build.DerivationInfo.DerivationOutput where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Prelude
 
 data DerivationOutput = DerivationOutput
@@ -10,4 +11,4 @@
     outputPath :: Maybe Text
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Build/EvaluationDependency.hs b/src/Hercules/API/Build/EvaluationDependency.hs
--- a/src/Hercules/API/Build/EvaluationDependency.hs
+++ b/src/Hercules/API/Build/EvaluationDependency.hs
@@ -3,6 +3,7 @@
 
 module Hercules.API.Build.EvaluationDependency where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Derivation (Derivation)
 import Hercules.API.Prelude
 
@@ -12,4 +13,4 @@
     outputName :: Text
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Build/EvaluationDetail.hs b/src/Hercules/API/Build/EvaluationDetail.hs
--- a/src/Hercules/API/Build/EvaluationDetail.hs
+++ b/src/Hercules/API/Build/EvaluationDetail.hs
@@ -4,6 +4,7 @@
 
 module Hercules.API.Build.EvaluationDetail where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Attribute (Attribute)
 import Hercules.API.Build.AgentRequirements (AgentRequirements)
 import Hercules.API.Build.EvaluationDependency
@@ -40,8 +41,8 @@
     unmetAgentRequirements :: [AgentRequirements]
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
 
 newtype IFDAttribute = IFDAttribute (Attribute Derivation)
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Build/EvaluationDiff.hs b/src/Hercules/API/Build/EvaluationDiff.hs
--- a/src/Hercules/API/Build/EvaluationDiff.hs
+++ b/src/Hercules/API/Build/EvaluationDiff.hs
@@ -11,6 +11,7 @@
   )
 where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Attribute (Attribute)
 import Hercules.API.Derivation (Derivation)
 import Hercules.API.Evaluation.AttributeError (AttributeError)
@@ -32,26 +33,28 @@
   deriving (Generic, Show, Eq)
   deriving anyclass (NFData, ToJSON, FromJSON)
 
-deriving instance ToSchema a => ToSchema (Diff a)
+deriving instance (ToSchema a) => ToSchema (Diff a)
 
+deriving instance (O3.ToSchema a) => O3.ToSchema (Diff a)
+
 newtype AttributeDiff = AttributeDiff (SimpleAttribute AttributeValueDiff)
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
 
 newtype AttributeValueDiff = AttributeValueDiff (Diff (Attribute (Result AttributeError Derivation)))
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
 
 newtype IFDDiff = IFDDiff (Diff DerivationOutputNamePair)
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
 
 data DerivationOutputNamePair = DerivationOutputNamePair
   { derivation :: Derivation,
     outputName :: Text
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
 
 data EvaluationDiff = EvaluationDiff
   { beforeId :: Id Evaluation,
@@ -60,4 +63,4 @@
     ifds :: [IFDDiff]
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Build/FailureGraph.hs b/src/Hercules/API/Build/FailureGraph.hs
--- a/src/Hercules/API/Build/FailureGraph.hs
+++ b/src/Hercules/API/Build/FailureGraph.hs
@@ -3,6 +3,7 @@
 
 module Hercules.API.Build.FailureGraph where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Derivation (Derivation)
 import Hercules.API.Prelude
 
@@ -13,7 +14,7 @@
   { nodes :: [Node]
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
 
 -- | A derivation and any dependencies that caused it to fail, if applicable.
 data Node = Node
@@ -23,4 +24,4 @@
     failedDependencies :: [Text]
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Build/Log.hs b/src/Hercules/API/Build/Log.hs
--- a/src/Hercules/API/Build/Log.hs
+++ b/src/Hercules/API/Build/Log.hs
@@ -4,6 +4,7 @@
 
 module Hercules.API.Build.Log where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Build.LogLine
 import Hercules.API.Prelude
 
@@ -13,4 +14,4 @@
     done :: Bool
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Build/LogLine.hs b/src/Hercules/API/Build/LogLine.hs
--- a/src/Hercules/API/Build/LogLine.hs
+++ b/src/Hercules/API/Build/LogLine.hs
@@ -3,9 +3,10 @@
 
 module Hercules.API.Build.LogLine where
 
+import Data.OpenApi qualified as O3
 import Data.Word
 import Hercules.API.Prelude
 
 data LogLine = LogLine {i :: !Word64, ms :: !Word64, t :: !Text}
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/ClientInfo/ClientInfo.hs b/src/Hercules/API/ClientInfo/ClientInfo.hs
--- a/src/Hercules/API/ClientInfo/ClientInfo.hs
+++ b/src/Hercules/API/ClientInfo/ClientInfo.hs
@@ -3,6 +3,7 @@
 
 module Hercules.API.ClientInfo.ClientInfo where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Accounts.Account (Account)
 import Hercules.API.Forge.Forge (Forge)
 import Hercules.API.Prelude
@@ -16,4 +17,4 @@
     personalAccounts :: [Account]
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Derivation.hs b/src/Hercules/API/Derivation.hs
--- a/src/Hercules/API/Derivation.hs
+++ b/src/Hercules/API/Derivation.hs
@@ -3,20 +3,21 @@
 
 module Hercules.API.Derivation where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Prelude hiding (either)
 
 data DerivationPath = DerivationPath
   { drvPath :: Text
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
 
 data Derivation = Derivation
   { status :: DerivationStatus,
     derivationPath :: Text
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
 
 data DerivationStatus
   = Waiting
@@ -26,4 +27,4 @@
   | BuildSuccess
   | Cancelled
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Effects/EffectEvent.hs b/src/Hercules/API/Effects/EffectEvent.hs
--- a/src/Hercules/API/Effects/EffectEvent.hs
+++ b/src/Hercules/API/Effects/EffectEvent.hs
@@ -6,6 +6,7 @@
 module Hercules.API.Effects.EffectEvent where
 
 import Data.Aeson.Types (FromJSON (..), ToJSON (..), genericParseJSON, genericToEncoding, genericToJSON)
+import Data.OpenApi qualified as O3
 import Hercules.API.Prelude
 
 data EffectEvent
@@ -15,7 +16,7 @@
   | Failed EffectEventFailed
   | Succeeded EffectEventSucceeded
   | Cancelled EffectEventCancelled
-  deriving (Generic, Show, Eq, NFData, ToSchema)
+  deriving (Generic, Show, Eq, NFData, ToSchema, O3.ToSchema)
 
 instance FromJSON EffectEvent where
   parseJSON = genericParseJSON schemaCompatibleOptions
@@ -37,13 +38,13 @@
   { time :: UTCTime
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
 
 data EffectEventDependencyFailed = EffectEventDependencyFailed
   { time :: UTCTime
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
 
 data EffectEventStarted = EffectEventStarted
   { time :: UTCTime,
@@ -52,29 +53,29 @@
     agentVersion :: Text
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
 
 data EffectEventReset = EffectEventReset
   { time :: UTCTime
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
 
 data EffectEventFailed = EffectEventFailed
   { time :: UTCTime,
     technicalError :: Maybe Text
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
 
 data EffectEventSucceeded = EffectEventSucceeded
   { time :: UTCTime
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
 
 data EffectEventCancelled = EffectEventCancelled
   { time :: UTCTime
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Effects/EffectInfo.hs b/src/Hercules/API/Effects/EffectInfo.hs
--- a/src/Hercules/API/Effects/EffectInfo.hs
+++ b/src/Hercules/API/Effects/EffectInfo.hs
@@ -3,6 +3,7 @@
 
 module Hercules.API.Effects.EffectInfo where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Build.DerivationInfo.DerivationInput (DerivationInput)
 import Hercules.API.Effects.EffectEvent (EffectEvent)
 import Hercules.API.Effects.EffectReference (EffectReference)
@@ -19,7 +20,7 @@
   | Successful
   | Cancelled
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
 
 data EffectInfo = EffectInfo
   { status :: EffectStatus,
@@ -35,4 +36,4 @@
     dummy :: Maybe EffectEvent -- TODO: remove and update/fix codegen
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Effects/EffectReference.hs b/src/Hercules/API/Effects/EffectReference.hs
--- a/src/Hercules/API/Effects/EffectReference.hs
+++ b/src/Hercules/API/Effects/EffectReference.hs
@@ -3,6 +3,7 @@
 
 module Hercules.API.Effects.EffectReference where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Prelude
 import Hercules.API.Projects.SimpleJob (SimpleJob)
 
@@ -11,4 +12,4 @@
     attributePath :: [Text]
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Error.hs b/src/Hercules/API/Error.hs
--- a/src/Hercules/API/Error.hs
+++ b/src/Hercules/API/Error.hs
@@ -3,6 +3,7 @@
 
 module Hercules.API.Error where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Prelude
 
 -- | General error type used in (some) HTTP error response bodies and in some
@@ -15,4 +16,4 @@
     message :: Text
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Evaluation/AttributeError.hs b/src/Hercules/API/Evaluation/AttributeError.hs
--- a/src/Hercules/API/Evaluation/AttributeError.hs
+++ b/src/Hercules/API/Evaluation/AttributeError.hs
@@ -3,6 +3,7 @@
 
 module Hercules.API.Evaluation.AttributeError where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Prelude
 
 data AttributeError = AttributeError
@@ -14,4 +15,4 @@
     trace :: Maybe Text
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Evaluation/Evaluation.hs b/src/Hercules/API/Evaluation/Evaluation.hs
--- a/src/Hercules/API/Evaluation/Evaluation.hs
+++ b/src/Hercules/API/Evaluation/Evaluation.hs
@@ -3,10 +3,11 @@
 
 module Hercules.API.Evaluation.Evaluation where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Prelude
 
 data Evaluation = Evaluation
   { id :: Id Evaluation
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Forge/Forge.hs b/src/Hercules/API/Forge/Forge.hs
--- a/src/Hercules/API/Forge/Forge.hs
+++ b/src/Hercules/API/Forge/Forge.hs
@@ -3,6 +3,7 @@
 
 module Hercules.API.Forge.Forge where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Prelude
 
 -- | A source hosting site (example github for github.com) used for
@@ -17,4 +18,4 @@
     adminPermission :: Maybe Bool
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Forge/SimpleForge.hs b/src/Hercules/API/Forge/SimpleForge.hs
--- a/src/Hercules/API/Forge/SimpleForge.hs
+++ b/src/Hercules/API/Forge/SimpleForge.hs
@@ -3,6 +3,7 @@
 
 module Hercules.API.Forge.SimpleForge where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Forge.Forge (Forge)
 import Hercules.API.Prelude
 
@@ -12,4 +13,4 @@
     displayName :: Text
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/GitLab/CreateInstallationBuilderRequest.hs b/src/Hercules/API/GitLab/CreateInstallationBuilderRequest.hs
--- a/src/Hercules/API/GitLab/CreateInstallationBuilderRequest.hs
+++ b/src/Hercules/API/GitLab/CreateInstallationBuilderRequest.hs
@@ -3,6 +3,7 @@
 
 module Hercules.API.GitLab.CreateInstallationBuilderRequest where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Prelude
 
 data CreateInstallationBuilderRequest = CreateInstallationBuilderRequest
@@ -11,4 +12,4 @@
     gitlabAdminPassword :: Text
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/GitLab/InstallationBuilder.hs b/src/Hercules/API/GitLab/InstallationBuilder.hs
--- a/src/Hercules/API/GitLab/InstallationBuilder.hs
+++ b/src/Hercules/API/GitLab/InstallationBuilder.hs
@@ -3,6 +3,7 @@
 
 module Hercules.API.GitLab.InstallationBuilder where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Error (Error)
 import Hercules.API.Forge.SimpleForge (SimpleForge)
 import Hercules.API.Prelude
@@ -16,10 +17,10 @@
     errors :: [Error]
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
 
 data InstallationBuilders = InstallationBuilders
   { items :: [InstallationBuilder]
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/GitLab/PatchInstallationBuilder.hs b/src/Hercules/API/GitLab/PatchInstallationBuilder.hs
--- a/src/Hercules/API/GitLab/PatchInstallationBuilder.hs
+++ b/src/Hercules/API/GitLab/PatchInstallationBuilder.hs
@@ -3,6 +3,7 @@
 
 module Hercules.API.GitLab.PatchInstallationBuilder where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Prelude
 
 data PatchInstallationBuilder = PatchInstallationBuilder
@@ -10,4 +11,4 @@
     displayName :: Maybe Text
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Inputs/ImmutableGitInput.hs b/src/Hercules/API/Inputs/ImmutableGitInput.hs
--- a/src/Hercules/API/Inputs/ImmutableGitInput.hs
+++ b/src/Hercules/API/Inputs/ImmutableGitInput.hs
@@ -3,6 +3,7 @@
 
 module Hercules.API.Inputs.ImmutableGitInput where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Prelude
 import Hercules.API.Projects.SimpleJob (SimpleJob)
 import Hercules.API.Repos.SimpleRepo (SimpleRepo)
@@ -17,4 +18,4 @@
     historyURL :: Maybe Text
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Inputs/ImmutableInput.hs b/src/Hercules/API/Inputs/ImmutableInput.hs
--- a/src/Hercules/API/Inputs/ImmutableInput.hs
+++ b/src/Hercules/API/Inputs/ImmutableInput.hs
@@ -9,13 +9,14 @@
     genericToEncoding,
     genericToJSON,
   )
+import Data.OpenApi qualified as O3
 import Hercules.API.Inputs.ImmutableGitInput
 import Hercules.API.Prelude
 
 data ImmutableInput
   = GitInput ImmutableGitInput
   | IgnoreMe ()
-  deriving (Generic, Show, Eq, NFData, ToSchema)
+  deriving (Generic, Show, Eq, NFData, ToSchema, O3.ToSchema)
 
 instance FromJSON ImmutableInput where
   parseJSON = genericParseJSON schemaCompatibleOptions
diff --git a/src/Hercules/API/Labels.hs b/src/Hercules/API/Labels.hs
--- a/src/Hercules/API/Labels.hs
+++ b/src/Hercules/API/Labels.hs
@@ -6,6 +6,7 @@
 import Control.Lens ((?~))
 import Data.Aeson (Value)
 import Data.Function ((&))
+import Data.OpenApi qualified as O3
 import Data.Swagger
 import Hercules.API.Prelude
 
@@ -14,8 +15,16 @@
 
 instance ToSchema Labels where
   declareNamedSchema _p = do
-    return $
-      NamedSchema (Just "Labels") $
-        mempty
-          & type_ ?~ SwaggerObject
-          & additionalProperties ?~ AdditionalPropertiesAllowed True
+    return
+      $ NamedSchema (Just "Labels")
+      $ mempty
+      & type_ ?~ SwaggerObject
+      & additionalProperties ?~ AdditionalPropertiesAllowed True
+
+instance O3.ToSchema Labels where
+  declareNamedSchema _p = do
+    return
+      $ O3.NamedSchema (Just "Labels")
+      $ mempty
+      & O3.type_ ?~ O3.OpenApiObject
+      & O3.additionalProperties ?~ O3.AdditionalPropertiesAllowed True
diff --git a/src/Hercules/API/Message.hs b/src/Hercules/API/Message.hs
--- a/src/Hercules/API/Message.hs
+++ b/src/Hercules/API/Message.hs
@@ -3,6 +3,7 @@
 
 module Hercules.API.Message where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Prelude
 
 data Message = Message
@@ -11,7 +12,7 @@
     message :: Text
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
 
 data Type
   = -- | Something went wrong, inform user about possible
@@ -27,4 +28,4 @@
     -- abstraction.
     Trace
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Organizations/BillingInfo.hs b/src/Hercules/API/Organizations/BillingInfo.hs
--- a/src/Hercules/API/Organizations/BillingInfo.hs
+++ b/src/Hercules/API/Organizations/BillingInfo.hs
@@ -3,6 +3,7 @@
 
 module Hercules.API.Organizations.BillingInfo where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Accounts.Account (Account)
 import Hercules.API.Prelude
 
@@ -11,4 +12,4 @@
     activeUsers :: [Account]
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Organizations/CreateOrganization.hs b/src/Hercules/API/Organizations/CreateOrganization.hs
--- a/src/Hercules/API/Organizations/CreateOrganization.hs
+++ b/src/Hercules/API/Organizations/CreateOrganization.hs
@@ -3,6 +3,7 @@
 
 module Hercules.API.Organizations.CreateOrganization where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Accounts.Account (Account)
 import Hercules.API.Prelude
 
@@ -11,4 +12,4 @@
     primaryAccountId :: Id Account
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Organizations/Organization.hs b/src/Hercules/API/Organizations/Organization.hs
--- a/src/Hercules/API/Organizations/Organization.hs
+++ b/src/Hercules/API/Organizations/Organization.hs
@@ -3,6 +3,7 @@
 
 module Hercules.API.Organizations.Organization where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.BillingStatus qualified as BillingStatus
 import Hercules.API.Prelude
 
@@ -17,4 +18,4 @@
     subscriptionUpdateUrl :: Maybe Text
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Organizations/PaymentLink.hs b/src/Hercules/API/Organizations/PaymentLink.hs
--- a/src/Hercules/API/Organizations/PaymentLink.hs
+++ b/src/Hercules/API/Organizations/PaymentLink.hs
@@ -3,6 +3,7 @@
 
 module Hercules.API.Organizations.PaymentLink where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Prelude
 
 data PaymentLink = PaymentLink
@@ -10,4 +11,4 @@
     productId :: Integer
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Orphans.hs b/src/Hercules/API/Orphans.hs
--- a/src/Hercules/API/Orphans.hs
+++ b/src/Hercules/API/Orphans.hs
@@ -1,15 +1,46 @@
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE OverloadedLists #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE TypeApplications #-}
 {-# OPTIONS_GHC -fno-warn-orphans #-}
 
 module Hercules.API.Orphans where
 
+import Control.Lens.Operators ((<>~))
+import Data.Data (Typeable)
+import Data.Function ((&), (.))
+import Data.Maybe (Maybe (Just))
+import Data.OpenApi qualified as O3
 import Data.Proxy
 import Data.Swagger
 import Servant.API
+import Servant.Auth (Auth, JWT)
+import Servant.OpenApi qualified as SO3
 
 -- | Ignores Headers.
 --
 -- FIXME: don't ignore headers
-instance forall a hs. ToSchema a => ToSchema (Headers hs a) where
+instance forall a hs. (ToSchema a) => ToSchema (Headers hs a) where
   declareNamedSchema _ = declareNamedSchema (Proxy @a)
+
+-- | Ignores Headers.
+--
+-- FIXME: don't ignore headers
+instance forall a hs. (O3.ToSchema a, Typeable hs) => O3.ToSchema (Headers hs a) where
+  declareNamedSchema _ = O3.declareNamedSchema (Proxy @a)
+
+instance (SO3.HasOpenApi a) => SO3.HasOpenApi (Auth '[JWT] x :> a) where
+  toOpenApi _ =
+    SO3.toOpenApi (Proxy :: Proxy a)
+      & O3.security
+        <>~ [ O3.SecurityRequirement [("jwt", [])]
+            ]
+      & O3.components . O3.securitySchemes
+        <>~ O3.SecurityDefinitions
+          [ ( "jwt",
+              O3.SecurityScheme
+                (O3.SecuritySchemeHttp (O3.HttpSchemeBearer (Just "jwt")))
+                (Just "JSON Web Token authentication")
+            )
+          ]
diff --git a/src/Hercules/API/Paging.hs b/src/Hercules/API/Paging.hs
--- a/src/Hercules/API/Paging.hs
+++ b/src/Hercules/API/Paging.hs
@@ -3,6 +3,7 @@
 
 module Hercules.API.Paging where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Prelude
 
 -- To be used in newtypes only; otherwise the schema will have colliding
@@ -15,4 +16,6 @@
   }
   deriving (Generic, Show, Eq, NFData, ToJSON, FromJSON)
 
-deriving instance ToSchema a => ToSchema (PagedResponse a)
+deriving instance (ToSchema a) => ToSchema (PagedResponse a)
+
+deriving instance (O3.ToSchema a) => O3.ToSchema (PagedResponse a)
diff --git a/src/Hercules/API/Projects.hs b/src/Hercules/API/Projects.hs
--- a/src/Hercules/API/Projects.hs
+++ b/src/Hercules/API/Projects.hs
@@ -4,6 +4,7 @@
 
 module Hercules.API.Projects where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Accounts.Account (Account)
 import Hercules.API.Build.EvaluationDetail
   ( EvaluationDetail,
@@ -246,4 +247,4 @@
 
 newtype PagedJobs = PagedJobs (PagedResponse Job)
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Projects/CreateProject.hs b/src/Hercules/API/Projects/CreateProject.hs
--- a/src/Hercules/API/Projects/CreateProject.hs
+++ b/src/Hercules/API/Projects/CreateProject.hs
@@ -3,6 +3,7 @@
 
 module Hercules.API.Projects.CreateProject where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Prelude
 import Hercules.API.Repos.Repo (Repo)
 
@@ -11,4 +12,4 @@
     enabled :: Bool
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Projects/CreateUserEffectTokenResponse.hs b/src/Hercules/API/Projects/CreateUserEffectTokenResponse.hs
--- a/src/Hercules/API/Projects/CreateUserEffectTokenResponse.hs
+++ b/src/Hercules/API/Projects/CreateUserEffectTokenResponse.hs
@@ -3,10 +3,11 @@
 
 module Hercules.API.Projects.CreateUserEffectTokenResponse where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Prelude
 
 data CreateUserEffectTokenResponse = CreateUserEffectTokenResponse
   { token :: Text
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Projects/Job.hs b/src/Hercules/API/Projects/Job.hs
--- a/src/Hercules/API/Projects/Job.hs
+++ b/src/Hercules/API/Projects/Job.hs
@@ -8,6 +8,7 @@
   )
 where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Accounts.Account (Account)
 import Hercules.API.Evaluation.Evaluation
   ( Evaluation,
@@ -49,7 +50,7 @@
     mayRerun :: Bool
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
 
 data JobType
   = Config
@@ -57,7 +58,7 @@
   | OnPush
   | OnSchedule
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
 
 data GitCommitSource = GitCommitSource
   { revision :: Text,
@@ -68,11 +69,11 @@
     link :: Text
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
 
 data ProjectAndJobs = ProjectAndJobs
   { project :: Project,
     jobs :: [Job]
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Projects/JobHandlers.hs b/src/Hercules/API/Projects/JobHandlers.hs
--- a/src/Hercules/API/Projects/JobHandlers.hs
+++ b/src/Hercules/API/Projects/JobHandlers.hs
@@ -6,6 +6,7 @@
   )
 where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Prelude
 import Hercules.API.Projects.Job (Job)
 import Hercules.API.Projects.JobHandlers.OnPushHandler (OnPushHandler)
@@ -17,4 +18,4 @@
     onSchedule :: Map Text OnScheduleHandler
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Projects/JobHandlers/OnPushHandler.hs b/src/Hercules/API/Projects/JobHandlers/OnPushHandler.hs
--- a/src/Hercules/API/Projects/JobHandlers/OnPushHandler.hs
+++ b/src/Hercules/API/Projects/JobHandlers/OnPushHandler.hs
@@ -6,6 +6,7 @@
   )
 where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Prelude
 
 data OnPushHandler = OnPushHandler
@@ -13,4 +14,4 @@
     isFlake :: Bool
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Projects/JobHandlers/OnScheduleHandler.hs b/src/Hercules/API/Projects/JobHandlers/OnScheduleHandler.hs
--- a/src/Hercules/API/Projects/JobHandlers/OnScheduleHandler.hs
+++ b/src/Hercules/API/Projects/JobHandlers/OnScheduleHandler.hs
@@ -7,6 +7,7 @@
   )
 where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.DayOfWeek (DayOfWeek)
 import Hercules.API.Prelude
 
@@ -17,7 +18,7 @@
     mainExists :: Bool
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
 
 data TimeConstraints = TimeConstraints
   { minute :: Int,
@@ -26,4 +27,4 @@
     dayOfMonth :: Maybe [Int]
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Projects/LegacySimpleJob.hs b/src/Hercules/API/Projects/LegacySimpleJob.hs
--- a/src/Hercules/API/Projects/LegacySimpleJob.hs
+++ b/src/Hercules/API/Projects/LegacySimpleJob.hs
@@ -4,6 +4,7 @@
 
 module Hercules.API.Projects.LegacySimpleJob where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Prelude
 import Hercules.API.Projects.Project (Project)
 import Hercules.API.Projects.SimpleJob (JobPhase, JobStatus)
@@ -17,4 +18,4 @@
     phase :: JobPhase
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Projects/PatchProject.hs b/src/Hercules/API/Projects/PatchProject.hs
--- a/src/Hercules/API/Projects/PatchProject.hs
+++ b/src/Hercules/API/Projects/PatchProject.hs
@@ -3,6 +3,7 @@
 
 module Hercules.API.Projects.PatchProject where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Prelude
 
 -- | Changes to a Project. 'Nothing' represents no change in a field.
@@ -10,4 +11,4 @@
   { enabled :: Maybe Bool
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Projects/Project.hs b/src/Hercules/API/Projects/Project.hs
--- a/src/Hercules/API/Projects/Project.hs
+++ b/src/Hercules/API/Projects/Project.hs
@@ -3,6 +3,7 @@
 
 module Hercules.API.Projects.Project where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Accounts.Account (Account)
 import Hercules.API.Accounts.SimpleAccount (SimpleAccount)
 import Hercules.API.Forge.Forge (Forge)
@@ -27,4 +28,4 @@
     isPublic :: Bool
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Projects/SimpleJob.hs b/src/Hercules/API/Projects/SimpleJob.hs
--- a/src/Hercules/API/Projects/SimpleJob.hs
+++ b/src/Hercules/API/Projects/SimpleJob.hs
@@ -4,6 +4,7 @@
 
 module Hercules.API.Projects.SimpleJob where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Prelude
 import Hercules.API.Projects.SimpleProject (SimpleProject)
 
@@ -15,7 +16,7 @@
     phase :: JobPhase
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
 
 data JobPhase
   = Queued
@@ -24,14 +25,14 @@
   | Effects
   | Done
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
 
 data JobStatus
   = Pending
   | Failure
   | Success
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
 
 -- | Whichever is "worse": 'Failure' wins out, otherwise 'Pending' wins out, otherwise all are 'Success'.
 instance Semigroup JobStatus where
diff --git a/src/Hercules/API/Projects/SimpleProject.hs b/src/Hercules/API/Projects/SimpleProject.hs
--- a/src/Hercules/API/Projects/SimpleProject.hs
+++ b/src/Hercules/API/Projects/SimpleProject.hs
@@ -4,6 +4,7 @@
 
 module Hercules.API.Projects.SimpleProject where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Accounts.SimpleAccount (SimpleAccount)
 import Hercules.API.Prelude
 import Hercules.API.Projects.Project (Project)
@@ -20,4 +21,4 @@
     isPublic :: Bool
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Repos/Repo.hs b/src/Hercules/API/Repos/Repo.hs
--- a/src/Hercules/API/Repos/Repo.hs
+++ b/src/Hercules/API/Repos/Repo.hs
@@ -3,6 +3,7 @@
 
 module Hercules.API.Repos.Repo where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Accounts.Account (Account)
 import Hercules.API.Prelude
 
@@ -28,4 +29,4 @@
     isInstallable :: Bool
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Repos/RepoKey.hs b/src/Hercules/API/Repos/RepoKey.hs
--- a/src/Hercules/API/Repos/RepoKey.hs
+++ b/src/Hercules/API/Repos/RepoKey.hs
@@ -3,6 +3,7 @@
 
 module Hercules.API.Repos.RepoKey where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Prelude
 import Hercules.API.Projects.Project (Project)
 
@@ -13,4 +14,4 @@
     projectId :: Maybe (Id Project)
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Repos/SimpleRepo.hs b/src/Hercules/API/Repos/SimpleRepo.hs
--- a/src/Hercules/API/Repos/SimpleRepo.hs
+++ b/src/Hercules/API/Repos/SimpleRepo.hs
@@ -3,6 +3,7 @@
 
 module Hercules.API.Repos.SimpleRepo where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Accounts.SimpleAccount (SimpleAccount)
 import Hercules.API.Prelude
 import Hercules.API.Repos.Repo (Repo)
@@ -16,4 +17,4 @@
     isPublic :: Bool
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/Result.hs b/src/Hercules/API/Result.hs
--- a/src/Hercules/API/Result.hs
+++ b/src/Hercules/API/Result.hs
@@ -16,6 +16,7 @@
     genericToEncoding,
     genericToJSON,
   )
+import Data.OpenApi qualified as O3
 import Data.Profunctor
   ( Profunctor,
     dimap,
@@ -29,6 +30,8 @@
   deriving (Generic, Show, Read, Eq, Ord, NFData, Functor, Foldable, Traversable)
 
 deriving instance (ToSchema e, ToSchema a) => ToSchema (Result e a)
+
+deriving instance (O3.ToSchema e, O3.ToSchema a) => O3.ToSchema (Result e a)
 
 -- many more typeclasses can be implemented
 instance (FromJSON e, FromJSON a) => FromJSON (Result e a) where
diff --git a/src/Hercules/API/SimpleAttribute.hs b/src/Hercules/API/SimpleAttribute.hs
--- a/src/Hercules/API/SimpleAttribute.hs
+++ b/src/Hercules/API/SimpleAttribute.hs
@@ -7,6 +7,7 @@
   )
 where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Prelude
 import Prelude ()
 
@@ -18,7 +19,9 @@
   deriving (Generic, Show, Eq)
   deriving anyclass (NFData, FromJSON, ToJSON)
 
-deriving instance ToSchema a => ToSchema (SimpleAttribute a)
+deriving instance (ToSchema a) => ToSchema (SimpleAttribute a)
+
+deriving instance (O3.ToSchema a) => O3.ToSchema (SimpleAttribute a)
 
 deriving instance Functor SimpleAttribute
 
diff --git a/src/Hercules/API/State.hs b/src/Hercules/API/State.hs
--- a/src/Hercules/API/State.hs
+++ b/src/Hercules/API/State.hs
@@ -5,6 +5,7 @@
 module Hercules.API.State where
 
 import Data.ByteString (ByteString)
+import Data.OpenApi qualified as O3
 import Data.Swagger (NamedSchema (NamedSchema), binarySchema)
 import Data.Swagger.Schema (ToSchema (..))
 import Hercules.API.Accounts.Account (Account)
@@ -23,6 +24,9 @@
 
 instance ToSchema RawBytes where
   declareNamedSchema _ = pure $ NamedSchema (Just "RawBytes") binarySchema
+
+instance O3.ToSchema RawBytes where
+  declareNamedSchema _ = pure $ O3.NamedSchema (Just "RawBytes") O3.binarySchema
 
 type ContentLength = Header "Content-Length" Integer
 
diff --git a/src/Hercules/API/State/ProjectState.hs b/src/Hercules/API/State/ProjectState.hs
--- a/src/Hercules/API/State/ProjectState.hs
+++ b/src/Hercules/API/State/ProjectState.hs
@@ -3,6 +3,7 @@
 
 module Hercules.API.State.ProjectState where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Prelude
 import Hercules.API.Projects.Project (Project)
 import Hercules.API.State.StateFile (StateFile)
@@ -12,4 +13,4 @@
     stateFiles :: Map Text StateFile
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/State/StateFile.hs b/src/Hercules/API/State/StateFile.hs
--- a/src/Hercules/API/State/StateFile.hs
+++ b/src/Hercules/API/State/StateFile.hs
@@ -3,6 +3,7 @@
 
 module Hercules.API.State.StateFile where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Prelude
 import Hercules.API.Projects.Project (Project)
 import Hercules.API.State.StateVersion (StateVersion)
@@ -13,4 +14,4 @@
     versions :: [StateVersion]
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/State/StateLockAcquireRequest.hs b/src/Hercules/API/State/StateLockAcquireRequest.hs
--- a/src/Hercules/API/State/StateLockAcquireRequest.hs
+++ b/src/Hercules/API/State/StateLockAcquireRequest.hs
@@ -4,6 +4,7 @@
 
 module Hercules.API.State.StateLockAcquireRequest where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Prelude
 
 data StateLockAcquireRequest = StateLockAcquireRequest
@@ -19,4 +20,4 @@
     idempotencyKey :: Maybe (Id "IdempotencyKey")
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/State/StateLockAcquireResponse.hs b/src/Hercules/API/State/StateLockAcquireResponse.hs
--- a/src/Hercules/API/State/StateLockAcquireResponse.hs
+++ b/src/Hercules/API/State/StateLockAcquireResponse.hs
@@ -4,6 +4,7 @@
 
 module Hercules.API.State.StateLockAcquireResponse where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Prelude
 import Hercules.API.State.StateLockLease (StateLockLease)
 
@@ -11,17 +12,17 @@
   = Acquired StateLockAcquiredResponse
   | Blocked StateLockBlockedResponse
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
 
 data StateLockAcquiredResponse = StateLockAcquiredResponse
   { leaseId :: Id "StateLockLease",
     expirationTime :: UTCTime
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
 
 data StateLockBlockedResponse = LockBlockedResponse
   { blockedByLeases :: [StateLockLease]
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/State/StateLockLease.hs b/src/Hercules/API/State/StateLockLease.hs
--- a/src/Hercules/API/State/StateLockLease.hs
+++ b/src/Hercules/API/State/StateLockLease.hs
@@ -4,6 +4,7 @@
 
 module Hercules.API.State.StateLockLease where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Accounts.SimpleAccount (SimpleAccount)
 import Hercules.API.Prelude
 import Hercules.API.Projects.SimpleJob (SimpleJob)
@@ -27,4 +28,4 @@
     exclusive :: Bool
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/State/StateLockUpdateRequest.hs b/src/Hercules/API/State/StateLockUpdateRequest.hs
--- a/src/Hercules/API/State/StateLockUpdateRequest.hs
+++ b/src/Hercules/API/State/StateLockUpdateRequest.hs
@@ -4,10 +4,11 @@
 
 module Hercules.API.State.StateLockUpdateRequest where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Prelude
 
 data StateLockUpdateRequest = StateLockUpdateRequest
   { description :: Maybe Text
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/API/State/StateVersion.hs b/src/Hercules/API/State/StateVersion.hs
--- a/src/Hercules/API/State/StateVersion.hs
+++ b/src/Hercules/API/State/StateVersion.hs
@@ -3,6 +3,7 @@
 
 module Hercules.API.State.StateVersion where
 
+import Data.OpenApi qualified as O3
 import Hercules.API.Accounts.Account (Account)
 import Hercules.API.Prelude
 import Hercules.API.Projects.Job (Job)
@@ -22,4 +23,4 @@
     size :: Maybe Int
   }
   deriving (Generic, Show, Eq)
-  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema)
+  deriving anyclass (NFData, ToJSON, FromJSON, ToSchema, O3.ToSchema)
diff --git a/src/Hercules/Frontend.hs b/src/Hercules/Frontend.hs
--- a/src/Hercules/Frontend.hs
+++ b/src/Hercules/Frontend.hs
@@ -55,8 +55,8 @@
   deriving (Generic)
 
 mkLinks :: URI -> FrontendRoutes Raw (AsLink Text)
-mkLinks base = allFieldLinks' $
-  \link -> shows2Text $ uriToString id $ linkURI link `relativeTo` base
+mkLinks base = allFieldLinks'
+  $ \link -> shows2Text $ uriToString id $ linkURI link `relativeTo` base
   where
     shows2Text :: ShowS -> Text
     shows2Text = T.pack . ($ "")
