diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2026 Justin Strong
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,203 @@
+## OpenAPI Auto-Generated [http-client](https://www.stackage.org/lts-10.0/package/http-client-0.5.7.1) Bindings to `Agent Push Kit API`
+
+The library in `lib` provides auto-generated-from-OpenAPI [http-client](https://www.stackage.org/lts-10.0/package/http-client-0.5.7.1) bindings to the Agent Push Kit API API.
+
+OpenApi Version: 3.1.0
+
+## Installation
+
+Installation follows the standard approach to installing Stack-based projects.
+
+1. Install the [Haskell `stack` tool](http://docs.haskellstack.org/en/stable/README).
+2. To build the package, and generate the documentation (recommended):
+```
+stack haddock
+```
+which will generate docs for this lib in the `docs` folder.
+
+To generate the docs in the normal location (to enable hyperlinks to external libs), remove
+```
+build:
+  haddock-arguments:
+    haddock-args:
+    - "--odir=./docs"
+```
+from the stack.yaml file and run `stack haddock` again.
+
+3. To run unit tests:
+```
+stack test
+```
+
+## OpenAPI-Generator
+
+The code generator that produced this library, and which explains how
+to obtain and use the openapi-generator cli tool lives at
+
+https://openapi-generator.tech
+
+The _generator-name_ argument (`--generator-name`) passed to the cli tool used should be
+
+```
+haskell-http-client
+```
+
+### Unsupported OpenAPI Features
+
+* Model Inheritance
+
+This is beta software; other cases may not be supported.
+
+### Codegen "additional properties" parameters
+
+These options allow some customization of the code generation process.
+
+**haskell-http-client additional properties:**
+
+| OPTION                          | DESCRIPTION                                                                                                                   | DEFAULT  | ACTUAL                                |
+|---------------------------------|-------------------------------------------------------------------------------------------------------------------------------|----------|---------------------------------------|
+| allowFromJsonNulls              | allow JSON Null during model decoding from JSON                                                                               | true     | true              |
+| allowNonUniqueOperationIds      | allow *different* API modules to contain the same operationId. Each API must be imported qualified                            | false    | false    |
+| allowToJsonNulls                | allow emitting JSON Null during model encoding to JSON                                                                        | false    | false                |
+| baseModule                      | Set the base module namespace                                                                                                 |          | AgentPushKit                      |
+| cabalPackage                    | Set the cabal package name, which consists of one or more alphanumeric words separated by hyphens                             |          | agent-push-kit                    |
+| cabalVersion                    | Set the cabal version number, consisting of a sequence of one or more integers separated by dots                              | 0.1.0.0  | 0.1.0.0                    |
+| customTestInstanceModule        | test module used to provide typeclass instances for types not known by the generator                                          |          |         |
+| configType                      | Set the name of the type used for configuration                                                                               |          | AgentPushKitConfig                      |
+| dateFormat                      | format string used to parse/render a date                                                                                     | %Y-%m-%d | %Y-%m-%d                      |
+| dateTimeFormat                  | format string used to parse/render a datetime. (Defaults to [formatISO8601Millis][1] when not provided)                       |          |                   |
+| dateTimeParseFormat             | overrides the format string used to parse a datetime                                                                          |          |              |
+| generateEnums                   | Generate specific datatypes for OpenAPI enums                                                                                 | true     | true                   |
+| generateFormUrlEncodedInstances | Generate FromForm/ToForm instances for models used by x-www-form-urlencoded operations (model fields must be primitive types) | true     | true |
+| generateLenses                  | Generate Lens optics for Models                                                                                               | true     | true                  |
+| generateModelConstructors       | Generate smart constructors (only supply required fields) for models                                                          | true     | true       |
+| inlineMimeTypes                 | Inline (hardcode) the content-type and accept parameters on operations, when there is only 1 option                           | true     | true                 |
+| modelDeriving                   | Additional classes to include in the deriving() clause of Models                                                              |          |                    |
+| requestType                     | Set the name of the type used to generate requests                                                                            |          | AgentPushKitRequest                     |
+| strictFields                    | Add strictness annotations to all model fields                                                                                | true     | true                  |
+| useKatip                        | Sets the default value for the UseKatip cabal flag. If true, the katip package provides logging instead of monad-logger       | true     | true                      |
+| queryExtraUnreserved            | Configures additional querystring characters which must not be URI encoded, e.g. '+' or ':'                                   |          |           |
+
+[1]: https://www.stackage.org/haddock/lts-9.0/iso8601-time-0.1.4/Data-Time-ISO8601.html#v:formatISO8601Millis
+
+An example setting _dateTimeFormat_ and _strictFields_:
+
+```
+java -jar openapi-generator-cli.jar generate -i petstore.yaml -g haskell-http-client -o output/haskell-http-client --additional-properties=dateTimeFormat="%Y-%m-%dT%H:%M:%S%Q%z" --additional-properties=strictFields=false
+```
+
+View the full list of Codegen "config option" parameters with the command:
+
+```
+java -jar openapi-generator-cli.jar config-help -g haskell-http-client
+```
+
+## Usage Notes
+
+### Example Petstore Haddock documentation
+
+An example of the generated haddock documentation targeting the server http://petstore.swagger.io/ (Petstore) can be found [here][2]
+
+[2]: https://hackage.haskell.org/package/swagger-petstore
+
+### Example Petstore App
+
+An example application using the auto-generated haskell-http-client bindings for the server http://petstore.swagger.io/ can be found [here][3]
+
+[3]: https://github.com/openapitools/openapi-generator/tree/master/samples/client/petstore/haskell-http-client/example-app
+
+This library is intended to be imported qualified.
+
+### Modules
+
+| MODULE              | NOTES                                               |
+| ------------------- | --------------------------------------------------- |
+| AgentPushKit.Client    | use the "dispatch" functions to send requests       |
+| AgentPushKit.Core      | core functions, config and request types            |
+| AgentPushKit.API       | construct api requests                              |
+| AgentPushKit.Model     | describes api models                                |
+| AgentPushKit.MimeTypes | encoding/decoding MIME types (content-types/accept) |
+| AgentPushKit.ModelLens | lenses for model fields                             |
+| AgentPushKit.Logging   | logging functions and utils                         |
+
+
+### MimeTypes
+
+This library adds type safety around what OpenAPI specifies as
+Produces and Consumes for each Operation (e.g. the list of MIME types an
+Operation can Produce (using 'accept' headers) and Consume (using 'content-type' headers).
+
+For example, if there is an Operation named _addFoo_, there will be a
+data type generated named _AddFoo_ (note the capitalization), which
+describes additional constraints and actions on the _addFoo_ operation
+via its typeclass instances. These typeclass instances can be viewed
+in GHCi or via the Haddocks.
+
+* required parameters are included as function arguments to _addFoo_
+* optional non-body parameters are included by using  `applyOptionalParam`
+* optional body parameters are set by using  `setBodyParam`
+
+Example code generated for pretend _addFoo_ operation:
+
+```haskell
+data AddFoo
+instance Consumes AddFoo MimeJSON
+instance Produces AddFoo MimeJSON
+instance Produces AddFoo MimeXML
+instance HasBodyParam AddFoo FooModel
+instance HasOptionalParam AddFoo FooName
+instance HasOptionalParam AddFoo FooId
+```
+
+this would indicate that:
+
+* the _addFoo_ operation can consume JSON
+* the _addFoo_ operation produces JSON or XML, depending on the argument passed to the dispatch function
+* the _addFoo_ operation can set it's body param of _FooModel_ via `setBodyParam`
+* the _addFoo_ operation can set 2 different optional parameters via `applyOptionalParam`
+
+If the OpenAPI spec doesn't declare it can accept or produce a certain
+MIME type for a given Operation, you should either add a Produces or
+Consumes instance for the desired MIME types (assuming the server
+supports it), use `dispatchLbsUnsafe` or modify the OpenAPI spec and
+run the generator again.
+
+New MIME type instances can be added via MimeType/MimeRender/MimeUnrender
+
+Only JSON instances are generated by default, and in some case
+x-www-form-urlencoded instances (FromFrom, ToForm) will also be
+generated if the model fields are primitive types, and there are
+Operations using x-www-form-urlencoded which use those models.
+
+### Authentication
+
+A haskell data type will be generated for each OpenAPI authentication type.
+
+If for example the AuthMethod `AuthOAuthFoo` is generated for OAuth operations, then
+`addAuthMethod` should be used to add the AuthMethod config.
+
+When a request is dispatched, if a matching auth method is found in
+the config, it will be applied to the request.
+
+### Example
+
+```haskell
+mgr <- newManager defaultManagerSettings
+config0 <- withStdoutLogging =<< newConfig
+let config = config0
+    `addAuthMethod` AuthOAuthFoo "secret-key"
+
+let addFooRequest =
+  addFoo
+    (ContentType MimeJSON)
+    (Accept MimeXML)
+    (ParamBar paramBar)
+    (ParamQux paramQux)
+    modelBaz
+  `applyOptionalParam` FooId 1
+  `applyOptionalParam` FooName "name"
+  `setHeader` [("qux_header","xxyy")]
+addFooResult <- dispatchMime mgr config addFooRequest
+```
+
+See the example app and the haddocks for details.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/agent-push-kit.cabal b/agent-push-kit.cabal
new file mode 100644
--- /dev/null
+++ b/agent-push-kit.cabal
@@ -0,0 +1,121 @@
+name:           agent-push-kit
+version:        0.1.0
+synopsis:       Auto-generated agent-push-kit API Client
+description:    .
+                Client library for calling the Agent Push Kit API API based on http-client.
+                .
+                host: api.chatdna.co
+                .
+                base path: https://api.chatdna.co/agent-push-kit/v1
+                .
+                Agent Push Kit API API version: 0.1.0
+                .
+                OpenAPI version: 3.1.0
+                .
+                Generator version: 7.24.0
+                .
+category:       Web
+homepage:       https://agentpushkit.com
+author:         Justin Strong
+maintainer:     JustinBStrong@users.noreply.github.com
+copyright:      2026 Justin Strong
+license:        MIT
+license-file:   LICENSE
+build-type:     Simple
+cabal-version:  >= 1.10
+
+extra-source-files:
+    README.md
+    openapi.yaml
+
+Flag UseKatip
+  Description: Use the katip package to provide logging (if false, use the default monad-logger package)
+  Default:     True
+  Manual:      True
+
+library
+  hs-source-dirs:
+      lib
+  ghc-options: -Wall -funbox-strict-fields
+  build-depends:
+      aeson >=1.0 && <3.0
+    , base >=4.7 && <5.0
+    , base64-bytestring >1.0 && <2.0
+    , bytestring >=0.10.0
+    , case-insensitive
+    , containers >=0.5.0.0 && <0.8
+    , deepseq >= 1.4 && <1.6
+    , exceptions >= 0.4
+    , http-api-data >= 0.3.4 && <0.7
+    , http-client >=0.5 && <0.8
+    , http-client-tls
+    , http-media >= 0.4 && < 0.9
+    , http-types >=0.8 && <0.13
+    , iso8601-time >=0.1.3 && <0.2.0
+    , microlens >= 0.4.3
+    , mtl >=2.2.1
+    , network >=2.6.2 && <3.9
+    , random >=1.1
+    , safe-exceptions <0.2
+    , text >=0.11 && <3
+    , time >=1.5
+    , transformers >=0.4.0.0
+    , unordered-containers
+    , vector >=0.10.9 && <0.14
+  other-modules:
+      Paths_agent_push_kit
+  exposed-modules:
+      AgentPushKit
+      AgentPushKit.API
+      AgentPushKit.API.Account
+      AgentPushKit.API.AgentTokens
+      AgentPushKit.API.Authentication
+      AgentPushKit.API.CustomerAccounts
+      AgentPushKit.API.Devices
+      AgentPushKit.API.Events
+      AgentPushKit.API.Health
+      AgentPushKit.API.Preferences
+      AgentPushKit.Client
+      AgentPushKit.Core
+      AgentPushKit.Logging
+      AgentPushKit.MimeTypes
+      AgentPushKit.Model
+      AgentPushKit.ModelLens
+  default-language: Haskell2010
+
+  if flag(UseKatip)
+      build-depends: katip >=0.8 && < 1.0
+      other-modules: AgentPushKit.LoggingKatip
+      cpp-options: -DUSE_KATIP
+  else
+      build-depends: monad-logger >=0.3 && <0.4
+      other-modules: AgentPushKit.LoggingMonadLogger
+      cpp-options: -DUSE_MONAD_LOGGER
+
+test-suite tests
+  type: exitcode-stdio-1.0
+  main-is: Test.hs
+  hs-source-dirs:
+      tests
+  ghc-options: -Wall -fno-warn-orphans
+  build-depends:
+      agent-push-kit
+    , QuickCheck
+    , aeson
+    , base >=4.7 && <5.0
+    , bytestring >=0.10.0
+    , containers
+    , hspec >=1.8
+    , iso8601-time
+    , mtl >=2.2.1
+    , semigroups
+    , text
+    , time
+    , transformers >=0.4.0.0
+    , unordered-containers
+    , vector
+  other-modules:
+      ApproxEq
+      Instances
+      PropMime
+  default-language: Haskell2010
diff --git a/lib/AgentPushKit.hs b/lib/AgentPushKit.hs
new file mode 100644
--- /dev/null
+++ b/lib/AgentPushKit.hs
@@ -0,0 +1,31 @@
+{-
+   Agent Push Kit API
+
+   The complete Agent Push Kit REST API. Application event ingestion uses an organization key beginning with `apk_`. Authenticated user operations accept either an Agent Push Kit login JWT or an agent access token beginning with `apt_`.
+
+   OpenAPI Version: 3.1.0
+   Agent Push Kit API API version: 0.1.0
+   Generated by OpenAPI Generator (https://openapi-generator.tech)
+-}
+
+{-|
+Module : AgentPushKit
+-}
+
+module AgentPushKit
+  (  module AgentPushKit.API
+  , module AgentPushKit.Client
+  , module AgentPushKit.Core
+  , module AgentPushKit.Logging
+  , module AgentPushKit.MimeTypes
+  , module AgentPushKit.Model
+  , module AgentPushKit.ModelLens
+  ) where
+
+import AgentPushKit.API
+import AgentPushKit.Client
+import AgentPushKit.Core
+import AgentPushKit.Logging
+import AgentPushKit.MimeTypes
+import AgentPushKit.Model
+import AgentPushKit.ModelLens
diff --git a/lib/AgentPushKit/API.hs b/lib/AgentPushKit/API.hs
new file mode 100644
--- /dev/null
+++ b/lib/AgentPushKit/API.hs
@@ -0,0 +1,33 @@
+{-
+   Agent Push Kit API
+
+   The complete Agent Push Kit REST API. Application event ingestion uses an organization key beginning with `apk_`. Authenticated user operations accept either an Agent Push Kit login JWT or an agent access token beginning with `apt_`.
+
+   OpenAPI Version: 3.1.0
+   Agent Push Kit API API version: 0.1.0
+   Generated by OpenAPI Generator (https://openapi-generator.tech)
+-}
+
+{-|
+Module : AgentPushKit.API
+-}
+
+module AgentPushKit.API
+  ( module AgentPushKit.API.Account
+  , module AgentPushKit.API.AgentTokens
+  , module AgentPushKit.API.Authentication
+  , module AgentPushKit.API.CustomerAccounts
+  , module AgentPushKit.API.Devices
+  , module AgentPushKit.API.Events
+  , module AgentPushKit.API.Health
+  , module AgentPushKit.API.Preferences
+  ) where
+
+import AgentPushKit.API.Account
+import AgentPushKit.API.AgentTokens
+import AgentPushKit.API.Authentication
+import AgentPushKit.API.CustomerAccounts
+import AgentPushKit.API.Devices
+import AgentPushKit.API.Events
+import AgentPushKit.API.Health
+import AgentPushKit.API.Preferences
diff --git a/lib/AgentPushKit/API/Account.hs b/lib/AgentPushKit/API/Account.hs
new file mode 100644
--- /dev/null
+++ b/lib/AgentPushKit/API/Account.hs
@@ -0,0 +1,96 @@
+{-
+   Agent Push Kit API
+
+   The complete Agent Push Kit REST API. Application event ingestion uses an organization key beginning with `apk_`. Authenticated user operations accept either an Agent Push Kit login JWT or an agent access token beginning with `apt_`.
+
+   OpenAPI Version: 3.1.0
+   Agent Push Kit API API version: 0.1.0
+   Generated by OpenAPI Generator (https://openapi-generator.tech)
+-}
+
+{-|
+Module : AgentPushKit.API.Account
+-}
+
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MonoLocalBinds #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# OPTIONS_GHC -fno-warn-name-shadowing -fno-warn-unused-binds -fno-warn-unused-imports #-}
+
+module AgentPushKit.API.Account where
+
+import AgentPushKit.Core
+import AgentPushKit.MimeTypes
+import AgentPushKit.Model as M
+
+import qualified Data.Aeson as A
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Lazy as BL
+import qualified Data.Data as P (Typeable, TypeRep, typeOf, typeRep)
+import qualified Data.Foldable as P
+import qualified Data.Map as Map
+import qualified Data.Maybe as P
+import qualified Data.Proxy as P (Proxy(..))
+import qualified Data.Set as Set
+import qualified Data.String as P
+import qualified Data.Text as T
+import qualified Data.Text.Encoding as T
+import qualified Data.Text.Lazy as TL
+import qualified Data.Text.Lazy.Encoding as TL
+import qualified Data.Time as TI
+import qualified Network.HTTP.Client.MultipartFormData as NH
+import qualified Network.HTTP.Media as ME
+import qualified Network.HTTP.Types as NH
+import qualified Web.FormUrlEncoded as WH
+import qualified Web.HttpApiData as WH
+
+import Data.Text (Text)
+import GHC.Base ((<|>))
+
+import Prelude ((==),(/=),($), (.),(<$>),(<*>),(>>=),Maybe(..),Bool(..),Char,Double,FilePath,Float,Int,Integer,String,fmap,undefined,mempty,maybe,pure,Monad,Applicative,Functor)
+import qualified Prelude as P
+
+-- * Operations
+
+
+-- ** Account
+
+-- *** deleteCurrentAccount
+
+-- | @DELETE \/me@
+-- 
+-- Delete the current user and customer accounts they own
+-- 
+-- AuthMethod: 'AuthBasicUserOrAgent'
+-- 
+deleteCurrentAccount
+  :: AgentPushKitRequest DeleteCurrentAccount MimeNoContent DeletedResponse MimeJSON
+deleteCurrentAccount =
+  _mkRequest "DELETE" ["/me"]
+    `_hasAuthType` (P.Proxy :: P.Proxy AuthBasicUserOrAgent)
+
+data DeleteCurrentAccount  
+-- | @application/json@
+instance Produces DeleteCurrentAccount MimeJSON
+
+
+-- *** getCurrentAccount
+
+-- | @GET \/me@
+-- 
+-- Get the current user and customer accounts
+-- 
+-- AuthMethod: 'AuthBasicUserOrAgent'
+-- 
+getCurrentAccount
+  :: AgentPushKitRequest GetCurrentAccount MimeNoContent CurrentAccount MimeJSON
+getCurrentAccount =
+  _mkRequest "GET" ["/me"]
+    `_hasAuthType` (P.Proxy :: P.Proxy AuthBasicUserOrAgent)
+
+data GetCurrentAccount  
+-- | @application/json@
+instance Produces GetCurrentAccount MimeJSON
+
diff --git a/lib/AgentPushKit/API/AgentTokens.hs b/lib/AgentPushKit/API/AgentTokens.hs
new file mode 100644
--- /dev/null
+++ b/lib/AgentPushKit/API/AgentTokens.hs
@@ -0,0 +1,154 @@
+{-
+   Agent Push Kit API
+
+   The complete Agent Push Kit REST API. Application event ingestion uses an organization key beginning with `apk_`. Authenticated user operations accept either an Agent Push Kit login JWT or an agent access token beginning with `apt_`.
+
+   OpenAPI Version: 3.1.0
+   Agent Push Kit API API version: 0.1.0
+   Generated by OpenAPI Generator (https://openapi-generator.tech)
+-}
+
+{-|
+Module : AgentPushKit.API.AgentTokens
+-}
+
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MonoLocalBinds #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# OPTIONS_GHC -fno-warn-name-shadowing -fno-warn-unused-binds -fno-warn-unused-imports #-}
+
+module AgentPushKit.API.AgentTokens where
+
+import AgentPushKit.Core
+import AgentPushKit.MimeTypes
+import AgentPushKit.Model as M
+
+import qualified Data.Aeson as A
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Lazy as BL
+import qualified Data.Data as P (Typeable, TypeRep, typeOf, typeRep)
+import qualified Data.Foldable as P
+import qualified Data.Map as Map
+import qualified Data.Maybe as P
+import qualified Data.Proxy as P (Proxy(..))
+import qualified Data.Set as Set
+import qualified Data.String as P
+import qualified Data.Text as T
+import qualified Data.Text.Encoding as T
+import qualified Data.Text.Lazy as TL
+import qualified Data.Text.Lazy.Encoding as TL
+import qualified Data.Time as TI
+import qualified Network.HTTP.Client.MultipartFormData as NH
+import qualified Network.HTTP.Media as ME
+import qualified Network.HTTP.Types as NH
+import qualified Web.FormUrlEncoded as WH
+import qualified Web.HttpApiData as WH
+
+import Data.Text (Text)
+import GHC.Base ((<|>))
+
+import Prelude ((==),(/=),($), (.),(<$>),(<*>),(>>=),Maybe(..),Bool(..),Char,Double,FilePath,Float,Int,Integer,String,fmap,undefined,mempty,maybe,pure,Monad,Applicative,Functor)
+import qualified Prelude as P
+
+-- * Operations
+
+
+-- ** AgentTokens
+
+-- *** callMcp
+
+-- | @POST \/mcp@
+-- 
+-- Connect through stateless MCP Streamable HTTP
+-- 
+-- This endpoint accepts only an `apt_` agent access token.
+-- 
+-- AuthMethod: 'AuthBasicAgentToken'
+-- 
+callMcp
+  :: (Consumes CallMcp MimeJSON, MimeRender MimeJSON RequestBody)
+  => RequestBody -- ^ "requestBody"
+  -> AgentPushKitRequest CallMcp MimeJSON NoContent MimeNoContent
+callMcp requestBody =
+  _mkRequest "POST" ["/mcp"]
+    `_hasAuthType` (P.Proxy :: P.Proxy AuthBasicAgentToken)
+    `setBodyParam` requestBody
+
+data CallMcp 
+instance HasBodyParam CallMcp RequestBody 
+
+-- | @application/json@
+instance Consumes CallMcp MimeJSON
+
+instance Produces CallMcp MimeNoContent
+
+
+-- *** createAgentToken
+
+-- | @POST \/agent-tokens@
+-- 
+-- Create a named non-expiring agent token
+-- 
+-- The raw `apt_` token is shown once. Store it before dismissing the response.
+-- 
+-- AuthMethod: 'AuthBasicUserOrAgent'
+-- 
+createAgentToken
+  :: (Consumes CreateAgentToken MimeJSON, MimeRender MimeJSON CreateAgentTokenInput)
+  => CreateAgentTokenInput -- ^ "createAgentTokenInput"
+  -> AgentPushKitRequest CreateAgentToken MimeJSON AgentTokenCreated MimeJSON
+createAgentToken createAgentTokenInput =
+  _mkRequest "POST" ["/agent-tokens"]
+    `_hasAuthType` (P.Proxy :: P.Proxy AuthBasicUserOrAgent)
+    `setBodyParam` createAgentTokenInput
+
+data CreateAgentToken 
+instance HasBodyParam CreateAgentToken CreateAgentTokenInput 
+
+-- | @application/json@
+instance Consumes CreateAgentToken MimeJSON
+
+-- | @application/json@
+instance Produces CreateAgentToken MimeJSON
+
+
+-- *** listAgentTokens
+
+-- | @GET \/agent-tokens@
+-- 
+-- List agent access tokens without their secrets
+-- 
+-- AuthMethod: 'AuthBasicUserOrAgent'
+-- 
+listAgentTokens
+  :: AgentPushKitRequest ListAgentTokens MimeNoContent [AgentToken] MimeJSON
+listAgentTokens =
+  _mkRequest "GET" ["/agent-tokens"]
+    `_hasAuthType` (P.Proxy :: P.Proxy AuthBasicUserOrAgent)
+
+data ListAgentTokens  
+-- | @application/json@
+instance Produces ListAgentTokens MimeJSON
+
+
+-- *** revokeAgentToken
+
+-- | @DELETE \/agent-tokens\/{tokenId}@
+-- 
+-- Revoke one of the current user's agent tokens
+-- 
+-- AuthMethod: 'AuthBasicUserOrAgent'
+-- 
+revokeAgentToken
+  :: TokenId -- ^ "tokenId"
+  -> AgentPushKitRequest RevokeAgentToken MimeNoContent RevokedResponse MimeJSON
+revokeAgentToken (TokenId tokenId) =
+  _mkRequest "DELETE" ["/agent-tokens/",toPath tokenId]
+    `_hasAuthType` (P.Proxy :: P.Proxy AuthBasicUserOrAgent)
+
+data RevokeAgentToken  
+-- | @application/json@
+instance Produces RevokeAgentToken MimeJSON
+
diff --git a/lib/AgentPushKit/API/Authentication.hs b/lib/AgentPushKit/API/Authentication.hs
new file mode 100644
--- /dev/null
+++ b/lib/AgentPushKit/API/Authentication.hs
@@ -0,0 +1,202 @@
+{-
+   Agent Push Kit API
+
+   The complete Agent Push Kit REST API. Application event ingestion uses an organization key beginning with `apk_`. Authenticated user operations accept either an Agent Push Kit login JWT or an agent access token beginning with `apt_`.
+
+   OpenAPI Version: 3.1.0
+   Agent Push Kit API API version: 0.1.0
+   Generated by OpenAPI Generator (https://openapi-generator.tech)
+-}
+
+{-|
+Module : AgentPushKit.API.Authentication
+-}
+
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MonoLocalBinds #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# OPTIONS_GHC -fno-warn-name-shadowing -fno-warn-unused-binds -fno-warn-unused-imports #-}
+
+module AgentPushKit.API.Authentication where
+
+import AgentPushKit.Core
+import AgentPushKit.MimeTypes
+import AgentPushKit.Model as M
+
+import qualified Data.Aeson as A
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Lazy as BL
+import qualified Data.Data as P (Typeable, TypeRep, typeOf, typeRep)
+import qualified Data.Foldable as P
+import qualified Data.Map as Map
+import qualified Data.Maybe as P
+import qualified Data.Proxy as P (Proxy(..))
+import qualified Data.Set as Set
+import qualified Data.String as P
+import qualified Data.Text as T
+import qualified Data.Text.Encoding as T
+import qualified Data.Text.Lazy as TL
+import qualified Data.Text.Lazy.Encoding as TL
+import qualified Data.Time as TI
+import qualified Network.HTTP.Client.MultipartFormData as NH
+import qualified Network.HTTP.Media as ME
+import qualified Network.HTTP.Types as NH
+import qualified Web.FormUrlEncoded as WH
+import qualified Web.HttpApiData as WH
+
+import Data.Text (Text)
+import GHC.Base ((<|>))
+
+import Prelude ((==),(/=),($), (.),(<$>),(<*>),(>>=),Maybe(..),Bool(..),Char,Double,FilePath,Float,Int,Integer,String,fmap,undefined,mempty,maybe,pure,Monad,Applicative,Functor)
+import qualified Prelude as P
+
+-- * Operations
+
+
+-- ** Authentication
+
+-- *** completePasswordReset
+
+-- | @POST \/auth\/password-reset\/complete@
+-- 
+-- Choose a new password and log in
+-- 
+completePasswordReset
+  :: (Consumes CompletePasswordReset MimeJSON, MimeRender MimeJSON PasswordResetCompleteInput)
+  => PasswordResetCompleteInput -- ^ "passwordResetCompleteInput"
+  -> AgentPushKitRequest CompletePasswordReset MimeJSON AuthResponse MimeJSON
+completePasswordReset passwordResetCompleteInput =
+  _mkRequest "POST" ["/auth/password-reset/complete"]
+    `setBodyParam` passwordResetCompleteInput
+
+data CompletePasswordReset 
+instance HasBodyParam CompletePasswordReset PasswordResetCompleteInput 
+
+-- | @application/json@
+instance Consumes CompletePasswordReset MimeJSON
+
+-- | @application/json@
+instance Produces CompletePasswordReset MimeJSON
+
+
+-- *** loginWithApple
+
+-- | @POST \/auth\/apple@
+-- 
+-- Log in or attach an account using a Sign in with Apple identity token
+-- 
+loginWithApple
+  :: (Consumes LoginWithApple MimeJSON, MimeRender MimeJSON ProviderLoginInput)
+  => ProviderLoginInput -- ^ "providerLoginInput"
+  -> AgentPushKitRequest LoginWithApple MimeJSON AuthResponse MimeJSON
+loginWithApple providerLoginInput =
+  _mkRequest "POST" ["/auth/apple"]
+    `setBodyParam` providerLoginInput
+
+data LoginWithApple 
+instance HasBodyParam LoginWithApple ProviderLoginInput 
+
+-- | @application/json@
+instance Consumes LoginWithApple MimeJSON
+
+-- | @application/json@
+instance Produces LoginWithApple MimeJSON
+
+
+-- *** loginWithGoogle
+
+-- | @POST \/auth\/google@
+-- 
+-- Log in or attach an account using a verified Google ID token
+-- 
+loginWithGoogle
+  :: (Consumes LoginWithGoogle MimeJSON, MimeRender MimeJSON ProviderLoginInput)
+  => ProviderLoginInput -- ^ "providerLoginInput"
+  -> AgentPushKitRequest LoginWithGoogle MimeJSON AuthResponse MimeJSON
+loginWithGoogle providerLoginInput =
+  _mkRequest "POST" ["/auth/google"]
+    `setBodyParam` providerLoginInput
+
+data LoginWithGoogle 
+instance HasBodyParam LoginWithGoogle ProviderLoginInput 
+
+-- | @application/json@
+instance Consumes LoginWithGoogle MimeJSON
+
+-- | @application/json@
+instance Produces LoginWithGoogle MimeJSON
+
+
+-- *** loginWithPassword
+
+-- | @POST \/auth\/login@
+-- 
+-- Log in with email and password
+-- 
+loginWithPassword
+  :: (Consumes LoginWithPassword MimeJSON, MimeRender MimeJSON PasswordLoginInput)
+  => PasswordLoginInput -- ^ "passwordLoginInput"
+  -> AgentPushKitRequest LoginWithPassword MimeJSON AuthResponse MimeJSON
+loginWithPassword passwordLoginInput =
+  _mkRequest "POST" ["/auth/login"]
+    `setBodyParam` passwordLoginInput
+
+data LoginWithPassword 
+instance HasBodyParam LoginWithPassword PasswordLoginInput 
+
+-- | @application/json@
+instance Consumes LoginWithPassword MimeJSON
+
+-- | @application/json@
+instance Produces LoginWithPassword MimeJSON
+
+
+-- *** register
+
+-- | @POST \/auth\/register@
+-- 
+-- Create a user and first customer account
+-- 
+register
+  :: (Consumes Register MimeJSON, MimeRender MimeJSON RegisterInput)
+  => RegisterInput -- ^ "registerInput"
+  -> AgentPushKitRequest Register MimeJSON AuthResponse MimeJSON
+register registerInput =
+  _mkRequest "POST" ["/auth/register"]
+    `setBodyParam` registerInput
+
+data Register 
+instance HasBodyParam Register RegisterInput 
+
+-- | @application/json@
+instance Consumes Register MimeJSON
+
+-- | @application/json@
+instance Produces Register MimeJSON
+
+
+-- *** requestPasswordReset
+
+-- | @POST \/auth\/password-reset\/request@
+-- 
+-- Email a single-use password reset token
+-- 
+requestPasswordReset
+  :: (Consumes RequestPasswordReset MimeJSON, MimeRender MimeJSON PasswordResetRequestInput)
+  => PasswordResetRequestInput -- ^ "passwordResetRequestInput"
+  -> AgentPushKitRequest RequestPasswordReset MimeJSON AcceptedResponse MimeJSON
+requestPasswordReset passwordResetRequestInput =
+  _mkRequest "POST" ["/auth/password-reset/request"]
+    `setBodyParam` passwordResetRequestInput
+
+data RequestPasswordReset 
+instance HasBodyParam RequestPasswordReset PasswordResetRequestInput 
+
+-- | @application/json@
+instance Consumes RequestPasswordReset MimeJSON
+
+-- | @application/json@
+instance Produces RequestPasswordReset MimeJSON
+
diff --git a/lib/AgentPushKit/API/CustomerAccounts.hs b/lib/AgentPushKit/API/CustomerAccounts.hs
new file mode 100644
--- /dev/null
+++ b/lib/AgentPushKit/API/CustomerAccounts.hs
@@ -0,0 +1,174 @@
+{-
+   Agent Push Kit API
+
+   The complete Agent Push Kit REST API. Application event ingestion uses an organization key beginning with `apk_`. Authenticated user operations accept either an Agent Push Kit login JWT or an agent access token beginning with `apt_`.
+
+   OpenAPI Version: 3.1.0
+   Agent Push Kit API API version: 0.1.0
+   Generated by OpenAPI Generator (https://openapi-generator.tech)
+-}
+
+{-|
+Module : AgentPushKit.API.CustomerAccounts
+-}
+
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MonoLocalBinds #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# OPTIONS_GHC -fno-warn-name-shadowing -fno-warn-unused-binds -fno-warn-unused-imports #-}
+
+module AgentPushKit.API.CustomerAccounts where
+
+import AgentPushKit.Core
+import AgentPushKit.MimeTypes
+import AgentPushKit.Model as M
+
+import qualified Data.Aeson as A
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Lazy as BL
+import qualified Data.Data as P (Typeable, TypeRep, typeOf, typeRep)
+import qualified Data.Foldable as P
+import qualified Data.Map as Map
+import qualified Data.Maybe as P
+import qualified Data.Proxy as P (Proxy(..))
+import qualified Data.Set as Set
+import qualified Data.String as P
+import qualified Data.Text as T
+import qualified Data.Text.Encoding as T
+import qualified Data.Text.Lazy as TL
+import qualified Data.Text.Lazy.Encoding as TL
+import qualified Data.Time as TI
+import qualified Network.HTTP.Client.MultipartFormData as NH
+import qualified Network.HTTP.Media as ME
+import qualified Network.HTTP.Types as NH
+import qualified Web.FormUrlEncoded as WH
+import qualified Web.HttpApiData as WH
+
+import Data.Text (Text)
+import GHC.Base ((<|>))
+
+import Prelude ((==),(/=),($), (.),(<$>),(<*>),(>>=),Maybe(..),Bool(..),Char,Double,FilePath,Float,Int,Integer,String,fmap,undefined,mempty,maybe,pure,Monad,Applicative,Functor)
+import qualified Prelude as P
+
+-- * Operations
+
+
+-- ** CustomerAccounts
+
+-- *** addOrganizationMember
+
+-- | @POST \/organizations\/{organizationId}\/members@
+-- 
+-- Add an already-registered user to a customer account
+-- 
+-- AuthMethod: 'AuthBasicUserOrAgent'
+-- 
+addOrganizationMember
+  :: (Consumes AddOrganizationMember MimeJSON, MimeRender MimeJSON AddMemberInput)
+  => AddMemberInput -- ^ "addMemberInput"
+  -> OrganizationId -- ^ "organizationId"
+  -> AgentPushKitRequest AddOrganizationMember MimeJSON Membership MimeJSON
+addOrganizationMember addMemberInput (OrganizationId organizationId) =
+  _mkRequest "POST" ["/organizations/",toPath organizationId,"/members"]
+    `_hasAuthType` (P.Proxy :: P.Proxy AuthBasicUserOrAgent)
+    `setBodyParam` addMemberInput
+
+data AddOrganizationMember 
+instance HasBodyParam AddOrganizationMember AddMemberInput 
+
+-- | @application/json@
+instance Consumes AddOrganizationMember MimeJSON
+
+-- | @application/json@
+instance Produces AddOrganizationMember MimeJSON
+
+
+-- *** createOrganization
+
+-- | @POST \/organizations@
+-- 
+-- Create another Agent Push Kit customer account
+-- 
+-- AuthMethod: 'AuthBasicUserOrAgent'
+-- 
+createOrganization
+  :: (Consumes CreateOrganization MimeJSON, MimeRender MimeJSON CreateOrganizationInput)
+  => CreateOrganizationInput -- ^ "createOrganizationInput"
+  -> AgentPushKitRequest CreateOrganization MimeJSON OrganizationCreated MimeJSON
+createOrganization createOrganizationInput =
+  _mkRequest "POST" ["/organizations"]
+    `_hasAuthType` (P.Proxy :: P.Proxy AuthBasicUserOrAgent)
+    `setBodyParam` createOrganizationInput
+
+data CreateOrganization 
+instance HasBodyParam CreateOrganization CreateOrganizationInput 
+
+-- | @application/json@
+instance Consumes CreateOrganization MimeJSON
+
+-- | @application/json@
+instance Produces CreateOrganization MimeJSON
+
+
+-- *** listOrganizationMembers
+
+-- | @GET \/organizations\/{organizationId}\/members@
+-- 
+-- List members of a customer account
+-- 
+-- AuthMethod: 'AuthBasicUserOrAgent'
+-- 
+listOrganizationMembers
+  :: OrganizationId -- ^ "organizationId"
+  -> AgentPushKitRequest ListOrganizationMembers MimeNoContent [Membership] MimeJSON
+listOrganizationMembers (OrganizationId organizationId) =
+  _mkRequest "GET" ["/organizations/",toPath organizationId,"/members"]
+    `_hasAuthType` (P.Proxy :: P.Proxy AuthBasicUserOrAgent)
+
+data ListOrganizationMembers  
+-- | @application/json@
+instance Produces ListOrganizationMembers MimeJSON
+
+
+-- *** listOrganizations
+
+-- | @GET \/organizations@
+-- 
+-- List customer accounts available to the current user
+-- 
+-- AuthMethod: 'AuthBasicUserOrAgent'
+-- 
+listOrganizations
+  :: AgentPushKitRequest ListOrganizations MimeNoContent [Organization] MimeJSON
+listOrganizations =
+  _mkRequest "GET" ["/organizations"]
+    `_hasAuthType` (P.Proxy :: P.Proxy AuthBasicUserOrAgent)
+
+data ListOrganizations  
+-- | @application/json@
+instance Produces ListOrganizations MimeJSON
+
+
+-- *** regenerateOrganizationApiKey
+
+-- | @POST \/organizations\/{organizationId}\/api-key\/regenerate@
+-- 
+-- Rotate the application event-ingestion key
+-- 
+-- The previous `apk_` key stops working immediately. The replacement is returned only in this response.
+-- 
+-- AuthMethod: 'AuthBasicUserOrAgent'
+-- 
+regenerateOrganizationApiKey
+  :: OrganizationId -- ^ "organizationId"
+  -> AgentPushKitRequest RegenerateOrganizationApiKey MimeNoContent OrganizationApiKeyCreated MimeJSON
+regenerateOrganizationApiKey (OrganizationId organizationId) =
+  _mkRequest "POST" ["/organizations/",toPath organizationId,"/api-key/regenerate"]
+    `_hasAuthType` (P.Proxy :: P.Proxy AuthBasicUserOrAgent)
+
+data RegenerateOrganizationApiKey  
+-- | @application/json@
+instance Produces RegenerateOrganizationApiKey MimeJSON
+
diff --git a/lib/AgentPushKit/API/Devices.hs b/lib/AgentPushKit/API/Devices.hs
new file mode 100644
--- /dev/null
+++ b/lib/AgentPushKit/API/Devices.hs
@@ -0,0 +1,171 @@
+{-
+   Agent Push Kit API
+
+   The complete Agent Push Kit REST API. Application event ingestion uses an organization key beginning with `apk_`. Authenticated user operations accept either an Agent Push Kit login JWT or an agent access token beginning with `apt_`.
+
+   OpenAPI Version: 3.1.0
+   Agent Push Kit API API version: 0.1.0
+   Generated by OpenAPI Generator (https://openapi-generator.tech)
+-}
+
+{-|
+Module : AgentPushKit.API.Devices
+-}
+
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MonoLocalBinds #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# OPTIONS_GHC -fno-warn-name-shadowing -fno-warn-unused-binds -fno-warn-unused-imports #-}
+
+module AgentPushKit.API.Devices where
+
+import AgentPushKit.Core
+import AgentPushKit.MimeTypes
+import AgentPushKit.Model as M
+
+import qualified Data.Aeson as A
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Lazy as BL
+import qualified Data.Data as P (Typeable, TypeRep, typeOf, typeRep)
+import qualified Data.Foldable as P
+import qualified Data.Map as Map
+import qualified Data.Maybe as P
+import qualified Data.Proxy as P (Proxy(..))
+import qualified Data.Set as Set
+import qualified Data.String as P
+import qualified Data.Text as T
+import qualified Data.Text.Encoding as T
+import qualified Data.Text.Lazy as TL
+import qualified Data.Text.Lazy.Encoding as TL
+import qualified Data.Time as TI
+import qualified Network.HTTP.Client.MultipartFormData as NH
+import qualified Network.HTTP.Media as ME
+import qualified Network.HTTP.Types as NH
+import qualified Web.FormUrlEncoded as WH
+import qualified Web.HttpApiData as WH
+
+import Data.Text (Text)
+import GHC.Base ((<|>))
+
+import Prelude ((==),(/=),($), (.),(<$>),(<*>),(>>=),Maybe(..),Bool(..),Char,Double,FilePath,Float,Int,Integer,String,fmap,undefined,mempty,maybe,pure,Monad,Applicative,Functor)
+import qualified Prelude as P
+
+-- * Operations
+
+
+-- ** Devices
+
+-- *** getWebPushConfiguration
+
+-- | @GET \/web-push\/configuration@
+-- 
+-- Get browser push availability and its public VAPID key
+-- 
+-- AuthMethod: 'AuthBasicUserOrAgent'
+-- 
+getWebPushConfiguration
+  :: AgentPushKitRequest GetWebPushConfiguration MimeNoContent WebPushConfiguration MimeJSON
+getWebPushConfiguration =
+  _mkRequest "GET" ["/web-push/configuration"]
+    `_hasAuthType` (P.Proxy :: P.Proxy AuthBasicUserOrAgent)
+
+data GetWebPushConfiguration  
+-- | @application/json@
+instance Produces GetWebPushConfiguration MimeJSON
+
+
+-- *** registerDevice
+
+-- | @POST \/devices@
+-- 
+-- Register or refresh an APNs device
+-- 
+-- AuthMethod: 'AuthBasicUserOrAgent'
+-- 
+registerDevice
+  :: (Consumes RegisterDevice MimeJSON, MimeRender MimeJSON RegisterDeviceInput)
+  => RegisterDeviceInput -- ^ "registerDeviceInput"
+  -> AgentPushKitRequest RegisterDevice MimeJSON Device MimeJSON
+registerDevice registerDeviceInput =
+  _mkRequest "POST" ["/devices"]
+    `_hasAuthType` (P.Proxy :: P.Proxy AuthBasicUserOrAgent)
+    `setBodyParam` registerDeviceInput
+
+data RegisterDevice 
+instance HasBodyParam RegisterDevice RegisterDeviceInput 
+
+-- | @application/json@
+instance Consumes RegisterDevice MimeJSON
+
+-- | @application/json@
+instance Produces RegisterDevice MimeJSON
+
+
+-- *** registerWebPushSubscription
+
+-- | @POST \/web-push\/subscriptions@
+-- 
+-- Register or refresh a browser push subscription
+-- 
+-- AuthMethod: 'AuthBasicUserOrAgent'
+-- 
+registerWebPushSubscription
+  :: (Consumes RegisterWebPushSubscription MimeJSON, MimeRender MimeJSON RegisterWebPushSubscriptionInput)
+  => RegisterWebPushSubscriptionInput -- ^ "registerWebPushSubscriptionInput"
+  -> AgentPushKitRequest RegisterWebPushSubscription MimeJSON WebPushSubscription MimeJSON
+registerWebPushSubscription registerWebPushSubscriptionInput =
+  _mkRequest "POST" ["/web-push/subscriptions"]
+    `_hasAuthType` (P.Proxy :: P.Proxy AuthBasicUserOrAgent)
+    `setBodyParam` registerWebPushSubscriptionInput
+
+data RegisterWebPushSubscription 
+instance HasBodyParam RegisterWebPushSubscription RegisterWebPushSubscriptionInput 
+
+-- | @application/json@
+instance Consumes RegisterWebPushSubscription MimeJSON
+
+-- | @application/json@
+instance Produces RegisterWebPushSubscription MimeJSON
+
+
+-- *** removeDevice
+
+-- | @DELETE \/devices\/{installationId}@
+-- 
+-- Disable push delivery to one installation
+-- 
+-- AuthMethod: 'AuthBasicUserOrAgent'
+-- 
+removeDevice
+  :: InstallationId -- ^ "installationId"
+  -> AgentPushKitRequest RemoveDevice MimeNoContent DisabledResponse MimeJSON
+removeDevice (InstallationId installationId) =
+  _mkRequest "DELETE" ["/devices/",toPath installationId]
+    `_hasAuthType` (P.Proxy :: P.Proxy AuthBasicUserOrAgent)
+
+data RemoveDevice  
+-- | @application/json@
+instance Produces RemoveDevice MimeJSON
+
+
+-- *** removeWebPushSubscription
+
+-- | @DELETE \/web-push\/subscriptions\/{subscriptionId}@
+-- 
+-- Disable a browser push subscription
+-- 
+-- AuthMethod: 'AuthBasicUserOrAgent'
+-- 
+removeWebPushSubscription
+  :: SubscriptionId -- ^ "subscriptionId"
+  -> AgentPushKitRequest RemoveWebPushSubscription MimeNoContent DisabledResponse MimeJSON
+removeWebPushSubscription (SubscriptionId subscriptionId) =
+  _mkRequest "DELETE" ["/web-push/subscriptions/",toPath subscriptionId]
+    `_hasAuthType` (P.Proxy :: P.Proxy AuthBasicUserOrAgent)
+
+data RemoveWebPushSubscription  
+-- | @application/json@
+instance Produces RemoveWebPushSubscription MimeJSON
+
diff --git a/lib/AgentPushKit/API/Events.hs b/lib/AgentPushKit/API/Events.hs
new file mode 100644
--- /dev/null
+++ b/lib/AgentPushKit/API/Events.hs
@@ -0,0 +1,242 @@
+{-
+   Agent Push Kit API
+
+   The complete Agent Push Kit REST API. Application event ingestion uses an organization key beginning with `apk_`. Authenticated user operations accept either an Agent Push Kit login JWT or an agent access token beginning with `apt_`.
+
+   OpenAPI Version: 3.1.0
+   Agent Push Kit API API version: 0.1.0
+   Generated by OpenAPI Generator (https://openapi-generator.tech)
+-}
+
+{-|
+Module : AgentPushKit.API.Events
+-}
+
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MonoLocalBinds #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# OPTIONS_GHC -fno-warn-name-shadowing -fno-warn-unused-binds -fno-warn-unused-imports #-}
+
+module AgentPushKit.API.Events where
+
+import AgentPushKit.Core
+import AgentPushKit.MimeTypes
+import AgentPushKit.Model as M
+
+import qualified Data.Aeson as A
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Lazy as BL
+import qualified Data.Data as P (Typeable, TypeRep, typeOf, typeRep)
+import qualified Data.Foldable as P
+import qualified Data.Map as Map
+import qualified Data.Maybe as P
+import qualified Data.Proxy as P (Proxy(..))
+import qualified Data.Set as Set
+import qualified Data.String as P
+import qualified Data.Text as T
+import qualified Data.Text.Encoding as T
+import qualified Data.Text.Lazy as TL
+import qualified Data.Text.Lazy.Encoding as TL
+import qualified Data.Time as TI
+import qualified Network.HTTP.Client.MultipartFormData as NH
+import qualified Network.HTTP.Media as ME
+import qualified Network.HTTP.Types as NH
+import qualified Web.FormUrlEncoded as WH
+import qualified Web.HttpApiData as WH
+
+import Data.Text (Text)
+import GHC.Base ((<|>))
+
+import Prelude ((==),(/=),($), (.),(<$>),(<*>),(>>=),Maybe(..),Bool(..),Char,Double,FilePath,Float,Int,Integer,String,fmap,undefined,mempty,maybe,pure,Monad,Applicative,Functor)
+import qualified Prelude as P
+
+-- * Operations
+
+
+-- ** Events
+
+-- *** getEvent
+
+-- | @GET \/organizations\/{organizationId}\/events\/{eventId}@
+-- 
+-- Get one event including metadata
+-- 
+-- AuthMethod: 'AuthBasicUserOrAgent'
+-- 
+getEvent
+  :: OrganizationId -- ^ "organizationId"
+  -> EventId -- ^ "eventId"
+  -> AgentPushKitRequest GetEvent MimeNoContent EventDetail MimeJSON
+getEvent (OrganizationId organizationId) (EventId eventId) =
+  _mkRequest "GET" ["/organizations/",toPath organizationId,"/events/",toPath eventId]
+    `_hasAuthType` (P.Proxy :: P.Proxy AuthBasicUserOrAgent)
+
+data GetEvent  
+-- | @application/json@
+instance Produces GetEvent MimeJSON
+
+
+-- *** listEvents
+
+-- | @GET \/organizations\/{organizationId}\/events@
+-- 
+-- List a paginated inbox
+-- 
+-- AuthMethod: 'AuthBasicUserOrAgent'
+-- 
+listEvents
+  :: OrganizationId -- ^ "organizationId"
+  -> AgentPushKitRequest ListEvents MimeNoContent EventPage MimeJSON
+listEvents (OrganizationId organizationId) =
+  _mkRequest "GET" ["/organizations/",toPath organizationId,"/events"]
+    `_hasAuthType` (P.Proxy :: P.Proxy AuthBasicUserOrAgent)
+
+data ListEvents  
+instance HasOptionalParam ListEvents Service2 where
+  applyOptionalParam req (Service2 xs) =
+    req `addQuery` toQuery ("service", Just xs)
+instance HasOptionalParam ListEvents ParamType where
+  applyOptionalParam req (ParamType xs) =
+    req `addQuery` toQuery ("type", Just xs)
+instance HasOptionalParam ListEvents Search where
+  applyOptionalParam req (Search xs) =
+    req `addQuery` toQuery ("search", Just xs)
+instance HasOptionalParam ListEvents Cursor where
+  applyOptionalParam req (Cursor xs) =
+    req `addQuery` toQuery ("cursor", Just xs)
+instance HasOptionalParam ListEvents Limit where
+  applyOptionalParam req (Limit xs) =
+    req `addQuery` toQuery ("limit", Just xs)
+-- | @application/json@
+instance Produces ListEvents MimeJSON
+
+
+-- *** listNotificationTypes
+
+-- | @GET \/organizations\/{organizationId}\/types@
+-- 
+-- List distinct notification types
+-- 
+-- AuthMethod: 'AuthBasicUserOrAgent'
+-- 
+listNotificationTypes
+  :: OrganizationId -- ^ "organizationId"
+  -> AgentPushKitRequest ListNotificationTypes MimeNoContent [Text] MimeJSON
+listNotificationTypes (OrganizationId organizationId) =
+  _mkRequest "GET" ["/organizations/",toPath organizationId,"/types"]
+    `_hasAuthType` (P.Proxy :: P.Proxy AuthBasicUserOrAgent)
+
+data ListNotificationTypes  
+
+-- | /Optional Param/ "serviceId" - Optionally restrict types to one service ID.
+instance HasOptionalParam ListNotificationTypes ServiceId where
+  applyOptionalParam req (ServiceId xs) =
+    req `addQuery` toQuery ("serviceId", Just xs)
+-- | @application/json@
+instance Produces ListNotificationTypes MimeJSON
+
+
+-- *** listServices
+
+-- | @GET \/organizations\/{organizationId}\/services@
+-- 
+-- List services discovered from ingested events
+-- 
+-- AuthMethod: 'AuthBasicUserOrAgent'
+-- 
+listServices
+  :: OrganizationId -- ^ "organizationId"
+  -> AgentPushKitRequest ListServices MimeNoContent [Service] MimeJSON
+listServices (OrganizationId organizationId) =
+  _mkRequest "GET" ["/organizations/",toPath organizationId,"/services"]
+    `_hasAuthType` (P.Proxy :: P.Proxy AuthBasicUserOrAgent)
+
+data ListServices  
+-- | @application/json@
+instance Produces ListServices MimeJSON
+
+
+-- *** searchEvents
+
+-- | @POST \/organizations\/{organizationId}\/events\/search@
+-- 
+-- Search events with a validated Boolean filter tree
+-- 
+-- AuthMethod: 'AuthBasicUserOrAgent'
+-- 
+searchEvents
+  :: (Consumes SearchEvents MimeJSON, MimeRender MimeJSON SearchEventsInput)
+  => SearchEventsInput -- ^ "searchEventsInput"
+  -> OrganizationId -- ^ "organizationId"
+  -> AgentPushKitRequest SearchEvents MimeJSON EventPage MimeJSON
+searchEvents searchEventsInput (OrganizationId organizationId) =
+  _mkRequest "POST" ["/organizations/",toPath organizationId,"/events/search"]
+    `_hasAuthType` (P.Proxy :: P.Proxy AuthBasicUserOrAgent)
+    `setBodyParam` searchEventsInput
+
+data SearchEvents 
+instance HasBodyParam SearchEvents SearchEventsInput 
+
+-- | @application/json@
+instance Consumes SearchEvents MimeJSON
+
+-- | @application/json@
+instance Produces SearchEvents MimeJSON
+
+
+-- *** sendEvent
+
+-- | @POST \/events@
+-- 
+-- Send an event using an application ingestion key
+-- 
+-- AuthMethod: 'AuthBasicOrganizationApiKey'
+-- 
+sendEvent
+  :: (Consumes SendEvent MimeJSON, MimeRender MimeJSON SendEventInput)
+  => SendEventInput -- ^ "sendEventInput"
+  -> AgentPushKitRequest SendEvent MimeJSON IngestionResult MimeJSON
+sendEvent sendEventInput =
+  _mkRequest "POST" ["/events"]
+    `_hasAuthType` (P.Proxy :: P.Proxy AuthBasicOrganizationApiKey)
+    `setBodyParam` sendEventInput
+
+data SendEvent 
+instance HasBodyParam SendEvent SendEventInput 
+
+-- | @application/json@
+instance Consumes SendEvent MimeJSON
+
+-- | @application/json@
+instance Produces SendEvent MimeJSON
+
+
+-- *** sendEventAsUser
+
+-- | @POST \/organizations\/{organizationId}\/events@
+-- 
+-- Send an event as an authenticated user or agent
+-- 
+-- AuthMethod: 'AuthBasicUserOrAgent'
+-- 
+sendEventAsUser
+  :: (Consumes SendEventAsUser MimeJSON, MimeRender MimeJSON SendEventInput)
+  => SendEventInput -- ^ "sendEventInput"
+  -> OrganizationId -- ^ "organizationId"
+  -> AgentPushKitRequest SendEventAsUser MimeJSON IngestionResult MimeJSON
+sendEventAsUser sendEventInput (OrganizationId organizationId) =
+  _mkRequest "POST" ["/organizations/",toPath organizationId,"/events"]
+    `_hasAuthType` (P.Proxy :: P.Proxy AuthBasicUserOrAgent)
+    `setBodyParam` sendEventInput
+
+data SendEventAsUser 
+instance HasBodyParam SendEventAsUser SendEventInput 
+
+-- | @application/json@
+instance Consumes SendEventAsUser MimeJSON
+
+-- | @application/json@
+instance Produces SendEventAsUser MimeJSON
+
diff --git a/lib/AgentPushKit/API/Health.hs b/lib/AgentPushKit/API/Health.hs
new file mode 100644
--- /dev/null
+++ b/lib/AgentPushKit/API/Health.hs
@@ -0,0 +1,74 @@
+{-
+   Agent Push Kit API
+
+   The complete Agent Push Kit REST API. Application event ingestion uses an organization key beginning with `apk_`. Authenticated user operations accept either an Agent Push Kit login JWT or an agent access token beginning with `apt_`.
+
+   OpenAPI Version: 3.1.0
+   Agent Push Kit API API version: 0.1.0
+   Generated by OpenAPI Generator (https://openapi-generator.tech)
+-}
+
+{-|
+Module : AgentPushKit.API.Health
+-}
+
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MonoLocalBinds #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# OPTIONS_GHC -fno-warn-name-shadowing -fno-warn-unused-binds -fno-warn-unused-imports #-}
+
+module AgentPushKit.API.Health where
+
+import AgentPushKit.Core
+import AgentPushKit.MimeTypes
+import AgentPushKit.Model as M
+
+import qualified Data.Aeson as A
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Lazy as BL
+import qualified Data.Data as P (Typeable, TypeRep, typeOf, typeRep)
+import qualified Data.Foldable as P
+import qualified Data.Map as Map
+import qualified Data.Maybe as P
+import qualified Data.Proxy as P (Proxy(..))
+import qualified Data.Set as Set
+import qualified Data.String as P
+import qualified Data.Text as T
+import qualified Data.Text.Encoding as T
+import qualified Data.Text.Lazy as TL
+import qualified Data.Text.Lazy.Encoding as TL
+import qualified Data.Time as TI
+import qualified Network.HTTP.Client.MultipartFormData as NH
+import qualified Network.HTTP.Media as ME
+import qualified Network.HTTP.Types as NH
+import qualified Web.FormUrlEncoded as WH
+import qualified Web.HttpApiData as WH
+
+import Data.Text (Text)
+import GHC.Base ((<|>))
+
+import Prelude ((==),(/=),($), (.),(<$>),(<*>),(>>=),Maybe(..),Bool(..),Char,Double,FilePath,Float,Int,Integer,String,fmap,undefined,mempty,maybe,pure,Monad,Applicative,Functor)
+import qualified Prelude as P
+
+-- * Operations
+
+
+-- ** Health
+
+-- *** getHealth
+
+-- | @GET \/health@
+-- 
+-- Check Agent Push Kit API health
+-- 
+getHealth
+  :: AgentPushKitRequest GetHealth MimeNoContent HealthResponse MimeJSON
+getHealth =
+  _mkRequest "GET" ["/health"]
+
+data GetHealth  
+-- | @application/json@
+instance Produces GetHealth MimeJSON
+
diff --git a/lib/AgentPushKit/API/Preferences.hs b/lib/AgentPushKit/API/Preferences.hs
new file mode 100644
--- /dev/null
+++ b/lib/AgentPushKit/API/Preferences.hs
@@ -0,0 +1,156 @@
+{-
+   Agent Push Kit API
+
+   The complete Agent Push Kit REST API. Application event ingestion uses an organization key beginning with `apk_`. Authenticated user operations accept either an Agent Push Kit login JWT or an agent access token beginning with `apt_`.
+
+   OpenAPI Version: 3.1.0
+   Agent Push Kit API API version: 0.1.0
+   Generated by OpenAPI Generator (https://openapi-generator.tech)
+-}
+
+{-|
+Module : AgentPushKit.API.Preferences
+-}
+
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MonoLocalBinds #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# OPTIONS_GHC -fno-warn-name-shadowing -fno-warn-unused-binds -fno-warn-unused-imports #-}
+
+module AgentPushKit.API.Preferences where
+
+import AgentPushKit.Core
+import AgentPushKit.MimeTypes
+import AgentPushKit.Model as M
+
+import qualified Data.Aeson as A
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Lazy as BL
+import qualified Data.Data as P (Typeable, TypeRep, typeOf, typeRep)
+import qualified Data.Foldable as P
+import qualified Data.Map as Map
+import qualified Data.Maybe as P
+import qualified Data.Proxy as P (Proxy(..))
+import qualified Data.Set as Set
+import qualified Data.String as P
+import qualified Data.Text as T
+import qualified Data.Text.Encoding as T
+import qualified Data.Text.Lazy as TL
+import qualified Data.Text.Lazy.Encoding as TL
+import qualified Data.Time as TI
+import qualified Network.HTTP.Client.MultipartFormData as NH
+import qualified Network.HTTP.Media as ME
+import qualified Network.HTTP.Types as NH
+import qualified Web.FormUrlEncoded as WH
+import qualified Web.HttpApiData as WH
+
+import Data.Text (Text)
+import GHC.Base ((<|>))
+
+import Prelude ((==),(/=),($), (.),(<$>),(<*>),(>>=),Maybe(..),Bool(..),Char,Double,FilePath,Float,Int,Integer,String,fmap,undefined,mempty,maybe,pure,Monad,Applicative,Functor)
+import qualified Prelude as P
+
+-- * Operations
+
+
+-- ** Preferences
+
+-- *** listPreferences
+
+-- | @GET \/organizations\/{organizationId}\/preferences@
+-- 
+-- List service defaults and exact-type overrides
+-- 
+-- AuthMethod: 'AuthBasicUserOrAgent'
+-- 
+listPreferences
+  :: OrganizationId -- ^ "organizationId"
+  -> AgentPushKitRequest ListPreferences MimeNoContent [ServicePreference] MimeJSON
+listPreferences (OrganizationId organizationId) =
+  _mkRequest "GET" ["/organizations/",toPath organizationId,"/preferences"]
+    `_hasAuthType` (P.Proxy :: P.Proxy AuthBasicUserOrAgent)
+
+data ListPreferences  
+-- | @application/json@
+instance Produces ListPreferences MimeJSON
+
+
+-- *** removeTypePreference
+
+-- | @DELETE \/services\/{serviceId}\/types\/{type}\/preference@
+-- 
+-- Remove an exact-type override so it inherits the service default
+-- 
+-- AuthMethod: 'AuthBasicUserOrAgent'
+-- 
+removeTypePreference
+  :: ServiceId -- ^ "serviceId"
+  -> ParamType -- ^ "_type"
+  -> AgentPushKitRequest RemoveTypePreference MimeNoContent InheritedResponse MimeJSON
+removeTypePreference (ServiceId serviceId) (ParamType _type) =
+  _mkRequest "DELETE" ["/services/",toPath serviceId,"/types/",toPath _type,"/preference"]
+    `_hasAuthType` (P.Proxy :: P.Proxy AuthBasicUserOrAgent)
+
+data RemoveTypePreference  
+-- | @application/json@
+instance Produces RemoveTypePreference MimeJSON
+
+
+-- *** setServicePreference
+
+-- | @PUT \/services\/{serviceId}\/preference@
+-- 
+-- Enable or disable pushes for a service by default
+-- 
+-- AuthMethod: 'AuthBasicUserOrAgent'
+-- 
+setServicePreference
+  :: (Consumes SetServicePreference MimeJSON, MimeRender MimeJSON SetEnabledInput)
+  => SetEnabledInput -- ^ "setEnabledInput"
+  -> ServiceId -- ^ "serviceId"
+  -> AgentPushKitRequest SetServicePreference MimeJSON PreferenceRecord MimeJSON
+setServicePreference setEnabledInput (ServiceId serviceId) =
+  _mkRequest "PUT" ["/services/",toPath serviceId,"/preference"]
+    `_hasAuthType` (P.Proxy :: P.Proxy AuthBasicUserOrAgent)
+    `setBodyParam` setEnabledInput
+
+data SetServicePreference 
+instance HasBodyParam SetServicePreference SetEnabledInput 
+
+-- | @application/json@
+instance Consumes SetServicePreference MimeJSON
+
+-- | @application/json@
+instance Produces SetServicePreference MimeJSON
+
+
+-- *** setTypePreference
+
+-- | @PUT \/services\/{serviceId}\/types\/{type}\/preference@
+-- 
+-- Override push delivery for one exact notification type
+-- 
+-- AuthMethod: 'AuthBasicUserOrAgent'
+-- 
+setTypePreference
+  :: (Consumes SetTypePreference MimeJSON, MimeRender MimeJSON SetEnabledInput)
+  => SetEnabledInput -- ^ "setEnabledInput"
+  -> ServiceId -- ^ "serviceId"
+  -> ParamType -- ^ "_type"
+  -> AgentPushKitRequest SetTypePreference MimeJSON PreferenceRecord MimeJSON
+setTypePreference setEnabledInput (ServiceId serviceId) (ParamType _type) =
+  _mkRequest "PUT" ["/services/",toPath serviceId,"/types/",toPath _type,"/preference"]
+    `_hasAuthType` (P.Proxy :: P.Proxy AuthBasicUserOrAgent)
+    `setBodyParam` setEnabledInput
+
+data SetTypePreference 
+instance HasBodyParam SetTypePreference SetEnabledInput 
+
+-- | @application/json@
+instance Consumes SetTypePreference MimeJSON
+
+-- | @application/json@
+instance Produces SetTypePreference MimeJSON
+
diff --git a/lib/AgentPushKit/Client.hs b/lib/AgentPushKit/Client.hs
new file mode 100644
--- /dev/null
+++ b/lib/AgentPushKit/Client.hs
@@ -0,0 +1,224 @@
+{-
+   Agent Push Kit API
+
+   The complete Agent Push Kit REST API. Application event ingestion uses an organization key beginning with `apk_`. Authenticated user operations accept either an Agent Push Kit login JWT or an agent access token beginning with `apt_`.
+
+   OpenAPI Version: 3.1.0
+   Agent Push Kit API API version: 0.1.0
+   Generated by OpenAPI Generator (https://openapi-generator.tech)
+-}
+
+{-|
+Module : AgentPushKit.Client
+-}
+
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE DeriveFunctor #-}
+{-# LANGUAGE DeriveFoldable #-}
+{-# LANGUAGE DeriveTraversable #-}
+{-# OPTIONS_GHC -fno-warn-unused-binds -fno-warn-unused-imports #-}
+
+module AgentPushKit.Client where
+
+import AgentPushKit.Core
+import AgentPushKit.Logging
+import AgentPushKit.MimeTypes
+
+import qualified Control.Exception.Safe as E
+import qualified Control.Monad.IO.Class as P
+import qualified Control.Monad as P
+import qualified Data.Aeson.Types as A
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Char8 as BC
+import qualified Data.ByteString.Lazy as BL
+import qualified Data.ByteString.Lazy.Char8 as BCL
+import qualified Data.Proxy as P (Proxy(..))
+import qualified Data.Text as T
+import qualified Data.Text.Encoding as T
+import qualified Data.Maybe as M
+import qualified Network.HTTP.Client as NH
+import qualified Network.HTTP.Client.MultipartFormData as NH
+import qualified Network.HTTP.Types as NH
+import qualified Web.FormUrlEncoded as WH
+import qualified Web.HttpApiData as WH
+
+import Data.Function ((&))
+import Data.Monoid ((<>))
+import Data.Text (Text)
+import GHC.Exts (IsString(..))
+
+-- * Dispatch
+
+-- ** Lbs
+
+-- | send a request returning the raw http response
+dispatchLbs
+  :: (Produces req accept, MimeType contentType)
+  => NH.Manager -- ^ http-client Connection manager
+  -> AgentPushKitConfig -- ^ config
+  -> AgentPushKitRequest req contentType res accept -- ^ request
+  -> IO (NH.Response BCL.ByteString) -- ^ response
+dispatchLbs manager config request  = do
+  initReq <- _toInitRequest config request
+  dispatchInitUnsafe manager config initReq
+
+-- ** Mime
+
+-- | pair of decoded http body and http response
+data MimeResult res =
+  MimeResult { mimeResult :: Either MimeError res -- ^ decoded http body
+             , mimeResultResponse :: NH.Response BCL.ByteString -- ^ http response
+             }
+  deriving (Show, Functor, Foldable, Traversable)
+
+-- | pair of unrender/parser error and http response
+data MimeError =
+  MimeError {
+    mimeError :: String -- ^ unrender/parser error
+  , mimeErrorResponse :: NH.Response BCL.ByteString -- ^ http response
+  } deriving (Show)
+
+-- | send a request returning the 'MimeResult'
+dispatchMime
+  :: forall req contentType res accept. (Produces req accept, MimeUnrender accept res, MimeType contentType)
+  => NH.Manager -- ^ http-client Connection manager
+  -> AgentPushKitConfig -- ^ config
+  -> AgentPushKitRequest req contentType res accept -- ^ request
+  -> IO (MimeResult res) -- ^ response
+dispatchMime manager config request = do
+  httpResponse <- dispatchLbs manager config request
+  let statusCode = NH.statusCode . NH.responseStatus $ httpResponse
+  parsedResult <-
+    runConfigLogWithExceptions "Client" config $
+    do if (statusCode >= 400 && statusCode < 600)
+         then do
+           let s = "error statusCode: " ++ show statusCode
+           _log "Client" levelError (T.pack s)
+           pure (Left (MimeError s httpResponse))
+         else case mimeUnrender (P.Proxy :: P.Proxy accept) (NH.responseBody httpResponse) of
+           Left s -> do
+             _log "Client" levelError (T.pack s)
+             pure (Left (MimeError s httpResponse))
+           Right r -> pure (Right r)
+  return (MimeResult parsedResult httpResponse)
+
+-- | like 'dispatchMime', but only returns the decoded http body
+dispatchMime'
+  :: (Produces req accept, MimeUnrender accept res, MimeType contentType)
+  => NH.Manager -- ^ http-client Connection manager
+  -> AgentPushKitConfig -- ^ config
+  -> AgentPushKitRequest req contentType res accept -- ^ request
+  -> IO (Either MimeError res) -- ^ response
+dispatchMime' manager config request  = do
+    MimeResult parsedResult _ <- dispatchMime manager config request
+    return parsedResult
+
+-- ** Unsafe
+
+-- | like 'dispatchReqLbs', but does not validate the operation is a 'Producer' of the "accept" 'MimeType'.  (Useful if the server's response is undocumented)
+dispatchLbsUnsafe
+  :: (MimeType accept, MimeType contentType)
+  => NH.Manager -- ^ http-client Connection manager
+  -> AgentPushKitConfig -- ^ config
+  -> AgentPushKitRequest req contentType res accept -- ^ request
+  -> IO (NH.Response BCL.ByteString) -- ^ response
+dispatchLbsUnsafe manager config request  = do
+  initReq <- _toInitRequest config request
+  dispatchInitUnsafe manager config initReq
+
+-- | dispatch an InitRequest
+dispatchInitUnsafe
+  :: NH.Manager -- ^ http-client Connection manager
+  -> AgentPushKitConfig -- ^ config
+  -> InitRequest req contentType res accept -- ^ init request
+  -> IO (NH.Response BCL.ByteString) -- ^ response
+dispatchInitUnsafe manager config (InitRequest req) = do
+  runConfigLogWithExceptions src config $
+    do _log src levelInfo requestLogMsg
+       _log src levelDebug requestDbgLogMsg
+       res <- P.liftIO $ NH.httpLbs req manager
+       _log src levelInfo (responseLogMsg res)
+       _log src levelDebug ((T.pack . show) res)
+       return res
+  where
+    src = "Client"
+    endpoint =
+      T.pack $
+      BC.unpack $
+      NH.method req <> " " <> NH.host req <> NH.path req <> NH.queryString req
+    requestLogMsg = "REQ:" <> endpoint
+    requestDbgLogMsg =
+      "Headers=" <> (T.pack . show) (NH.requestHeaders req) <> " Body=" <>
+      (case NH.requestBody req of
+         NH.RequestBodyLBS xs -> T.decodeUtf8 (BL.toStrict xs)
+         _ -> "<RequestBody>")
+    responseStatusCode = (T.pack . show) . NH.statusCode . NH.responseStatus
+    responseLogMsg res =
+      "RES:statusCode=" <> responseStatusCode res <> " (" <> endpoint <> ")"
+
+-- * InitRequest
+
+-- | wraps an http-client 'Request' with request/response type parameters
+newtype InitRequest req contentType res accept = InitRequest
+  { unInitRequest :: NH.Request
+  } deriving (Show)
+
+-- |  Build an http-client 'Request' record from the supplied config and request
+_toInitRequest
+  :: (MimeType accept, MimeType contentType)
+  => AgentPushKitConfig -- ^ config
+  -> AgentPushKitRequest req contentType res accept -- ^ request
+  -> IO (InitRequest req contentType res accept) -- ^ initialized request
+_toInitRequest config req0  =
+  runConfigLogWithExceptions "Client" config $ do
+    parsedReq <- P.liftIO $ NH.parseRequest $ BCL.unpack $ BCL.append (configHost config) (BCL.concat (rUrlPath req0))
+    req1 <- P.liftIO $ _applyAuthMethods req0 config
+    P.when
+        (configValidateAuthMethods config && (not . null . rAuthTypes) req1)
+        (E.throw $ AuthMethodException $ "AuthMethod not configured: " <> (maybe "" show .  M.listToMaybe . rAuthTypes) req1)
+    let req2 = req1 & _setContentTypeHeader & _setAcceptHeader
+        params = rParams req2
+        reqHeaders = ("User-Agent", WH.toHeader (configUserAgent config)) : paramsHeaders params
+        reqQuery = let query = paramsQuery params
+                       queryExtraUnreserved = configQueryExtraUnreserved config
+                   in if B.null queryExtraUnreserved
+                        then NH.renderQuery True query
+                        else NH.renderQueryPartialEscape True (toPartialEscapeQuery queryExtraUnreserved query)
+        pReq = parsedReq { NH.method = rMethod req2
+                        , NH.requestHeaders = reqHeaders
+                        , NH.queryString = reqQuery
+                        }
+    outReq <- case paramsBody params of
+        ParamBodyNone -> pure (pReq { NH.requestBody = mempty })
+        ParamBodyB bs -> pure (pReq { NH.requestBody = NH.RequestBodyBS bs })
+        ParamBodyBL bl -> pure (pReq { NH.requestBody = NH.RequestBodyLBS bl })
+        ParamBodyFormUrlEncoded form -> pure (pReq { NH.requestBody = NH.RequestBodyLBS (WH.urlEncodeForm form) })
+        ParamBodyMultipartFormData parts -> NH.formDataBody parts pReq
+
+    pure (InitRequest outReq)
+
+-- | modify the underlying Request
+modifyInitRequest :: InitRequest req contentType res accept -> (NH.Request -> NH.Request) -> InitRequest req contentType res accept
+modifyInitRequest (InitRequest req) f = InitRequest (f req)
+
+-- | modify the underlying Request (monadic)
+modifyInitRequestM :: Monad m => InitRequest req contentType res accept -> (NH.Request -> m NH.Request) -> m (InitRequest req contentType res accept)
+modifyInitRequestM (InitRequest req) f = fmap InitRequest (f req)
+
+-- ** Logging
+
+-- | Run a block using the configured logger instance
+runConfigLog
+  :: P.MonadIO m
+  => AgentPushKitConfig -> LogExec m a
+runConfigLog config = configLogExecWithContext config (configLogContext config)
+
+-- | Run a block using the configured logger instance (logs exceptions)
+runConfigLogWithExceptions
+  :: (E.MonadCatch m, P.MonadIO m)
+  => T.Text -> AgentPushKitConfig -> LogExec m a
+runConfigLogWithExceptions src config = runConfigLog config . logExceptions src
diff --git a/lib/AgentPushKit/Core.hs b/lib/AgentPushKit/Core.hs
new file mode 100644
--- /dev/null
+++ b/lib/AgentPushKit/Core.hs
@@ -0,0 +1,620 @@
+{-
+   Agent Push Kit API
+
+   The complete Agent Push Kit REST API. Application event ingestion uses an organization key beginning with `apk_`. Authenticated user operations accept either an Agent Push Kit login JWT or an agent access token beginning with `apt_`.
+
+   OpenAPI Version: 3.1.0
+   Agent Push Kit API API version: 0.1.0
+   Generated by OpenAPI Generator (https://openapi-generator.tech)
+-}
+
+{-|
+Module : AgentPushKit.Core
+-}
+
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE ExistentialQuantification #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE NamedFieldPuns #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE CPP #-}
+{-# OPTIONS_GHC -fno-warn-name-shadowing -fno-warn-unused-binds -fno-warn-unused-imports #-}
+
+module AgentPushKit.Core where
+
+import AgentPushKit.MimeTypes
+import AgentPushKit.Logging
+
+import qualified Control.Arrow as P (left)
+import qualified Control.DeepSeq as NF
+import qualified Control.Exception.Safe as E
+import qualified Data.Aeson as A
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Base64.Lazy as BL64
+import qualified Data.ByteString.Builder as BB
+import qualified Data.ByteString.Char8 as BC
+import qualified Data.ByteString.Lazy as BL
+import qualified Data.ByteString.Lazy.Char8 as BCL
+import qualified Data.CaseInsensitive as CI
+import qualified Data.Data as P (Data, Typeable, TypeRep, typeRep)
+import qualified Data.Foldable as P
+import qualified Data.Ix as P
+import qualified Data.Kind as K (Type)
+import qualified Data.Maybe as P
+import qualified Data.Proxy as P (Proxy(..))
+import qualified Data.Text as T
+import qualified Data.Text.Encoding as T
+import qualified Data.Text.Lazy.Encoding as TL
+import qualified Data.Time as TI
+import qualified Data.Time.ISO8601 as TI
+import qualified GHC.Base as P (Alternative)
+import qualified Lens.Micro as L
+import qualified Network.HTTP.Client.MultipartFormData as NH
+import qualified Network.HTTP.Types as NH
+import qualified Prelude as P
+import qualified Text.Printf as T
+import qualified Web.FormUrlEncoded as WH
+import qualified Web.HttpApiData as WH
+
+import Control.Applicative ((<|>))
+import Control.Applicative (Alternative)
+import Control.Monad.Fail (MonadFail)
+import Data.Function ((&))
+import Data.Foldable(foldlM)
+import Data.Monoid ((<>))
+import Data.Text (Text)
+import Data.Type.Equality (type (~))
+import Prelude (($), (.), (&&), (<$>), (<*>), Maybe(..), Bool(..), Char, String, fmap, mempty, pure, return, show, IO, Monad, Functor, maybe)
+
+-- * AgentPushKitConfig
+
+-- |
+data AgentPushKitConfig = AgentPushKitConfig
+  { configHost  :: BCL.ByteString -- ^ host supplied in the Request
+  , configUserAgent :: Text -- ^ user-agent supplied in the Request
+  , configLogExecWithContext :: LogExecWithContext -- ^ Run a block using a Logger instance
+  , configLogContext :: LogContext -- ^ Configures the logger
+  , configAuthMethods :: [AnyAuthMethod] -- ^ List of configured auth methods
+  , configValidateAuthMethods :: Bool -- ^ throw exceptions if auth methods are not configured
+  , configQueryExtraUnreserved :: B.ByteString -- ^ Configures additional querystring characters which must not be URI encoded, e.g. '+' or ':'
+  }
+
+-- | display the config
+instance P.Show AgentPushKitConfig where
+  show c =
+    T.printf
+      "{ configHost = %v, configUserAgent = %v, ..}"
+      (show (configHost c))
+      (show (configUserAgent c))
+
+-- | constructs a default AgentPushKitConfig
+--
+-- configHost:
+--
+-- @https://api.chatdna.co/agent-push-kit/v1@
+--
+-- configUserAgent:
+--
+-- @"agent-push-kit/0.1.0.0"@
+--
+newConfig :: IO AgentPushKitConfig
+newConfig = do
+    logCxt <- initLogContext
+    return $ AgentPushKitConfig
+        { configHost = "https://api.chatdna.co/agent-push-kit/v1"
+        , configUserAgent = "agent-push-kit/0.1.0.0"
+        , configLogExecWithContext = runDefaultLogExecWithContext
+        , configLogContext = logCxt
+        , configAuthMethods = []
+        , configValidateAuthMethods = True
+        , configQueryExtraUnreserved = ""
+        }
+
+-- | updates config use AuthMethod on matching requests
+addAuthMethod :: AuthMethod auth => AgentPushKitConfig -> auth -> AgentPushKitConfig
+addAuthMethod config@AgentPushKitConfig {configAuthMethods = as} a =
+  config { configAuthMethods = AnyAuthMethod a : as}
+
+-- | updates the config to use stdout logging
+withStdoutLogging :: AgentPushKitConfig -> IO AgentPushKitConfig
+withStdoutLogging p = do
+    logCxt <- stdoutLoggingContext (configLogContext p)
+    return $ p { configLogExecWithContext = stdoutLoggingExec, configLogContext = logCxt }
+
+-- | updates the config to use stderr logging
+withStderrLogging :: AgentPushKitConfig -> IO AgentPushKitConfig
+withStderrLogging p = do
+    logCxt <- stderrLoggingContext (configLogContext p)
+    return $ p { configLogExecWithContext = stderrLoggingExec, configLogContext = logCxt }
+
+-- | updates the config to disable logging
+withNoLogging :: AgentPushKitConfig -> AgentPushKitConfig
+withNoLogging p = p { configLogExecWithContext =  runNullLogExec}
+
+-- * AgentPushKitRequest
+
+-- | Represents a request.
+--
+--   Type Variables:
+--
+--   * req - request operation
+--   * contentType - 'MimeType' associated with request body
+--   * res - response model
+--   * accept - 'MimeType' associated with response body
+data AgentPushKitRequest req contentType res accept = AgentPushKitRequest
+  { rMethod  :: NH.Method   -- ^ Method of AgentPushKitRequest
+  , rUrlPath :: [BCL.ByteString] -- ^ Endpoint of AgentPushKitRequest
+  , rParams   :: Params -- ^ params of AgentPushKitRequest
+  , rAuthTypes :: [P.TypeRep] -- ^ types of auth methods
+  }
+  deriving (P.Show)
+
+-- | 'rMethod' Lens
+rMethodL :: Lens_' (AgentPushKitRequest req contentType res accept) NH.Method
+rMethodL f AgentPushKitRequest{..} = (\rMethod -> AgentPushKitRequest { rMethod, ..} ) <$> f rMethod
+{-# INLINE rMethodL #-}
+
+-- | 'rUrlPath' Lens
+rUrlPathL :: Lens_' (AgentPushKitRequest req contentType res accept) [BCL.ByteString]
+rUrlPathL f AgentPushKitRequest{..} = (\rUrlPath -> AgentPushKitRequest { rUrlPath, ..} ) <$> f rUrlPath
+{-# INLINE rUrlPathL #-}
+
+-- | 'rParams' Lens
+rParamsL :: Lens_' (AgentPushKitRequest req contentType res accept) Params
+rParamsL f AgentPushKitRequest{..} = (\rParams -> AgentPushKitRequest { rParams, ..} ) <$> f rParams
+{-# INLINE rParamsL #-}
+
+-- | 'rParams' Lens
+rAuthTypesL :: Lens_' (AgentPushKitRequest req contentType res accept) [P.TypeRep]
+rAuthTypesL f AgentPushKitRequest{..} = (\rAuthTypes -> AgentPushKitRequest { rAuthTypes, ..} ) <$> f rAuthTypes
+{-# INLINE rAuthTypesL #-}
+
+-- * HasBodyParam
+
+-- | Designates the body parameter of a request
+class HasBodyParam req param where
+  setBodyParam :: forall contentType res accept. (Consumes req contentType, MimeRender contentType param) => AgentPushKitRequest req contentType res accept -> param -> AgentPushKitRequest req contentType res accept
+  setBodyParam req xs =
+    req `_setBodyLBS` mimeRender (P.Proxy :: P.Proxy contentType) xs & _setContentTypeHeader
+
+-- * HasOptionalParam
+
+-- | Designates the optional parameters of a request
+class HasOptionalParam req param where
+  {-# MINIMAL applyOptionalParam | (-&-) #-}
+
+  -- | Apply an optional parameter to a request
+  applyOptionalParam :: AgentPushKitRequest req contentType res accept -> param -> AgentPushKitRequest req contentType res accept
+  applyOptionalParam = (-&-)
+  {-# INLINE applyOptionalParam #-}
+
+  -- | infix operator \/ alias for 'addOptionalParam'
+  (-&-) :: AgentPushKitRequest req contentType res accept -> param -> AgentPushKitRequest req contentType res accept
+  (-&-) = applyOptionalParam
+  {-# INLINE (-&-) #-}
+
+infixl 2 -&-
+
+-- | Request Params
+data Params = Params
+  { paramsQuery :: NH.Query
+  , paramsHeaders :: NH.RequestHeaders
+  , paramsBody :: ParamBody
+  }
+  deriving (P.Show)
+
+-- | 'paramsQuery' Lens
+paramsQueryL :: Lens_' Params NH.Query
+paramsQueryL f Params{..} = (\paramsQuery -> Params { paramsQuery, ..} ) <$> f paramsQuery
+{-# INLINE paramsQueryL #-}
+
+-- | 'paramsHeaders' Lens
+paramsHeadersL :: Lens_' Params NH.RequestHeaders
+paramsHeadersL f Params{..} = (\paramsHeaders -> Params { paramsHeaders, ..} ) <$> f paramsHeaders
+{-# INLINE paramsHeadersL #-}
+
+-- | 'paramsBody' Lens
+paramsBodyL :: Lens_' Params ParamBody
+paramsBodyL f Params{..} = (\paramsBody -> Params { paramsBody, ..} ) <$> f paramsBody
+{-# INLINE paramsBodyL #-}
+
+-- | Request Body
+data ParamBody
+  = ParamBodyNone
+  | ParamBodyB B.ByteString
+  | ParamBodyBL BL.ByteString
+  | ParamBodyFormUrlEncoded WH.Form
+  | ParamBodyMultipartFormData [NH.Part]
+  deriving (P.Show)
+
+-- ** AgentPushKitRequest Utils
+
+_mkRequest :: NH.Method -- ^ Method
+          -> [BCL.ByteString] -- ^ Endpoint
+          -> AgentPushKitRequest req contentType res accept -- ^ req: Request Type, res: Response Type
+_mkRequest m u = AgentPushKitRequest m u _mkParams []
+
+_mkParams :: Params
+_mkParams = Params [] [] ParamBodyNone
+
+setHeader ::
+     AgentPushKitRequest req contentType res accept
+  -> [NH.Header]
+  -> AgentPushKitRequest req contentType res accept
+setHeader req header =
+  req `removeHeader` P.fmap P.fst header
+  & (`addHeader` header)
+
+addHeader ::
+     AgentPushKitRequest req contentType res accept
+  -> [NH.Header]
+  -> AgentPushKitRequest req contentType res accept
+addHeader req header = L.over (rParamsL . paramsHeadersL) (header P.++) req
+
+removeHeader :: AgentPushKitRequest req contentType res accept -> [NH.HeaderName] -> AgentPushKitRequest req contentType res accept
+removeHeader req header =
+  req &
+  L.over
+    (rParamsL . paramsHeadersL)
+    (P.filter (\h -> cifst h `P.notElem` P.fmap CI.mk header))
+  where
+    cifst = CI.mk . P.fst
+
+
+_setContentTypeHeader :: forall req contentType res accept. MimeType contentType => AgentPushKitRequest req contentType res accept -> AgentPushKitRequest req contentType res accept
+_setContentTypeHeader req =
+    case mimeType (P.Proxy :: P.Proxy contentType) of
+        Just m -> req `setHeader` [("content-type", BC.pack $ P.show m)]
+        Nothing -> req `removeHeader` ["content-type"]
+
+_setAcceptHeader :: forall req contentType res accept. MimeType accept => AgentPushKitRequest req contentType res accept -> AgentPushKitRequest req contentType res accept
+_setAcceptHeader req =
+    case mimeType (P.Proxy :: P.Proxy accept) of
+        Just m -> req `setHeader` [("accept", BC.pack $ P.show m)]
+        Nothing -> req `removeHeader` ["accept"]
+
+setQuery ::
+     AgentPushKitRequest req contentType res accept
+  -> [NH.QueryItem]
+  -> AgentPushKitRequest req contentType res accept
+setQuery req query =
+  req &
+  L.over
+    (rParamsL . paramsQueryL)
+    (P.filter (\q -> cifst q `P.notElem` P.fmap cifst query)) &
+  (`addQuery` query)
+  where
+    cifst = CI.mk . P.fst
+
+addQuery ::
+     AgentPushKitRequest req contentType res accept
+  -> [NH.QueryItem]
+  -> AgentPushKitRequest req contentType res accept
+addQuery req query = req & L.over (rParamsL . paramsQueryL) (query P.++)
+
+addForm :: AgentPushKitRequest req contentType res accept -> WH.Form -> AgentPushKitRequest req contentType res accept
+addForm req newform =
+    let form = case paramsBody (rParams req) of
+            ParamBodyFormUrlEncoded _form -> _form
+            _ -> mempty
+    in req & L.set (rParamsL . paramsBodyL) (ParamBodyFormUrlEncoded (newform <> form))
+
+_addMultiFormPart :: AgentPushKitRequest req contentType res accept -> NH.Part -> AgentPushKitRequest req contentType res accept
+_addMultiFormPart req newpart =
+    let parts = case paramsBody (rParams req) of
+            ParamBodyMultipartFormData _parts -> _parts
+            _ -> []
+    in req & L.set (rParamsL . paramsBodyL) (ParamBodyMultipartFormData (newpart : parts))
+
+_setBodyBS :: AgentPushKitRequest req contentType res accept -> B.ByteString -> AgentPushKitRequest req contentType res accept
+_setBodyBS req body =
+    req & L.set (rParamsL . paramsBodyL) (ParamBodyB body)
+
+_setBodyLBS :: AgentPushKitRequest req contentType res accept -> BL.ByteString -> AgentPushKitRequest req contentType res accept
+_setBodyLBS req body =
+    req & L.set (rParamsL . paramsBodyL) (ParamBodyBL body)
+
+_hasAuthType :: AuthMethod authMethod => AgentPushKitRequest req contentType res accept -> P.Proxy authMethod -> AgentPushKitRequest req contentType res accept
+_hasAuthType req proxy =
+  req & L.over rAuthTypesL (P.typeRep proxy :)
+
+-- ** Params Utils
+
+toPath
+  :: WH.ToHttpApiData a
+  => a -> BCL.ByteString
+toPath = BB.toLazyByteString . WH.toEncodedUrlPiece
+
+toHeader :: WH.ToHttpApiData a => (NH.HeaderName, a) -> [NH.Header]
+toHeader x = [fmap WH.toHeader x]
+
+toForm :: WH.ToHttpApiData v => (BC.ByteString, v) -> WH.Form
+toForm (k,v) = WH.toForm [(BC.unpack k,v)]
+
+toQuery :: WH.ToHttpApiData a => (BC.ByteString, Maybe a) -> [NH.QueryItem]
+toQuery x = [(fmap . fmap) toQueryParam x]
+  where toQueryParam = T.encodeUtf8 . WH.toQueryParam
+
+toJsonQuery :: A.ToJSON a => (BC.ByteString, Maybe a) -> [NH.QueryItem]
+toJsonQuery = toQuery . (fmap . fmap) (TL.decodeUtf8 . A.encode)
+
+toPartialEscapeQuery :: B.ByteString -> NH.Query -> NH.PartialEscapeQuery
+toPartialEscapeQuery extraUnreserved query = fmap (\(k, v) -> (k, maybe [] go v)) query
+  where go :: B.ByteString -> [NH.EscapeItem]
+        go v = v & B.groupBy (\a b -> a `B.notElem` extraUnreserved && b `B.notElem` extraUnreserved)
+                 & fmap (\xs -> if B.null xs then NH.QN xs
+                                  else if B.head xs `B.elem` extraUnreserved
+                                          then NH.QN xs -- Not Encoded
+                                          else NH.QE xs -- Encoded
+                        )
+
+-- *** OpenAPI `CollectionFormat` Utils
+
+-- | Determines the format of the array if type array is used.
+data CollectionFormat
+  = CommaSeparated -- ^ CSV format for multiple parameters.
+  | SpaceSeparated -- ^ Also called "SSV"
+  | TabSeparated -- ^ Also called "TSV"
+  | PipeSeparated -- ^ `value1|value2|value2`
+  | MultiParamArray -- ^ Using multiple GET parameters, e.g. `foo=bar&foo=baz`. This is valid only for parameters in "query" ('NH.Query') or "formData" ('WH.Form')
+
+toHeaderColl :: WH.ToHttpApiData a => CollectionFormat -> (NH.HeaderName, [a]) -> [NH.Header]
+toHeaderColl c xs = _toColl c toHeader xs
+
+toFormColl :: WH.ToHttpApiData v => CollectionFormat -> (BC.ByteString, [v]) -> WH.Form
+toFormColl c xs = WH.toForm $ fmap unpack $ _toColl c toHeader $ pack xs
+  where
+    pack (k,v) = (CI.mk k, v)
+    unpack (k,v) = (BC.unpack (CI.original k), BC.unpack v)
+
+toQueryColl :: WH.ToHttpApiData a => CollectionFormat -> (BC.ByteString, Maybe [a]) -> NH.Query
+toQueryColl c xs = _toCollA c toQuery xs
+
+toJsonQueryColl :: A.ToJSON a => CollectionFormat -> (BC.ByteString, Maybe [a]) -> NH.Query
+toJsonQueryColl c xs = _toCollA c toJsonQuery xs
+
+_toColl :: P.Traversable f => CollectionFormat -> (f a -> [(b, BC.ByteString)]) -> f [a] -> [(b, BC.ByteString)]
+_toColl c encode xs = fmap (fmap P.fromJust) (_toCollA' c fencode BC.singleton (fmap Just xs))
+  where fencode = fmap (fmap Just) . encode . fmap P.fromJust
+        {-# INLINE fencode #-}
+
+_toCollA :: (P.Traversable f, P.Traversable t, P.Alternative t) => CollectionFormat -> (f (t a) -> [(b, t BC.ByteString)]) -> f (t [a]) -> [(b, t BC.ByteString)]
+_toCollA c encode xs = _toCollA' c encode BC.singleton xs
+
+_toCollA' :: (P.Monoid c, P.Traversable f, P.Traversable t, P.Alternative t) => CollectionFormat -> (f (t a) -> [(b, t c)]) -> (Char -> c) -> f (t [a]) -> [(b, t c)]
+_toCollA' c encode one xs = case c of
+  CommaSeparated -> go (one ',')
+  SpaceSeparated -> go (one ' ')
+  TabSeparated -> go (one '\t')
+  PipeSeparated -> go (one '|')
+  MultiParamArray -> expandList
+  where
+    go sep =
+      [P.foldl1 (\(sk, sv) (_, v) -> (sk, (combine sep <$> sv <*> v) <|> sv <|> v)) expandList]
+    combine sep x y = x <> sep <> y
+    expandList = (P.concatMap encode . (P.traverse . P.traverse) P.toList) xs
+    {-# INLINE go #-}
+    {-# INLINE expandList #-}
+    {-# INLINE combine #-}
+
+-- * AuthMethods
+
+-- | Provides a method to apply auth methods to requests
+class P.Typeable a =>
+      AuthMethod a  where
+  applyAuthMethod
+    :: AgentPushKitConfig
+    -> a
+    -> AgentPushKitRequest req contentType res accept
+    -> IO (AgentPushKitRequest req contentType res accept)
+
+-- OpenAPI Generator 7.24 references bearer schemes as AuthBasic* types
+-- but does not emit their definitions. These wrappers all apply the same
+-- RFC 6750 Authorization header while preserving the generated type-level
+-- distinction between user/agent, agent-only, and ingestion-key endpoints.
+newtype AuthBasicUserOrAgent = AuthBasicUserOrAgent Text deriving (P.Typeable)
+newtype AuthBasicAgentToken = AuthBasicAgentToken Text deriving (P.Typeable)
+newtype AuthBasicOrganizationApiKey = AuthBasicOrganizationApiKey Text deriving (P.Typeable)
+
+applyBearerToken
+  :: P.TypeRep
+  -> Text
+  -> AgentPushKitRequest req contentType res accept
+  -> IO (AgentPushKitRequest req contentType res accept)
+applyBearerToken authType token req =
+  return $
+    (req `setHeader` [("Authorization", "Bearer " <> T.encodeUtf8 token)])
+      & L.over rAuthTypesL (P.filter (P./= authType))
+
+instance AuthMethod AuthBasicUserOrAgent where
+  applyAuthMethod _ (AuthBasicUserOrAgent token) =
+    applyBearerToken (P.typeRep (P.Proxy :: P.Proxy AuthBasicUserOrAgent)) token
+
+instance AuthMethod AuthBasicAgentToken where
+  applyAuthMethod _ (AuthBasicAgentToken token) =
+    applyBearerToken (P.typeRep (P.Proxy :: P.Proxy AuthBasicAgentToken)) token
+
+instance AuthMethod AuthBasicOrganizationApiKey where
+  applyAuthMethod _ (AuthBasicOrganizationApiKey token) =
+    applyBearerToken (P.typeRep (P.Proxy :: P.Proxy AuthBasicOrganizationApiKey)) token
+
+-- | An existential wrapper for any AuthMethod
+data AnyAuthMethod = forall a. AuthMethod a => AnyAuthMethod a deriving (P.Typeable)
+
+instance AuthMethod AnyAuthMethod where applyAuthMethod config (AnyAuthMethod a) req = applyAuthMethod config a req
+
+-- | indicates exceptions related to AuthMethods
+data AuthMethodException = AuthMethodException String deriving (P.Show, P.Typeable)
+
+instance E.Exception AuthMethodException
+
+-- | apply all matching AuthMethods in config to request
+_applyAuthMethods
+  :: AgentPushKitRequest req contentType res accept
+  -> AgentPushKitConfig
+  -> IO (AgentPushKitRequest req contentType res accept)
+_applyAuthMethods req config@(AgentPushKitConfig {configAuthMethods = as}) =
+  foldlM go req as
+  where
+    go r (AnyAuthMethod a) = applyAuthMethod config a r
+
+-- * Utils
+
+-- | Removes Null fields.  (OpenAPI-Specification 2.0 does not allow Null in JSON)
+#if MIN_VERSION_aeson(2,0,0)
+_omitNulls :: [(A.Key, A.Value)] -> A.Value
+#else
+_omitNulls :: [(Text, A.Value)] -> A.Value
+#endif
+_omitNulls = A.object . P.filter notNull
+  where
+    notNull (_, A.Null) = False
+    notNull _ = True
+
+-- | Encodes fields using WH.toQueryParam
+_toFormItem :: (WH.ToHttpApiData a, Functor f) => t -> f a -> f (t, [Text])
+_toFormItem name x = (name,) . (:[]) . WH.toQueryParam <$> x
+
+-- | Collapse (Just "") to Nothing
+_emptyToNothing :: Maybe String -> Maybe String
+_emptyToNothing (Just "") = Nothing
+_emptyToNothing x = x
+{-# INLINE _emptyToNothing #-}
+
+-- | Collapse (Just mempty) to Nothing
+_memptyToNothing :: (P.Monoid a, P.Eq a) => Maybe a -> Maybe a
+_memptyToNothing (Just x) | x P.== P.mempty = Nothing
+_memptyToNothing x = x
+{-# INLINE _memptyToNothing #-}
+
+-- * DateTime Formatting
+
+newtype DateTime = DateTime { unDateTime :: TI.UTCTime }
+  deriving (P.Eq,P.Data,P.Ord,P.Typeable,NF.NFData)
+instance A.FromJSON DateTime where
+  parseJSON = A.withText "DateTime" (_readDateTime . T.unpack)
+instance A.ToJSON DateTime where
+  toJSON (DateTime t) = A.toJSON (_showDateTime t)
+instance WH.FromHttpApiData DateTime where
+  parseUrlPiece = P.maybe (P.Left "parseUrlPiece @DateTime") P.Right . _readDateTime . T.unpack
+instance WH.ToHttpApiData DateTime where
+  toUrlPiece (DateTime t) = T.pack (_showDateTime t)
+instance P.Show DateTime where
+  show (DateTime t) = _showDateTime t
+instance MimeRender MimeMultipartFormData DateTime where
+  mimeRender _ = mimeRenderDefaultMultipartFormData
+
+-- | @_parseISO8601@
+_readDateTime :: (MonadFail m, Alternative m) => String -> m DateTime
+_readDateTime s =
+  DateTime <$> _parseISO8601 s
+{-# INLINE _readDateTime #-}
+
+-- | @TI.formatISO8601Millis@
+_showDateTime :: (t ~ TI.UTCTime, TI.FormatTime t) => t -> String
+_showDateTime =
+  TI.formatISO8601Millis
+{-# INLINE _showDateTime #-}
+
+-- | parse an ISO8601 date-time string
+_parseISO8601 :: (TI.ParseTime t, MonadFail m, Alternative m) => String -> m t
+_parseISO8601 t =
+  P.asum $
+  P.flip (TI.parseTimeM True TI.defaultTimeLocale) t <$>
+  ["%FT%T%QZ", "%FT%T%Q%z", "%FT%T%Q%Z"]
+{-# INLINE _parseISO8601 #-}
+
+-- * Date Formatting
+
+newtype Date = Date { unDate :: TI.Day }
+  deriving (P.Enum,P.Eq,P.Data,P.Ord,P.Ix,NF.NFData)
+instance A.FromJSON Date where
+  parseJSON = A.withText "Date" (_readDate . T.unpack)
+instance A.ToJSON Date where
+  toJSON (Date t) = A.toJSON (_showDate t)
+instance WH.FromHttpApiData Date where
+  parseUrlPiece = P.maybe (P.Left "parseUrlPiece @Date") P.Right . _readDate . T.unpack
+instance WH.ToHttpApiData Date where
+  toUrlPiece (Date t) = T.pack (_showDate t)
+instance P.Show Date where
+  show (Date t) = _showDate t
+instance MimeRender MimeMultipartFormData Date where
+  mimeRender _ = mimeRenderDefaultMultipartFormData
+
+-- | @TI.parseTimeM True TI.defaultTimeLocale "%Y-%m-%d"@
+_readDate :: MonadFail m => String -> m Date
+_readDate s = Date <$> TI.parseTimeM True TI.defaultTimeLocale "%Y-%m-%d" s
+{-# INLINE _readDate #-}
+
+-- | @TI.formatTime TI.defaultTimeLocale "%Y-%m-%d"@
+_showDate :: TI.FormatTime t => t -> String
+_showDate =
+  TI.formatTime TI.defaultTimeLocale "%Y-%m-%d"
+{-# INLINE _showDate #-}
+
+-- * Byte/Binary Formatting
+
+
+-- | base64 encoded characters
+newtype ByteArray = ByteArray { unByteArray :: BL.ByteString }
+  deriving (P.Eq,P.Data,P.Ord,P.Typeable,NF.NFData)
+
+instance A.FromJSON ByteArray where
+  parseJSON = A.withText "ByteArray" _readByteArray
+instance A.ToJSON ByteArray where
+  toJSON = A.toJSON . _showByteArray
+instance WH.FromHttpApiData ByteArray where
+  parseUrlPiece = P.maybe (P.Left "parseUrlPiece @ByteArray") P.Right . _readByteArray
+instance WH.ToHttpApiData ByteArray where
+  toUrlPiece = _showByteArray
+instance P.Show ByteArray where
+  show = T.unpack . _showByteArray
+instance MimeRender MimeMultipartFormData ByteArray where
+  mimeRender _ = mimeRenderDefaultMultipartFormData
+
+-- | read base64 encoded characters
+_readByteArray :: MonadFail m => Text -> m ByteArray
+_readByteArray = P.either P.fail (pure . ByteArray) . BL64.decode . BL.fromStrict . T.encodeUtf8
+{-# INLINE _readByteArray #-}
+
+-- | show base64 encoded characters
+_showByteArray :: ByteArray -> Text
+_showByteArray = T.decodeUtf8 . BL.toStrict . BL64.encode . unByteArray
+{-# INLINE _showByteArray #-}
+
+-- | any sequence of octets
+newtype Binary = Binary { unBinary :: BL.ByteString }
+  deriving (P.Eq,P.Data,P.Ord,P.Typeable,NF.NFData)
+
+instance A.FromJSON Binary where
+  parseJSON = A.withText "Binary" _readBinaryBase64
+instance A.ToJSON Binary where
+  toJSON = A.toJSON . _showBinaryBase64
+instance WH.FromHttpApiData Binary where
+  parseUrlPiece = P.maybe (P.Left "parseUrlPiece @Binary") P.Right . _readBinaryBase64
+instance WH.ToHttpApiData Binary where
+  toUrlPiece = _showBinaryBase64
+instance P.Show Binary where
+  show = T.unpack . _showBinaryBase64
+instance MimeRender MimeMultipartFormData Binary where
+  mimeRender _ = unBinary
+
+_readBinaryBase64 :: MonadFail m => Text -> m Binary
+_readBinaryBase64 = P.either P.fail (pure . Binary) . BL64.decode . BL.fromStrict . T.encodeUtf8
+{-# INLINE _readBinaryBase64 #-}
+
+_showBinaryBase64 :: Binary -> Text
+_showBinaryBase64 = T.decodeUtf8 . BL.toStrict . BL64.encode . unBinary
+{-# INLINE _showBinaryBase64 #-}
+
+-- * Lens Type Aliases
+
+type Lens_' s a = Lens_ s s a a
+type Lens_ s t a b = forall (f :: K.Type -> K.Type). Functor f => (a -> f b) -> s -> f t
diff --git a/lib/AgentPushKit/Logging.hs b/lib/AgentPushKit/Logging.hs
new file mode 100644
--- /dev/null
+++ b/lib/AgentPushKit/Logging.hs
@@ -0,0 +1,33 @@
+{-
+   Agent Push Kit API
+
+   The complete Agent Push Kit REST API. Application event ingestion uses an organization key beginning with `apk_`. Authenticated user operations accept either an Agent Push Kit login JWT or an agent access token beginning with `apt_`.
+
+   OpenAPI Version: 3.1.0
+   Agent Push Kit API API version: 0.1.0
+   Generated by OpenAPI Generator (https://openapi-generator.tech)
+-}
+
+{-|
+Module : AgentPushKit.Logging
+Logging functions
+-}
+{-# LANGUAGE CPP #-}
+
+#ifdef USE_KATIP
+
+module AgentPushKit.Logging
+  ( module AgentPushKit.LoggingKatip
+  ) where
+
+import AgentPushKit.LoggingKatip
+
+#else
+
+module AgentPushKit.Logging
+  ( module AgentPushKit.LoggingMonadLogger
+  ) where
+
+import AgentPushKit.LoggingMonadLogger
+
+#endif
diff --git a/lib/AgentPushKit/LoggingKatip.hs b/lib/AgentPushKit/LoggingKatip.hs
new file mode 100644
--- /dev/null
+++ b/lib/AgentPushKit/LoggingKatip.hs
@@ -0,0 +1,117 @@
+{-
+   Agent Push Kit API
+
+   The complete Agent Push Kit REST API. Application event ingestion uses an organization key beginning with `apk_`. Authenticated user operations accept either an Agent Push Kit login JWT or an agent access token beginning with `apt_`.
+
+   OpenAPI Version: 3.1.0
+   Agent Push Kit API API version: 0.1.0
+   Generated by OpenAPI Generator (https://openapi-generator.tech)
+-}
+
+{-|
+Module : AgentPushKit.LoggingKatip
+Katip Logging functions
+-}
+
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+module AgentPushKit.LoggingKatip where
+
+import qualified Control.Exception.Safe as E
+import qualified Control.Monad.IO.Class as P
+import qualified Control.Monad.Trans.Reader as P
+import qualified Data.Text as T
+import qualified Lens.Micro as L
+import qualified System.IO as IO
+
+import Data.Text (Text)
+import GHC.Exts (IsString(..))
+
+import qualified Katip as LG
+
+-- * Type Aliases (for compatibility)
+
+-- | Runs a Katip logging block with the Log environment
+type LogExecWithContext = forall m a. P.MonadIO m =>
+                                      LogContext -> LogExec m a
+
+-- | A Katip logging block
+type LogExec m a = LG.KatipT m a -> m a
+
+-- | A Katip Log environment
+type LogContext = LG.LogEnv
+
+-- | A Katip Log severity
+type LogLevel = LG.Severity
+
+-- * default logger
+
+-- | the default log environment
+initLogContext :: IO LogContext
+initLogContext = LG.initLogEnv "AgentPushKit" "dev"
+
+-- | Runs a Katip logging block with the Log environment
+runDefaultLogExecWithContext :: LogExecWithContext
+runDefaultLogExecWithContext = LG.runKatipT
+
+-- * stdout logger
+
+-- | Runs a Katip logging block with the Log environment
+stdoutLoggingExec :: LogExecWithContext
+stdoutLoggingExec = runDefaultLogExecWithContext
+
+-- | A Katip Log environment which targets stdout
+stdoutLoggingContext :: LogContext -> IO LogContext
+stdoutLoggingContext cxt = do
+    handleScribe <- LG.mkHandleScribe LG.ColorIfTerminal IO.stdout (LG.permitItem LG.InfoS) LG.V2
+    LG.registerScribe "stdout" handleScribe LG.defaultScribeSettings cxt
+
+-- * stderr logger
+
+-- | Runs a Katip logging block with the Log environment
+stderrLoggingExec :: LogExecWithContext
+stderrLoggingExec = runDefaultLogExecWithContext
+
+-- | A Katip Log environment which targets stderr
+stderrLoggingContext :: LogContext -> IO LogContext
+stderrLoggingContext cxt = do
+    handleScribe <- LG.mkHandleScribe LG.ColorIfTerminal IO.stderr (LG.permitItem LG.InfoS) LG.V2
+    LG.registerScribe "stderr" handleScribe LG.defaultScribeSettings cxt
+
+-- * Null logger
+
+-- | Disables Katip logging
+runNullLogExec :: LogExecWithContext
+runNullLogExec le (LG.KatipT f) = P.runReaderT f (L.set LG.logEnvScribes mempty le)
+
+-- * Log Msg
+
+-- | Log a katip message
+_log :: (Applicative m, LG.Katip m) => Text -> LogLevel -> Text -> m ()
+_log src level msg = do
+  LG.logMsg (fromString $ T.unpack src) level (LG.logStr msg)
+
+-- * Log Exceptions
+
+-- | re-throws exceptions after logging them
+logExceptions
+  :: (LG.Katip m, E.MonadCatch m, Applicative m)
+  => Text -> m a -> m a
+logExceptions src =
+  E.handle
+    (\(e :: E.SomeException) -> do
+       _log src LG.ErrorS ((T.pack . show) e)
+       E.throw e)
+
+-- * Log Level
+
+levelInfo :: LogLevel
+levelInfo = LG.InfoS
+
+levelError :: LogLevel
+levelError = LG.ErrorS
+
+levelDebug :: LogLevel
+levelDebug = LG.DebugS
diff --git a/lib/AgentPushKit/LoggingMonadLogger.hs b/lib/AgentPushKit/LoggingMonadLogger.hs
new file mode 100644
--- /dev/null
+++ b/lib/AgentPushKit/LoggingMonadLogger.hs
@@ -0,0 +1,126 @@
+{-
+   Agent Push Kit API
+
+   The complete Agent Push Kit REST API. Application event ingestion uses an organization key beginning with `apk_`. Authenticated user operations accept either an Agent Push Kit login JWT or an agent access token beginning with `apt_`.
+
+   OpenAPI Version: 3.1.0
+   Agent Push Kit API API version: 0.1.0
+   Generated by OpenAPI Generator (https://openapi-generator.tech)
+-}
+
+{-|
+Module : AgentPushKit.LoggingMonadLogger
+monad-logger Logging functions
+-}
+
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+module AgentPushKit.LoggingMonadLogger where
+
+import qualified Control.Exception.Safe as E
+import qualified Control.Monad.IO.Class as P
+import qualified Data.Text as T
+import qualified Data.Time as TI
+
+import Data.Text (Text)
+
+import qualified Control.Monad.Logger as LG
+
+-- * Type Aliases (for compatibility)
+
+-- | Runs a monad-logger  block with the filter predicate
+type LogExecWithContext = forall m a. P.MonadIO m =>
+                                      LogContext -> LogExec m a
+
+-- | A monad-logger block
+type LogExec m a = LG.LoggingT m a -> m a
+
+-- | A monad-logger filter predicate
+type LogContext = LG.LogSource -> LG.LogLevel -> Bool
+
+-- | A monad-logger log level
+type LogLevel = LG.LogLevel
+
+-- * default logger
+
+-- | the default log environment
+initLogContext :: IO LogContext
+initLogContext = pure infoLevelFilter
+
+-- | Runs a monad-logger block with the filter predicate
+runDefaultLogExecWithContext :: LogExecWithContext
+runDefaultLogExecWithContext = runNullLogExec
+
+-- * stdout logger
+
+-- | Runs a monad-logger block targeting stdout, with the filter predicate
+stdoutLoggingExec :: LogExecWithContext
+stdoutLoggingExec cxt = LG.runStdoutLoggingT . LG.filterLogger cxt
+
+-- | @pure@
+stdoutLoggingContext :: LogContext -> IO LogContext
+stdoutLoggingContext = pure
+
+-- * stderr logger
+
+-- | Runs a monad-logger block targeting stderr, with the filter predicate
+stderrLoggingExec :: LogExecWithContext
+stderrLoggingExec cxt = LG.runStderrLoggingT . LG.filterLogger cxt
+
+-- | @pure@
+stderrLoggingContext :: LogContext -> IO LogContext
+stderrLoggingContext = pure
+
+-- * Null logger
+
+-- | Disables monad-logger logging
+runNullLogExec :: LogExecWithContext
+runNullLogExec = const (`LG.runLoggingT` nullLogger)
+
+-- | monad-logger which does nothing
+nullLogger :: LG.Loc -> LG.LogSource -> LG.LogLevel -> LG.LogStr -> IO ()
+nullLogger _ _ _ _ = return ()
+
+-- * Log Msg
+
+-- | Log a message using the current time
+_log :: (P.MonadIO m, LG.MonadLogger m) => Text -> LG.LogLevel -> Text -> m ()
+_log src level msg = do
+  now <- P.liftIO (formatTimeLog <$> TI.getCurrentTime)
+  LG.logOtherNS ("AgentPushKit." <> src) level ("[" <> now <> "] " <> msg)
+ where
+  formatTimeLog =
+    T.pack . TI.formatTime TI.defaultTimeLocale "%Y-%m-%dT%H:%M:%S%Z"
+
+-- * Log Exceptions
+
+-- | re-throws exceptions after logging them
+logExceptions
+   :: (LG.MonadLogger m, E.MonadCatch m, P.MonadIO m)
+   => Text -> m a -> m a
+logExceptions src =
+   E.handle
+     (\(e :: E.SomeException) -> do
+        _log src LG.LevelError ((T.pack . show) e)
+        E.throw e)
+
+-- * Log Level
+
+levelInfo :: LogLevel
+levelInfo = LG.LevelInfo
+
+levelError :: LogLevel
+levelError = LG.LevelError
+
+levelDebug :: LogLevel
+levelDebug = LG.LevelDebug
+
+-- * Level Filter
+
+minLevelFilter :: LG.LogLevel -> LG.LogSource -> LG.LogLevel -> Bool
+minLevelFilter l _ l' = l' >= l
+
+infoLevelFilter :: LG.LogSource -> LG.LogLevel -> Bool
+infoLevelFilter = minLevelFilter LG.LevelInfo
diff --git a/lib/AgentPushKit/MimeTypes.hs b/lib/AgentPushKit/MimeTypes.hs
new file mode 100644
--- /dev/null
+++ b/lib/AgentPushKit/MimeTypes.hs
@@ -0,0 +1,203 @@
+{-
+   Agent Push Kit API
+
+   The complete Agent Push Kit REST API. Application event ingestion uses an organization key beginning with `apk_`. Authenticated user operations accept either an Agent Push Kit login JWT or an agent access token beginning with `apt_`.
+
+   OpenAPI Version: 3.1.0
+   Agent Push Kit API API version: 0.1.0
+   Generated by OpenAPI Generator (https://openapi-generator.tech)
+-}
+
+{-|
+Module : AgentPushKit.MimeTypes
+-}
+
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE ExistentialQuantification #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# OPTIONS_GHC -fno-warn-unused-binds -fno-warn-unused-imports #-}
+
+module AgentPushKit.MimeTypes where
+
+import qualified Control.Arrow as P (left)
+import qualified Data.Aeson as A
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Builder as BB
+import qualified Data.ByteString.Char8 as BC
+import qualified Data.ByteString.Lazy as BL
+import qualified Data.ByteString.Lazy.Char8 as BCL
+import qualified Data.Data as P (Typeable)
+import qualified Data.Proxy as P (Proxy(..))
+import qualified Data.String as P
+import qualified Data.Text as T
+import qualified Data.Text.Encoding as T
+import qualified Network.HTTP.Media as ME
+import qualified Web.FormUrlEncoded as WH
+import qualified Web.HttpApiData as WH
+
+import Prelude (($), (.),(<$>),(<*>),Maybe(..),Bool(..),Char,Double,FilePath,Float,Int,Integer,String,fmap,undefined,mempty)
+import qualified Prelude as P
+
+-- * ContentType MimeType
+
+data ContentType a = MimeType a => ContentType { unContentType :: a }
+
+-- * Accept MimeType
+
+data Accept a = MimeType a => Accept { unAccept :: a }
+
+-- * Consumes Class
+
+class MimeType mtype => Consumes req mtype where
+
+-- * Produces Class
+
+class MimeType mtype => Produces req mtype where
+
+-- * Default Mime Types
+
+data MimeJSON = MimeJSON deriving (P.Typeable)
+data MimeXML = MimeXML deriving (P.Typeable)
+data MimePlainText = MimePlainText deriving (P.Typeable)
+data MimeFormUrlEncoded = MimeFormUrlEncoded deriving (P.Typeable)
+data MimeMultipartFormData = MimeMultipartFormData deriving (P.Typeable)
+data MimeOctetStream = MimeOctetStream deriving (P.Typeable)
+data MimeNoContent = MimeNoContent deriving (P.Typeable)
+data MimeAny = MimeAny deriving (P.Typeable)
+
+-- | A type for responses without content-body.
+data NoContent = NoContent
+  deriving (P.Show, P.Eq, P.Typeable)
+
+
+-- * MimeType Class
+
+class P.Typeable mtype => MimeType mtype  where
+  {-# MINIMAL mimeType | mimeTypes #-}
+
+  mimeTypes :: P.Proxy mtype -> [ME.MediaType]
+  mimeTypes p =
+    case mimeType p of
+      Just x -> [x]
+      Nothing -> []
+
+  mimeType :: P.Proxy mtype -> Maybe ME.MediaType
+  mimeType p =
+    case mimeTypes p of
+      [] -> Nothing
+      (x:_) -> Just x
+
+  mimeType' :: mtype -> Maybe ME.MediaType
+  mimeType' _ = mimeType (P.Proxy :: P.Proxy mtype)
+  mimeTypes' :: mtype -> [ME.MediaType]
+  mimeTypes' _ = mimeTypes (P.Proxy :: P.Proxy mtype)
+
+-- Default MimeType Instances
+
+-- | @application/json; charset=utf-8@
+instance MimeType MimeJSON where
+  mimeType _ = Just $ P.fromString "application/json"
+-- | @application/xml; charset=utf-8@
+instance MimeType MimeXML where
+  mimeType _ = Just $ P.fromString "application/xml"
+-- | @application/x-www-form-urlencoded@
+instance MimeType MimeFormUrlEncoded where
+  mimeType _ = Just $ P.fromString "application/x-www-form-urlencoded"
+-- | @multipart/form-data@
+instance MimeType MimeMultipartFormData where
+  mimeType _ = Just $ P.fromString "multipart/form-data"
+-- | @text/plain; charset=utf-8@
+instance MimeType MimePlainText where
+  mimeType _ = Just $ P.fromString "text/plain"
+-- | @application/octet-stream@
+instance MimeType MimeOctetStream where
+  mimeType _ = Just $ P.fromString "application/octet-stream"
+-- | @"*/*"@
+instance MimeType MimeAny where
+  mimeType _ = Just $ P.fromString "*/*"
+instance MimeType MimeNoContent where
+  mimeType _ = Nothing
+
+-- * MimeRender Class
+
+class MimeType mtype => MimeRender mtype x where
+    mimeRender  :: P.Proxy mtype -> x -> BL.ByteString
+    mimeRender' :: mtype -> x -> BL.ByteString
+    mimeRender' _ x = mimeRender (P.Proxy :: P.Proxy mtype) x
+
+
+mimeRenderDefaultMultipartFormData :: WH.ToHttpApiData a => a -> BL.ByteString
+mimeRenderDefaultMultipartFormData = BL.fromStrict . T.encodeUtf8 . WH.toQueryParam
+
+-- Default MimeRender Instances
+
+-- | `A.encode`
+instance A.ToJSON a => MimeRender MimeJSON a where mimeRender _ = A.encode
+-- | @WH.urlEncodeAsForm@
+instance WH.ToForm a => MimeRender MimeFormUrlEncoded a where mimeRender _ = WH.urlEncodeAsForm
+
+-- | @P.id@
+instance MimeRender MimePlainText BL.ByteString where mimeRender _ = P.id
+-- | @BL.fromStrict . T.encodeUtf8@
+instance MimeRender MimePlainText T.Text where mimeRender _ = BL.fromStrict . T.encodeUtf8
+-- | @BCL.pack@
+instance MimeRender MimePlainText String where mimeRender _ = BCL.pack
+
+-- | @P.id@
+instance MimeRender MimeOctetStream BL.ByteString where mimeRender _ = P.id
+-- | @BL.fromStrict . T.encodeUtf8@
+instance MimeRender MimeOctetStream T.Text where mimeRender _ = BL.fromStrict . T.encodeUtf8
+-- | @BCL.pack@
+instance MimeRender MimeOctetStream String where mimeRender _ = BCL.pack
+
+instance MimeRender MimeMultipartFormData BL.ByteString where mimeRender _ = P.id
+
+instance MimeRender MimeMultipartFormData Bool where mimeRender _ = mimeRenderDefaultMultipartFormData
+instance MimeRender MimeMultipartFormData Char where mimeRender _ = mimeRenderDefaultMultipartFormData
+instance MimeRender MimeMultipartFormData Double where mimeRender _ = mimeRenderDefaultMultipartFormData
+instance MimeRender MimeMultipartFormData Float where mimeRender _ = mimeRenderDefaultMultipartFormData
+instance MimeRender MimeMultipartFormData Int where mimeRender _ = mimeRenderDefaultMultipartFormData
+instance MimeRender MimeMultipartFormData Integer where mimeRender _ = mimeRenderDefaultMultipartFormData
+instance MimeRender MimeMultipartFormData String where mimeRender _ = mimeRenderDefaultMultipartFormData
+instance MimeRender MimeMultipartFormData T.Text where mimeRender _ = mimeRenderDefaultMultipartFormData
+
+-- | @P.Right . P.const NoContent@
+instance MimeRender MimeNoContent NoContent where mimeRender _ = P.const BCL.empty
+
+
+-- * MimeUnrender Class
+
+class MimeType mtype => MimeUnrender mtype o where
+    mimeUnrender :: P.Proxy mtype -> BL.ByteString -> P.Either String o
+    mimeUnrender' :: mtype -> BL.ByteString -> P.Either String o
+    mimeUnrender' _ x = mimeUnrender (P.Proxy :: P.Proxy mtype) x
+
+-- Default MimeUnrender Instances
+
+-- | @A.eitherDecode@
+instance A.FromJSON a => MimeUnrender MimeJSON a where mimeUnrender _ = A.eitherDecode
+-- | @P.left T.unpack . WH.urlDecodeAsForm@
+instance WH.FromForm a => MimeUnrender MimeFormUrlEncoded a where mimeUnrender _ = P.left T.unpack . WH.urlDecodeAsForm
+-- | @P.Right . P.id@
+
+instance MimeUnrender MimePlainText BL.ByteString where mimeUnrender _ = P.Right . P.id
+-- | @P.left P.show . TL.decodeUtf8'@
+instance MimeUnrender MimePlainText T.Text where mimeUnrender _ = P.left P.show . T.decodeUtf8' . BL.toStrict
+-- | @P.Right . BCL.unpack@
+instance MimeUnrender MimePlainText String where mimeUnrender _ = P.Right . BCL.unpack
+
+-- | @P.Right . P.id@
+instance MimeUnrender MimeOctetStream BL.ByteString where mimeUnrender _ = P.Right . P.id
+-- | @P.left P.show . T.decodeUtf8' . BL.toStrict@
+instance MimeUnrender MimeOctetStream T.Text where mimeUnrender _ = P.left P.show . T.decodeUtf8' . BL.toStrict
+-- | @P.Right . BCL.unpack@
+instance MimeUnrender MimeOctetStream String where mimeUnrender _ = P.Right . BCL.unpack
+
+-- | @P.Right . P.const NoContent@
+instance MimeUnrender MimeNoContent NoContent where mimeUnrender _ = P.Right . P.const NoContent
+
+
diff --git a/lib/AgentPushKit/Model.hs b/lib/AgentPushKit/Model.hs
new file mode 100644
--- /dev/null
+++ b/lib/AgentPushKit/Model.hs
@@ -0,0 +1,2516 @@
+{-
+   Agent Push Kit API
+
+   The complete Agent Push Kit REST API. Application event ingestion uses an organization key beginning with `apk_`. Authenticated user operations accept either an Agent Push Kit login JWT or an agent access token beginning with `apt_`.
+
+   OpenAPI Version: 3.1.0
+   Agent Push Kit API API version: 0.1.0
+   Generated by OpenAPI Generator (https://openapi-generator.tech)
+-}
+
+{-|
+Module : AgentPushKit.Model
+-}
+
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveFoldable #-}
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE DeriveTraversable #-}
+{-# LANGUAGE DuplicateRecordFields #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE LambdaCase #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE NamedFieldPuns #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# OPTIONS_GHC -fno-warn-unused-matches -fno-warn-unused-binds -fno-warn-unused-imports #-}
+
+module AgentPushKit.Model where
+
+import AgentPushKit.Core
+import AgentPushKit.MimeTypes
+
+import Data.Aeson ((.:),(.:!),(.:?),(.=))
+
+import qualified Control.Arrow as P (left)
+import qualified Data.Aeson as A
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Base64 as B64
+import qualified Data.ByteString.Char8 as BC
+import qualified Data.ByteString.Lazy as BL
+import qualified Data.Data as P (Typeable, TypeRep, typeOf, typeRep)
+import qualified Data.Foldable as P
+import qualified Data.HashMap.Lazy as HM
+import qualified Data.Map as Map
+import qualified Data.Maybe as P
+import qualified Data.Set as Set
+import qualified Data.Text as T
+import qualified Data.Text.Encoding as T
+import qualified Data.Time as TI
+import qualified Lens.Micro as L
+import qualified Web.FormUrlEncoded as WH
+import qualified Web.HttpApiData as WH
+
+import Control.Applicative ((<|>))
+import Control.Applicative (Alternative)
+import Data.Function ((&))
+import Data.Monoid ((<>))
+import Data.Text (Text)
+import Prelude (($),(/=),(.),(<$>),(<*>),(>>=),(=<<),Maybe(..),Bool(..),Char,Double,FilePath,Float,Int,Integer,String,fmap,undefined,mempty,maybe,pure,Monad,Applicative,Functor)
+
+import qualified Prelude as P
+
+-- OpenAPI Generator 7.24 emits AnyType for free-form JSON without defining it.
+-- Aeson Value is the precise representation for an arbitrary JSON value.
+type AnyType = A.Value
+
+
+-- * Parameter newtypes
+
+
+-- ** Cursor
+newtype Cursor = Cursor { unCursor :: Text } deriving (P.Eq, P.Show)
+
+-- ** EventId
+newtype EventId = EventId { unEventId :: Text } deriving (P.Eq, P.Show)
+
+-- ** InstallationId
+newtype InstallationId = InstallationId { unInstallationId :: Text } deriving (P.Eq, P.Show)
+
+-- ** Limit
+newtype Limit = Limit { unLimit :: Int } deriving (P.Eq, P.Show)
+
+-- ** OrganizationId
+newtype OrganizationId = OrganizationId { unOrganizationId :: Text } deriving (P.Eq, P.Show)
+
+-- ** ParamType
+newtype ParamType = ParamType { unParamType :: Text } deriving (P.Eq, P.Show)
+
+-- ** RequestBody
+newtype RequestBody = RequestBody { unRequestBody :: (Map.Map String AnyType) } deriving (P.Eq, P.Show, A.ToJSON)
+
+-- ** Search
+newtype Search = Search { unSearch :: Text } deriving (P.Eq, P.Show)
+
+-- ** Service2
+newtype Service2 = Service2 { unService2 :: Text } deriving (P.Eq, P.Show)
+
+-- ** ServiceId
+newtype ServiceId = ServiceId { unServiceId :: Text } deriving (P.Eq, P.Show)
+
+-- ** SubscriptionId
+newtype SubscriptionId = SubscriptionId { unSubscriptionId :: Text } deriving (P.Eq, P.Show)
+
+-- ** TokenId
+newtype TokenId = TokenId { unTokenId :: Text } deriving (P.Eq, P.Show)
+
+-- * Models
+
+
+-- ** AcceptedResponse
+-- | AcceptedResponse
+data AcceptedResponse = AcceptedResponse
+  { acceptedResponseAccepted :: !(Bool) -- ^ /Required/ "accepted"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON AcceptedResponse
+instance A.FromJSON AcceptedResponse where
+  parseJSON = A.withObject "AcceptedResponse" $ \o ->
+    AcceptedResponse
+      <$> (o .:  "accepted")
+
+-- | ToJSON AcceptedResponse
+instance A.ToJSON AcceptedResponse where
+  toJSON AcceptedResponse {..} =
+   _omitNulls
+      [ "accepted" .= acceptedResponseAccepted
+      ]
+
+
+-- | Construct a value of type 'AcceptedResponse' (by applying it's required fields, if any)
+mkAcceptedResponse
+  :: Bool -- ^ 'acceptedResponseAccepted' 
+  -> AcceptedResponse
+mkAcceptedResponse acceptedResponseAccepted =
+  AcceptedResponse
+  { acceptedResponseAccepted
+  }
+
+-- ** AddMemberInput
+-- | AddMemberInput
+data AddMemberInput = AddMemberInput
+  { addMemberInputEmail :: !(Text) -- ^ /Required/ "email"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON AddMemberInput
+instance A.FromJSON AddMemberInput where
+  parseJSON = A.withObject "AddMemberInput" $ \o ->
+    AddMemberInput
+      <$> (o .:  "email")
+
+-- | ToJSON AddMemberInput
+instance A.ToJSON AddMemberInput where
+  toJSON AddMemberInput {..} =
+   _omitNulls
+      [ "email" .= addMemberInputEmail
+      ]
+
+
+-- | Construct a value of type 'AddMemberInput' (by applying it's required fields, if any)
+mkAddMemberInput
+  :: Text -- ^ 'addMemberInputEmail' 
+  -> AddMemberInput
+mkAddMemberInput addMemberInputEmail =
+  AddMemberInput
+  { addMemberInputEmail
+  }
+
+-- ** AgentToken
+-- | AgentToken
+data AgentToken = AgentToken
+  { agentTokenId :: !(Text) -- ^ /Required/ "id"
+  , agentTokenName :: !(Text) -- ^ /Required/ "name"
+  , agentTokenKeyPrefix :: !(Text) -- ^ /Required/ "keyPrefix"
+  , agentTokenLastFour :: !(Text) -- ^ /Required/ "lastFour"
+  , agentTokenCreatedAt :: !(DateTime) -- ^ /Required/ "createdAt"
+  , agentTokenLastUsedAt :: !(Maybe DateTime) -- ^ "lastUsedAt"
+  , agentTokenRevokedAt :: !(Maybe DateTime) -- ^ "revokedAt"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON AgentToken
+instance A.FromJSON AgentToken where
+  parseJSON = A.withObject "AgentToken" $ \o ->
+    AgentToken
+      <$> (o .:  "id")
+      <*> (o .:  "name")
+      <*> (o .:  "keyPrefix")
+      <*> (o .:  "lastFour")
+      <*> (o .:  "createdAt")
+      <*> (o .:? "lastUsedAt")
+      <*> (o .:? "revokedAt")
+
+-- | ToJSON AgentToken
+instance A.ToJSON AgentToken where
+  toJSON AgentToken {..} =
+   _omitNulls
+      [ "id" .= agentTokenId
+      , "name" .= agentTokenName
+      , "keyPrefix" .= agentTokenKeyPrefix
+      , "lastFour" .= agentTokenLastFour
+      , "createdAt" .= agentTokenCreatedAt
+      , "lastUsedAt" .= agentTokenLastUsedAt
+      , "revokedAt" .= agentTokenRevokedAt
+      ]
+
+
+-- | Construct a value of type 'AgentToken' (by applying it's required fields, if any)
+mkAgentToken
+  :: Text -- ^ 'agentTokenId' 
+  -> Text -- ^ 'agentTokenName' 
+  -> Text -- ^ 'agentTokenKeyPrefix' 
+  -> Text -- ^ 'agentTokenLastFour' 
+  -> DateTime -- ^ 'agentTokenCreatedAt' 
+  -> AgentToken
+mkAgentToken agentTokenId agentTokenName agentTokenKeyPrefix agentTokenLastFour agentTokenCreatedAt =
+  AgentToken
+  { agentTokenId
+  , agentTokenName
+  , agentTokenKeyPrefix
+  , agentTokenLastFour
+  , agentTokenCreatedAt
+  , agentTokenLastUsedAt = Nothing
+  , agentTokenRevokedAt = Nothing
+  }
+
+-- ** AgentTokenCreated
+-- | AgentTokenCreated
+data AgentTokenCreated = AgentTokenCreated
+  { agentTokenCreatedId :: !(Text) -- ^ /Required/ "id"
+  , agentTokenCreatedName :: !(Text) -- ^ /Required/ "name"
+  , agentTokenCreatedKeyPrefix :: !(Text) -- ^ /Required/ "keyPrefix"
+  , agentTokenCreatedLastFour :: !(Text) -- ^ /Required/ "lastFour"
+  , agentTokenCreatedCreatedAt :: !(DateTime) -- ^ /Required/ "createdAt"
+  , agentTokenCreatedLastUsedAt :: !(Maybe DateTime) -- ^ "lastUsedAt"
+  , agentTokenCreatedRevokedAt :: !(Maybe DateTime) -- ^ "revokedAt"
+  , agentTokenCreatedToken :: !(Text) -- ^ /Required/ "token"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON AgentTokenCreated
+instance A.FromJSON AgentTokenCreated where
+  parseJSON = A.withObject "AgentTokenCreated" $ \o ->
+    AgentTokenCreated
+      <$> (o .:  "id")
+      <*> (o .:  "name")
+      <*> (o .:  "keyPrefix")
+      <*> (o .:  "lastFour")
+      <*> (o .:  "createdAt")
+      <*> (o .:? "lastUsedAt")
+      <*> (o .:? "revokedAt")
+      <*> (o .:  "token")
+
+-- | ToJSON AgentTokenCreated
+instance A.ToJSON AgentTokenCreated where
+  toJSON AgentTokenCreated {..} =
+   _omitNulls
+      [ "id" .= agentTokenCreatedId
+      , "name" .= agentTokenCreatedName
+      , "keyPrefix" .= agentTokenCreatedKeyPrefix
+      , "lastFour" .= agentTokenCreatedLastFour
+      , "createdAt" .= agentTokenCreatedCreatedAt
+      , "lastUsedAt" .= agentTokenCreatedLastUsedAt
+      , "revokedAt" .= agentTokenCreatedRevokedAt
+      , "token" .= agentTokenCreatedToken
+      ]
+
+
+-- | Construct a value of type 'AgentTokenCreated' (by applying it's required fields, if any)
+mkAgentTokenCreated
+  :: Text -- ^ 'agentTokenCreatedId' 
+  -> Text -- ^ 'agentTokenCreatedName' 
+  -> Text -- ^ 'agentTokenCreatedKeyPrefix' 
+  -> Text -- ^ 'agentTokenCreatedLastFour' 
+  -> DateTime -- ^ 'agentTokenCreatedCreatedAt' 
+  -> Text -- ^ 'agentTokenCreatedToken' 
+  -> AgentTokenCreated
+mkAgentTokenCreated agentTokenCreatedId agentTokenCreatedName agentTokenCreatedKeyPrefix agentTokenCreatedLastFour agentTokenCreatedCreatedAt agentTokenCreatedToken =
+  AgentTokenCreated
+  { agentTokenCreatedId
+  , agentTokenCreatedName
+  , agentTokenCreatedKeyPrefix
+  , agentTokenCreatedLastFour
+  , agentTokenCreatedCreatedAt
+  , agentTokenCreatedLastUsedAt = Nothing
+  , agentTokenCreatedRevokedAt = Nothing
+  , agentTokenCreatedToken
+  }
+
+-- ** ApiKeySummary
+-- | ApiKeySummary
+data ApiKeySummary = ApiKeySummary
+  { apiKeySummaryKeyPrefix :: !(Maybe Text) -- ^ "keyPrefix"
+  , apiKeySummaryLastFour :: !(Maybe Text) -- ^ "lastFour"
+  , apiKeySummaryUpdatedAt :: !(Maybe DateTime) -- ^ "updatedAt"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON ApiKeySummary
+instance A.FromJSON ApiKeySummary where
+  parseJSON = A.withObject "ApiKeySummary" $ \o ->
+    ApiKeySummary
+      <$> (o .:? "keyPrefix")
+      <*> (o .:? "lastFour")
+      <*> (o .:? "updatedAt")
+
+-- | ToJSON ApiKeySummary
+instance A.ToJSON ApiKeySummary where
+  toJSON ApiKeySummary {..} =
+   _omitNulls
+      [ "keyPrefix" .= apiKeySummaryKeyPrefix
+      , "lastFour" .= apiKeySummaryLastFour
+      , "updatedAt" .= apiKeySummaryUpdatedAt
+      ]
+
+
+-- | Construct a value of type 'ApiKeySummary' (by applying it's required fields, if any)
+mkApiKeySummary
+  :: ApiKeySummary
+mkApiKeySummary =
+  ApiKeySummary
+  { apiKeySummaryKeyPrefix = Nothing
+  , apiKeySummaryLastFour = Nothing
+  , apiKeySummaryUpdatedAt = Nothing
+  }
+
+-- ** AuthResponse
+-- | AuthResponse
+data AuthResponse = AuthResponse
+  { authResponseAccessToken :: !(Text) -- ^ /Required/ "accessToken"
+  , authResponseUser :: !(User) -- ^ /Required/ "user"
+  , authResponseOrganizations :: !([Organization]) -- ^ /Required/ "organizations"
+  , authResponseBootstrapApiKey :: !(Maybe Text) -- ^ "bootstrapApiKey" - Present only when a new customer account was created.
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON AuthResponse
+instance A.FromJSON AuthResponse where
+  parseJSON = A.withObject "AuthResponse" $ \o ->
+    AuthResponse
+      <$> (o .:  "accessToken")
+      <*> (o .:  "user")
+      <*> (o .:  "organizations")
+      <*> (o .:? "bootstrapApiKey")
+
+-- | ToJSON AuthResponse
+instance A.ToJSON AuthResponse where
+  toJSON AuthResponse {..} =
+   _omitNulls
+      [ "accessToken" .= authResponseAccessToken
+      , "user" .= authResponseUser
+      , "organizations" .= authResponseOrganizations
+      , "bootstrapApiKey" .= authResponseBootstrapApiKey
+      ]
+
+
+-- | Construct a value of type 'AuthResponse' (by applying it's required fields, if any)
+mkAuthResponse
+  :: Text -- ^ 'authResponseAccessToken' 
+  -> User -- ^ 'authResponseUser' 
+  -> [Organization] -- ^ 'authResponseOrganizations' 
+  -> AuthResponse
+mkAuthResponse authResponseAccessToken authResponseUser authResponseOrganizations =
+  AuthResponse
+  { authResponseAccessToken
+  , authResponseUser
+  , authResponseOrganizations
+  , authResponseBootstrapApiKey = Nothing
+  }
+
+-- ** CreateAgentTokenInput
+-- | CreateAgentTokenInput
+data CreateAgentTokenInput = CreateAgentTokenInput
+  { createAgentTokenInputName :: !(Text) -- ^ /Required/ "name"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON CreateAgentTokenInput
+instance A.FromJSON CreateAgentTokenInput where
+  parseJSON = A.withObject "CreateAgentTokenInput" $ \o ->
+    CreateAgentTokenInput
+      <$> (o .:  "name")
+
+-- | ToJSON CreateAgentTokenInput
+instance A.ToJSON CreateAgentTokenInput where
+  toJSON CreateAgentTokenInput {..} =
+   _omitNulls
+      [ "name" .= createAgentTokenInputName
+      ]
+
+
+-- | Construct a value of type 'CreateAgentTokenInput' (by applying it's required fields, if any)
+mkCreateAgentTokenInput
+  :: Text -- ^ 'createAgentTokenInputName' 
+  -> CreateAgentTokenInput
+mkCreateAgentTokenInput createAgentTokenInputName =
+  CreateAgentTokenInput
+  { createAgentTokenInputName
+  }
+
+-- ** CreateOrganizationInput
+-- | CreateOrganizationInput
+data CreateOrganizationInput = CreateOrganizationInput
+  { createOrganizationInputName :: !(Text) -- ^ /Required/ "name"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON CreateOrganizationInput
+instance A.FromJSON CreateOrganizationInput where
+  parseJSON = A.withObject "CreateOrganizationInput" $ \o ->
+    CreateOrganizationInput
+      <$> (o .:  "name")
+
+-- | ToJSON CreateOrganizationInput
+instance A.ToJSON CreateOrganizationInput where
+  toJSON CreateOrganizationInput {..} =
+   _omitNulls
+      [ "name" .= createOrganizationInputName
+      ]
+
+
+-- | Construct a value of type 'CreateOrganizationInput' (by applying it's required fields, if any)
+mkCreateOrganizationInput
+  :: Text -- ^ 'createOrganizationInputName' 
+  -> CreateOrganizationInput
+mkCreateOrganizationInput createOrganizationInputName =
+  CreateOrganizationInput
+  { createOrganizationInputName
+  }
+
+-- ** CurrentAccount
+-- | CurrentAccount
+data CurrentAccount = CurrentAccount
+  { currentAccountUser :: !(User) -- ^ /Required/ "user"
+  , currentAccountOrganizations :: !([Organization]) -- ^ /Required/ "organizations"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON CurrentAccount
+instance A.FromJSON CurrentAccount where
+  parseJSON = A.withObject "CurrentAccount" $ \o ->
+    CurrentAccount
+      <$> (o .:  "user")
+      <*> (o .:  "organizations")
+
+-- | ToJSON CurrentAccount
+instance A.ToJSON CurrentAccount where
+  toJSON CurrentAccount {..} =
+   _omitNulls
+      [ "user" .= currentAccountUser
+      , "organizations" .= currentAccountOrganizations
+      ]
+
+
+-- | Construct a value of type 'CurrentAccount' (by applying it's required fields, if any)
+mkCurrentAccount
+  :: User -- ^ 'currentAccountUser' 
+  -> [Organization] -- ^ 'currentAccountOrganizations' 
+  -> CurrentAccount
+mkCurrentAccount currentAccountUser currentAccountOrganizations =
+  CurrentAccount
+  { currentAccountUser
+  , currentAccountOrganizations
+  }
+
+-- ** DeletedResponse
+-- | DeletedResponse
+data DeletedResponse = DeletedResponse
+  { deletedResponseDeleted :: !(Bool) -- ^ /Required/ "deleted"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON DeletedResponse
+instance A.FromJSON DeletedResponse where
+  parseJSON = A.withObject "DeletedResponse" $ \o ->
+    DeletedResponse
+      <$> (o .:  "deleted")
+
+-- | ToJSON DeletedResponse
+instance A.ToJSON DeletedResponse where
+  toJSON DeletedResponse {..} =
+   _omitNulls
+      [ "deleted" .= deletedResponseDeleted
+      ]
+
+
+-- | Construct a value of type 'DeletedResponse' (by applying it's required fields, if any)
+mkDeletedResponse
+  :: Bool -- ^ 'deletedResponseDeleted' 
+  -> DeletedResponse
+mkDeletedResponse deletedResponseDeleted =
+  DeletedResponse
+  { deletedResponseDeleted
+  }
+
+-- ** DeliverySummary
+-- | DeliverySummary
+data DeliverySummary = DeliverySummary
+  { deliverySummarySent :: !(Int) -- ^ /Required/ "sent"
+  , deliverySummaryFailed :: !(Int) -- ^ /Required/ "failed"
+  , deliverySummarySuppressedUsers :: !(Int) -- ^ /Required/ "suppressedUsers"
+  , deliverySummaryEligibleDevices :: !(Int) -- ^ /Required/ "eligibleDevices"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON DeliverySummary
+instance A.FromJSON DeliverySummary where
+  parseJSON = A.withObject "DeliverySummary" $ \o ->
+    DeliverySummary
+      <$> (o .:  "sent")
+      <*> (o .:  "failed")
+      <*> (o .:  "suppressedUsers")
+      <*> (o .:  "eligibleDevices")
+
+-- | ToJSON DeliverySummary
+instance A.ToJSON DeliverySummary where
+  toJSON DeliverySummary {..} =
+   _omitNulls
+      [ "sent" .= deliverySummarySent
+      , "failed" .= deliverySummaryFailed
+      , "suppressedUsers" .= deliverySummarySuppressedUsers
+      , "eligibleDevices" .= deliverySummaryEligibleDevices
+      ]
+
+
+-- | Construct a value of type 'DeliverySummary' (by applying it's required fields, if any)
+mkDeliverySummary
+  :: Int -- ^ 'deliverySummarySent' 
+  -> Int -- ^ 'deliverySummaryFailed' 
+  -> Int -- ^ 'deliverySummarySuppressedUsers' 
+  -> Int -- ^ 'deliverySummaryEligibleDevices' 
+  -> DeliverySummary
+mkDeliverySummary deliverySummarySent deliverySummaryFailed deliverySummarySuppressedUsers deliverySummaryEligibleDevices =
+  DeliverySummary
+  { deliverySummarySent
+  , deliverySummaryFailed
+  , deliverySummarySuppressedUsers
+  , deliverySummaryEligibleDevices
+  }
+
+-- ** Device
+-- | Device
+data Device = Device
+  { deviceId :: !(Text) -- ^ /Required/ "id"
+  , deviceInstallationId :: !(Text) -- ^ /Required/ "installationId"
+  , deviceEnvironment :: !(E'Environment) -- ^ /Required/ "environment"
+  , deviceAppVersion :: !(Maybe Text) -- ^ "appVersion"
+  , deviceEnabled :: !(Bool) -- ^ /Required/ "enabled"
+  , deviceLastSeenAt :: !(DateTime) -- ^ /Required/ "lastSeenAt"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON Device
+instance A.FromJSON Device where
+  parseJSON = A.withObject "Device" $ \o ->
+    Device
+      <$> (o .:  "id")
+      <*> (o .:  "installationId")
+      <*> (o .:  "environment")
+      <*> (o .:? "appVersion")
+      <*> (o .:  "enabled")
+      <*> (o .:  "lastSeenAt")
+
+-- | ToJSON Device
+instance A.ToJSON Device where
+  toJSON Device {..} =
+   _omitNulls
+      [ "id" .= deviceId
+      , "installationId" .= deviceInstallationId
+      , "environment" .= deviceEnvironment
+      , "appVersion" .= deviceAppVersion
+      , "enabled" .= deviceEnabled
+      , "lastSeenAt" .= deviceLastSeenAt
+      ]
+
+
+-- | Construct a value of type 'Device' (by applying it's required fields, if any)
+mkDevice
+  :: Text -- ^ 'deviceId' 
+  -> Text -- ^ 'deviceInstallationId' 
+  -> E'Environment -- ^ 'deviceEnvironment' 
+  -> Bool -- ^ 'deviceEnabled' 
+  -> DateTime -- ^ 'deviceLastSeenAt' 
+  -> Device
+mkDevice deviceId deviceInstallationId deviceEnvironment deviceEnabled deviceLastSeenAt =
+  Device
+  { deviceId
+  , deviceInstallationId
+  , deviceEnvironment
+  , deviceAppVersion = Nothing
+  , deviceEnabled
+  , deviceLastSeenAt
+  }
+
+-- ** DisabledResponse
+-- | DisabledResponse
+data DisabledResponse = DisabledResponse
+  { disabledResponseDisabled :: !(Bool) -- ^ /Required/ "disabled"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON DisabledResponse
+instance A.FromJSON DisabledResponse where
+  parseJSON = A.withObject "DisabledResponse" $ \o ->
+    DisabledResponse
+      <$> (o .:  "disabled")
+
+-- | ToJSON DisabledResponse
+instance A.ToJSON DisabledResponse where
+  toJSON DisabledResponse {..} =
+   _omitNulls
+      [ "disabled" .= disabledResponseDisabled
+      ]
+
+
+-- | Construct a value of type 'DisabledResponse' (by applying it's required fields, if any)
+mkDisabledResponse
+  :: Bool -- ^ 'disabledResponseDisabled' 
+  -> DisabledResponse
+mkDisabledResponse disabledResponseDisabled =
+  DisabledResponse
+  { disabledResponseDisabled
+  }
+
+-- ** ErrorResponse
+-- | ErrorResponse
+data ErrorResponse = ErrorResponse
+  { errorResponseStatusCode :: !(Int) -- ^ /Required/ "statusCode"
+  , errorResponseMessage :: !(Text) -- ^ /Required/ "message"
+  , errorResponseError :: !(Maybe Text) -- ^ "error"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON ErrorResponse
+instance A.FromJSON ErrorResponse where
+  parseJSON = A.withObject "ErrorResponse" $ \o ->
+    ErrorResponse
+      <$> (o .:  "statusCode")
+      <*> (o .:  "message")
+      <*> (o .:? "error")
+
+-- | ToJSON ErrorResponse
+instance A.ToJSON ErrorResponse where
+  toJSON ErrorResponse {..} =
+   _omitNulls
+      [ "statusCode" .= errorResponseStatusCode
+      , "message" .= errorResponseMessage
+      , "error" .= errorResponseError
+      ]
+
+
+-- | Construct a value of type 'ErrorResponse' (by applying it's required fields, if any)
+mkErrorResponse
+  :: Int -- ^ 'errorResponseStatusCode' 
+  -> Text -- ^ 'errorResponseMessage' 
+  -> ErrorResponse
+mkErrorResponse errorResponseStatusCode errorResponseMessage =
+  ErrorResponse
+  { errorResponseStatusCode
+  , errorResponseMessage
+  , errorResponseError = Nothing
+  }
+
+-- ** EventDetail
+-- | EventDetail
+data EventDetail = EventDetail
+  { eventDetailId :: !(Text) -- ^ /Required/ "id"
+  , eventDetailType :: !(Text) -- ^ /Required/ "type"
+  , eventDetailTitle :: !(Text) -- ^ /Required/ "title"
+  , eventDetailBody :: !(Text) -- ^ /Required/ "body"
+  , eventDetailExternalId :: !(Maybe Text) -- ^ "externalId"
+  , eventDetailActionUrl :: !(Maybe Text) -- ^ "actionUrl"
+  , eventDetailCreatedAt :: !(DateTime) -- ^ /Required/ "createdAt"
+  , eventDetailService :: !(ServiceSummary) -- ^ /Required/ "service"
+  , eventDetailServiceId :: !(Text) -- ^ /Required/ "serviceId"
+  , eventDetailMetadata :: !(Maybe (Map.Map String AnyType)) -- ^ "metadata"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON EventDetail
+instance A.FromJSON EventDetail where
+  parseJSON = A.withObject "EventDetail" $ \o ->
+    EventDetail
+      <$> (o .:  "id")
+      <*> (o .:  "type")
+      <*> (o .:  "title")
+      <*> (o .:  "body")
+      <*> (o .:? "externalId")
+      <*> (o .:? "actionUrl")
+      <*> (o .:  "createdAt")
+      <*> (o .:  "service")
+      <*> (o .:  "serviceId")
+      <*> (o .:? "metadata")
+
+-- | ToJSON EventDetail
+instance A.ToJSON EventDetail where
+  toJSON EventDetail {..} =
+   _omitNulls
+      [ "id" .= eventDetailId
+      , "type" .= eventDetailType
+      , "title" .= eventDetailTitle
+      , "body" .= eventDetailBody
+      , "externalId" .= eventDetailExternalId
+      , "actionUrl" .= eventDetailActionUrl
+      , "createdAt" .= eventDetailCreatedAt
+      , "service" .= eventDetailService
+      , "serviceId" .= eventDetailServiceId
+      , "metadata" .= eventDetailMetadata
+      ]
+
+
+-- | Construct a value of type 'EventDetail' (by applying it's required fields, if any)
+mkEventDetail
+  :: Text -- ^ 'eventDetailId' 
+  -> Text -- ^ 'eventDetailType' 
+  -> Text -- ^ 'eventDetailTitle' 
+  -> Text -- ^ 'eventDetailBody' 
+  -> DateTime -- ^ 'eventDetailCreatedAt' 
+  -> ServiceSummary -- ^ 'eventDetailService' 
+  -> Text -- ^ 'eventDetailServiceId' 
+  -> EventDetail
+mkEventDetail eventDetailId eventDetailType eventDetailTitle eventDetailBody eventDetailCreatedAt eventDetailService eventDetailServiceId =
+  EventDetail
+  { eventDetailId
+  , eventDetailType
+  , eventDetailTitle
+  , eventDetailBody
+  , eventDetailExternalId = Nothing
+  , eventDetailActionUrl = Nothing
+  , eventDetailCreatedAt
+  , eventDetailService
+  , eventDetailServiceId
+  , eventDetailMetadata = Nothing
+  }
+
+-- ** EventFilter
+-- | EventFilter
+data EventFilter = EventFilter
+  { eventFilterOperator :: !(E'Operator) -- ^ /Required/ "operator"
+  , eventFilterChildren :: !([EventFilter]) -- ^ /Required/ "children"
+  , eventFilterChild :: !(EventFilter) -- ^ /Required/ "child"
+  , eventFilterField :: !(E'Field) -- ^ /Required/ "field"
+  , eventFilterComparison :: !(E'Comparison) -- ^ /Required/ "comparison"
+  , eventFilterValue :: !(DateTime) -- ^ /Required/ "value"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON EventFilter
+instance A.FromJSON EventFilter where
+  parseJSON = A.withObject "EventFilter" $ \o ->
+    EventFilter
+      <$> (o .:  "operator")
+      <*> (o .:  "children")
+      <*> (o .:  "child")
+      <*> (o .:  "field")
+      <*> (o .:  "comparison")
+      <*> (o .:  "value")
+
+-- | ToJSON EventFilter
+instance A.ToJSON EventFilter where
+  toJSON EventFilter {..} =
+   _omitNulls
+      [ "operator" .= eventFilterOperator
+      , "children" .= eventFilterChildren
+      , "child" .= eventFilterChild
+      , "field" .= eventFilterField
+      , "comparison" .= eventFilterComparison
+      , "value" .= eventFilterValue
+      ]
+
+
+-- | Construct a value of type 'EventFilter' (by applying it's required fields, if any)
+mkEventFilter
+  :: E'Operator -- ^ 'eventFilterOperator' 
+  -> [EventFilter] -- ^ 'eventFilterChildren' 
+  -> EventFilter -- ^ 'eventFilterChild' 
+  -> E'Field -- ^ 'eventFilterField' 
+  -> E'Comparison -- ^ 'eventFilterComparison' 
+  -> DateTime -- ^ 'eventFilterValue' 
+  -> EventFilter
+mkEventFilter eventFilterOperator eventFilterChildren eventFilterChild eventFilterField eventFilterComparison eventFilterValue =
+  EventFilter
+  { eventFilterOperator
+  , eventFilterChildren
+  , eventFilterChild
+  , eventFilterField
+  , eventFilterComparison
+  , eventFilterValue
+  }
+
+-- ** EventPage
+-- | EventPage
+data EventPage = EventPage
+  { eventPageEvents :: !([EventSummary]) -- ^ /Required/ "events"
+  , eventPageNextCursor :: !(Maybe Text) -- ^ "nextCursor"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON EventPage
+instance A.FromJSON EventPage where
+  parseJSON = A.withObject "EventPage" $ \o ->
+    EventPage
+      <$> (o .:  "events")
+      <*> (o .:? "nextCursor")
+
+-- | ToJSON EventPage
+instance A.ToJSON EventPage where
+  toJSON EventPage {..} =
+   _omitNulls
+      [ "events" .= eventPageEvents
+      , "nextCursor" .= eventPageNextCursor
+      ]
+
+
+-- | Construct a value of type 'EventPage' (by applying it's required fields, if any)
+mkEventPage
+  :: [EventSummary] -- ^ 'eventPageEvents' 
+  -> EventPage
+mkEventPage eventPageEvents =
+  EventPage
+  { eventPageEvents
+  , eventPageNextCursor = Nothing
+  }
+
+-- ** EventSummary
+-- | EventSummary
+data EventSummary = EventSummary
+  { eventSummaryId :: !(Text) -- ^ /Required/ "id"
+  , eventSummaryType :: !(Text) -- ^ /Required/ "type"
+  , eventSummaryTitle :: !(Text) -- ^ /Required/ "title"
+  , eventSummaryBody :: !(Text) -- ^ /Required/ "body"
+  , eventSummaryExternalId :: !(Maybe Text) -- ^ "externalId"
+  , eventSummaryActionUrl :: !(Maybe Text) -- ^ "actionUrl"
+  , eventSummaryCreatedAt :: !(DateTime) -- ^ /Required/ "createdAt"
+  , eventSummaryService :: !(ServiceSummary) -- ^ /Required/ "service"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON EventSummary
+instance A.FromJSON EventSummary where
+  parseJSON = A.withObject "EventSummary" $ \o ->
+    EventSummary
+      <$> (o .:  "id")
+      <*> (o .:  "type")
+      <*> (o .:  "title")
+      <*> (o .:  "body")
+      <*> (o .:? "externalId")
+      <*> (o .:? "actionUrl")
+      <*> (o .:  "createdAt")
+      <*> (o .:  "service")
+
+-- | ToJSON EventSummary
+instance A.ToJSON EventSummary where
+  toJSON EventSummary {..} =
+   _omitNulls
+      [ "id" .= eventSummaryId
+      , "type" .= eventSummaryType
+      , "title" .= eventSummaryTitle
+      , "body" .= eventSummaryBody
+      , "externalId" .= eventSummaryExternalId
+      , "actionUrl" .= eventSummaryActionUrl
+      , "createdAt" .= eventSummaryCreatedAt
+      , "service" .= eventSummaryService
+      ]
+
+
+-- | Construct a value of type 'EventSummary' (by applying it's required fields, if any)
+mkEventSummary
+  :: Text -- ^ 'eventSummaryId' 
+  -> Text -- ^ 'eventSummaryType' 
+  -> Text -- ^ 'eventSummaryTitle' 
+  -> Text -- ^ 'eventSummaryBody' 
+  -> DateTime -- ^ 'eventSummaryCreatedAt' 
+  -> ServiceSummary -- ^ 'eventSummaryService' 
+  -> EventSummary
+mkEventSummary eventSummaryId eventSummaryType eventSummaryTitle eventSummaryBody eventSummaryCreatedAt eventSummaryService =
+  EventSummary
+  { eventSummaryId
+  , eventSummaryType
+  , eventSummaryTitle
+  , eventSummaryBody
+  , eventSummaryExternalId = Nothing
+  , eventSummaryActionUrl = Nothing
+  , eventSummaryCreatedAt
+  , eventSummaryService
+  }
+
+-- ** FilterGroup
+-- | FilterGroup
+data FilterGroup = FilterGroup
+  { filterGroupOperator :: !(E'Operator2) -- ^ /Required/ "operator"
+  , filterGroupChildren :: !([EventFilter]) -- ^ /Required/ "children"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON FilterGroup
+instance A.FromJSON FilterGroup where
+  parseJSON = A.withObject "FilterGroup" $ \o ->
+    FilterGroup
+      <$> (o .:  "operator")
+      <*> (o .:  "children")
+
+-- | ToJSON FilterGroup
+instance A.ToJSON FilterGroup where
+  toJSON FilterGroup {..} =
+   _omitNulls
+      [ "operator" .= filterGroupOperator
+      , "children" .= filterGroupChildren
+      ]
+
+
+-- | Construct a value of type 'FilterGroup' (by applying it's required fields, if any)
+mkFilterGroup
+  :: E'Operator2 -- ^ 'filterGroupOperator' 
+  -> [EventFilter] -- ^ 'filterGroupChildren' 
+  -> FilterGroup
+mkFilterGroup filterGroupOperator filterGroupChildren =
+  FilterGroup
+  { filterGroupOperator
+  , filterGroupChildren
+  }
+
+-- ** FilterNot
+-- | FilterNot
+data FilterNot = FilterNot
+  { filterNotOperator :: !(E'Operator) -- ^ /Required/ "operator"
+  , filterNotChild :: !(EventFilter) -- ^ /Required/ "child"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON FilterNot
+instance A.FromJSON FilterNot where
+  parseJSON = A.withObject "FilterNot" $ \o ->
+    FilterNot
+      <$> (o .:  "operator")
+      <*> (o .:  "child")
+
+-- | ToJSON FilterNot
+instance A.ToJSON FilterNot where
+  toJSON FilterNot {..} =
+   _omitNulls
+      [ "operator" .= filterNotOperator
+      , "child" .= filterNotChild
+      ]
+
+
+-- | Construct a value of type 'FilterNot' (by applying it's required fields, if any)
+mkFilterNot
+  :: E'Operator -- ^ 'filterNotOperator' 
+  -> EventFilter -- ^ 'filterNotChild' 
+  -> FilterNot
+mkFilterNot filterNotOperator filterNotChild =
+  FilterNot
+  { filterNotOperator
+  , filterNotChild
+  }
+
+-- ** HealthResponse
+-- | HealthResponse
+data HealthResponse = HealthResponse
+  { healthResponseStatus :: !(E'Status) -- ^ /Required/ "status"
+  , healthResponseService :: !(E'Service) -- ^ /Required/ "service"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON HealthResponse
+instance A.FromJSON HealthResponse where
+  parseJSON = A.withObject "HealthResponse" $ \o ->
+    HealthResponse
+      <$> (o .:  "status")
+      <*> (o .:  "service")
+
+-- | ToJSON HealthResponse
+instance A.ToJSON HealthResponse where
+  toJSON HealthResponse {..} =
+   _omitNulls
+      [ "status" .= healthResponseStatus
+      , "service" .= healthResponseService
+      ]
+
+
+-- | Construct a value of type 'HealthResponse' (by applying it's required fields, if any)
+mkHealthResponse
+  :: E'Status -- ^ 'healthResponseStatus' 
+  -> E'Service -- ^ 'healthResponseService' 
+  -> HealthResponse
+mkHealthResponse healthResponseStatus healthResponseService =
+  HealthResponse
+  { healthResponseStatus
+  , healthResponseService
+  }
+
+-- ** IngestionResult
+-- | IngestionResult
+data IngestionResult = IngestionResult
+  { ingestionResultEvent :: !(EventDetail) -- ^ /Required/ "event"
+  , ingestionResultDuplicate :: !(Bool) -- ^ /Required/ "duplicate"
+  , ingestionResultDelivery :: !(DeliverySummary) -- ^ /Required/ "delivery"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON IngestionResult
+instance A.FromJSON IngestionResult where
+  parseJSON = A.withObject "IngestionResult" $ \o ->
+    IngestionResult
+      <$> (o .:  "event")
+      <*> (o .:  "duplicate")
+      <*> (o .:  "delivery")
+
+-- | ToJSON IngestionResult
+instance A.ToJSON IngestionResult where
+  toJSON IngestionResult {..} =
+   _omitNulls
+      [ "event" .= ingestionResultEvent
+      , "duplicate" .= ingestionResultDuplicate
+      , "delivery" .= ingestionResultDelivery
+      ]
+
+
+-- | Construct a value of type 'IngestionResult' (by applying it's required fields, if any)
+mkIngestionResult
+  :: EventDetail -- ^ 'ingestionResultEvent' 
+  -> Bool -- ^ 'ingestionResultDuplicate' 
+  -> DeliverySummary -- ^ 'ingestionResultDelivery' 
+  -> IngestionResult
+mkIngestionResult ingestionResultEvent ingestionResultDuplicate ingestionResultDelivery =
+  IngestionResult
+  { ingestionResultEvent
+  , ingestionResultDuplicate
+  , ingestionResultDelivery
+  }
+
+-- ** InheritedResponse
+-- | InheritedResponse
+data InheritedResponse = InheritedResponse
+  { inheritedResponseInherited :: !(Bool) -- ^ /Required/ "inherited"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON InheritedResponse
+instance A.FromJSON InheritedResponse where
+  parseJSON = A.withObject "InheritedResponse" $ \o ->
+    InheritedResponse
+      <$> (o .:  "inherited")
+
+-- | ToJSON InheritedResponse
+instance A.ToJSON InheritedResponse where
+  toJSON InheritedResponse {..} =
+   _omitNulls
+      [ "inherited" .= inheritedResponseInherited
+      ]
+
+
+-- | Construct a value of type 'InheritedResponse' (by applying it's required fields, if any)
+mkInheritedResponse
+  :: Bool -- ^ 'inheritedResponseInherited' 
+  -> InheritedResponse
+mkInheritedResponse inheritedResponseInherited =
+  InheritedResponse
+  { inheritedResponseInherited
+  }
+
+-- ** Membership
+-- | Membership
+data Membership = Membership
+  { membershipId :: !(Text) -- ^ /Required/ "id"
+  , membershipRole :: !(E'Role) -- ^ /Required/ "role"
+  , membershipCreatedAt :: !(DateTime) -- ^ /Required/ "createdAt"
+  , membershipUser :: !(MembershipUser) -- ^ /Required/ "user"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON Membership
+instance A.FromJSON Membership where
+  parseJSON = A.withObject "Membership" $ \o ->
+    Membership
+      <$> (o .:  "id")
+      <*> (o .:  "role")
+      <*> (o .:  "createdAt")
+      <*> (o .:  "user")
+
+-- | ToJSON Membership
+instance A.ToJSON Membership where
+  toJSON Membership {..} =
+   _omitNulls
+      [ "id" .= membershipId
+      , "role" .= membershipRole
+      , "createdAt" .= membershipCreatedAt
+      , "user" .= membershipUser
+      ]
+
+
+-- | Construct a value of type 'Membership' (by applying it's required fields, if any)
+mkMembership
+  :: Text -- ^ 'membershipId' 
+  -> E'Role -- ^ 'membershipRole' 
+  -> DateTime -- ^ 'membershipCreatedAt' 
+  -> MembershipUser -- ^ 'membershipUser' 
+  -> Membership
+mkMembership membershipId membershipRole membershipCreatedAt membershipUser =
+  Membership
+  { membershipId
+  , membershipRole
+  , membershipCreatedAt
+  , membershipUser
+  }
+
+-- ** MembershipUser
+-- | MembershipUser
+data MembershipUser = MembershipUser
+  { membershipUserId :: !(Text) -- ^ /Required/ "id"
+  , membershipUserEmail :: !(Text) -- ^ /Required/ "email"
+  , membershipUserDisplayName :: !(Maybe Text) -- ^ "displayName"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON MembershipUser
+instance A.FromJSON MembershipUser where
+  parseJSON = A.withObject "MembershipUser" $ \o ->
+    MembershipUser
+      <$> (o .:  "id")
+      <*> (o .:  "email")
+      <*> (o .:? "displayName")
+
+-- | ToJSON MembershipUser
+instance A.ToJSON MembershipUser where
+  toJSON MembershipUser {..} =
+   _omitNulls
+      [ "id" .= membershipUserId
+      , "email" .= membershipUserEmail
+      , "displayName" .= membershipUserDisplayName
+      ]
+
+
+-- | Construct a value of type 'MembershipUser' (by applying it's required fields, if any)
+mkMembershipUser
+  :: Text -- ^ 'membershipUserId' 
+  -> Text -- ^ 'membershipUserEmail' 
+  -> MembershipUser
+mkMembershipUser membershipUserId membershipUserEmail =
+  MembershipUser
+  { membershipUserId
+  , membershipUserEmail
+  , membershipUserDisplayName = Nothing
+  }
+
+-- ** Organization
+-- | Organization
+data Organization = Organization
+  { organizationId :: !(Text) -- ^ /Required/ "id"
+  , organizationName :: !(Text) -- ^ /Required/ "name"
+  , organizationRole :: !(E'Role) -- ^ /Required/ "role"
+  , organizationCreatedAt :: !(DateTime) -- ^ /Required/ "createdAt"
+  , organizationUpdatedAt :: !(DateTime) -- ^ /Required/ "updatedAt"
+  , organizationJoinedAt :: !(DateTime) -- ^ /Required/ "joinedAt"
+  , organizationApiKey :: !(Maybe ApiKeySummary) -- ^ "apiKey"
+  , organizationCount :: !(Maybe OrganizationCount) -- ^ "_count"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON Organization
+instance A.FromJSON Organization where
+  parseJSON = A.withObject "Organization" $ \o ->
+    Organization
+      <$> (o .:  "id")
+      <*> (o .:  "name")
+      <*> (o .:  "role")
+      <*> (o .:  "createdAt")
+      <*> (o .:  "updatedAt")
+      <*> (o .:  "joinedAt")
+      <*> (o .:? "apiKey")
+      <*> (o .:? "_count")
+
+-- | ToJSON Organization
+instance A.ToJSON Organization where
+  toJSON Organization {..} =
+   _omitNulls
+      [ "id" .= organizationId
+      , "name" .= organizationName
+      , "role" .= organizationRole
+      , "createdAt" .= organizationCreatedAt
+      , "updatedAt" .= organizationUpdatedAt
+      , "joinedAt" .= organizationJoinedAt
+      , "apiKey" .= organizationApiKey
+      , "_count" .= organizationCount
+      ]
+
+
+-- | Construct a value of type 'Organization' (by applying it's required fields, if any)
+mkOrganization
+  :: Text -- ^ 'organizationId' 
+  -> Text -- ^ 'organizationName' 
+  -> E'Role -- ^ 'organizationRole' 
+  -> DateTime -- ^ 'organizationCreatedAt' 
+  -> DateTime -- ^ 'organizationUpdatedAt' 
+  -> DateTime -- ^ 'organizationJoinedAt' 
+  -> Organization
+mkOrganization organizationId organizationName organizationRole organizationCreatedAt organizationUpdatedAt organizationJoinedAt =
+  Organization
+  { organizationId
+  , organizationName
+  , organizationRole
+  , organizationCreatedAt
+  , organizationUpdatedAt
+  , organizationJoinedAt
+  , organizationApiKey = Nothing
+  , organizationCount = Nothing
+  }
+
+-- ** OrganizationApiKeyCreated
+-- | OrganizationApiKeyCreated
+data OrganizationApiKeyCreated = OrganizationApiKeyCreated
+  { organizationApiKeyCreatedKeyPrefix :: !(Text) -- ^ /Required/ "keyPrefix"
+  , organizationApiKeyCreatedLastFour :: !(Text) -- ^ /Required/ "lastFour"
+  , organizationApiKeyCreatedUpdatedAt :: !(DateTime) -- ^ /Required/ "updatedAt"
+  , organizationApiKeyCreatedApiKey :: !(Text) -- ^ /Required/ "apiKey"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON OrganizationApiKeyCreated
+instance A.FromJSON OrganizationApiKeyCreated where
+  parseJSON = A.withObject "OrganizationApiKeyCreated" $ \o ->
+    OrganizationApiKeyCreated
+      <$> (o .:  "keyPrefix")
+      <*> (o .:  "lastFour")
+      <*> (o .:  "updatedAt")
+      <*> (o .:  "apiKey")
+
+-- | ToJSON OrganizationApiKeyCreated
+instance A.ToJSON OrganizationApiKeyCreated where
+  toJSON OrganizationApiKeyCreated {..} =
+   _omitNulls
+      [ "keyPrefix" .= organizationApiKeyCreatedKeyPrefix
+      , "lastFour" .= organizationApiKeyCreatedLastFour
+      , "updatedAt" .= organizationApiKeyCreatedUpdatedAt
+      , "apiKey" .= organizationApiKeyCreatedApiKey
+      ]
+
+
+-- | Construct a value of type 'OrganizationApiKeyCreated' (by applying it's required fields, if any)
+mkOrganizationApiKeyCreated
+  :: Text -- ^ 'organizationApiKeyCreatedKeyPrefix' 
+  -> Text -- ^ 'organizationApiKeyCreatedLastFour' 
+  -> DateTime -- ^ 'organizationApiKeyCreatedUpdatedAt' 
+  -> Text -- ^ 'organizationApiKeyCreatedApiKey' 
+  -> OrganizationApiKeyCreated
+mkOrganizationApiKeyCreated organizationApiKeyCreatedKeyPrefix organizationApiKeyCreatedLastFour organizationApiKeyCreatedUpdatedAt organizationApiKeyCreatedApiKey =
+  OrganizationApiKeyCreated
+  { organizationApiKeyCreatedKeyPrefix
+  , organizationApiKeyCreatedLastFour
+  , organizationApiKeyCreatedUpdatedAt
+  , organizationApiKeyCreatedApiKey
+  }
+
+-- ** OrganizationCount
+-- | OrganizationCount
+data OrganizationCount = OrganizationCount
+  { organizationCountMemberships :: !(Maybe Int) -- ^ "memberships"
+  , organizationCountServices :: !(Maybe Int) -- ^ "services"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON OrganizationCount
+instance A.FromJSON OrganizationCount where
+  parseJSON = A.withObject "OrganizationCount" $ \o ->
+    OrganizationCount
+      <$> (o .:? "memberships")
+      <*> (o .:? "services")
+
+-- | ToJSON OrganizationCount
+instance A.ToJSON OrganizationCount where
+  toJSON OrganizationCount {..} =
+   _omitNulls
+      [ "memberships" .= organizationCountMemberships
+      , "services" .= organizationCountServices
+      ]
+
+
+-- | Construct a value of type 'OrganizationCount' (by applying it's required fields, if any)
+mkOrganizationCount
+  :: OrganizationCount
+mkOrganizationCount =
+  OrganizationCount
+  { organizationCountMemberships = Nothing
+  , organizationCountServices = Nothing
+  }
+
+-- ** OrganizationCreated
+-- | OrganizationCreated
+data OrganizationCreated = OrganizationCreated
+  { organizationCreatedOrganization :: !(OrganizationRecord) -- ^ /Required/ "organization"
+  , organizationCreatedApiKey :: !(Text) -- ^ /Required/ "apiKey"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON OrganizationCreated
+instance A.FromJSON OrganizationCreated where
+  parseJSON = A.withObject "OrganizationCreated" $ \o ->
+    OrganizationCreated
+      <$> (o .:  "organization")
+      <*> (o .:  "apiKey")
+
+-- | ToJSON OrganizationCreated
+instance A.ToJSON OrganizationCreated where
+  toJSON OrganizationCreated {..} =
+   _omitNulls
+      [ "organization" .= organizationCreatedOrganization
+      , "apiKey" .= organizationCreatedApiKey
+      ]
+
+
+-- | Construct a value of type 'OrganizationCreated' (by applying it's required fields, if any)
+mkOrganizationCreated
+  :: OrganizationRecord -- ^ 'organizationCreatedOrganization' 
+  -> Text -- ^ 'organizationCreatedApiKey' 
+  -> OrganizationCreated
+mkOrganizationCreated organizationCreatedOrganization organizationCreatedApiKey =
+  OrganizationCreated
+  { organizationCreatedOrganization
+  , organizationCreatedApiKey
+  }
+
+-- ** OrganizationRecord
+-- | OrganizationRecord
+data OrganizationRecord = OrganizationRecord
+  { organizationRecordId :: !(Text) -- ^ /Required/ "id"
+  , organizationRecordName :: !(Text) -- ^ /Required/ "name"
+  , organizationRecordCreatedAt :: !(DateTime) -- ^ /Required/ "createdAt"
+  , organizationRecordUpdatedAt :: !(DateTime) -- ^ /Required/ "updatedAt"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON OrganizationRecord
+instance A.FromJSON OrganizationRecord where
+  parseJSON = A.withObject "OrganizationRecord" $ \o ->
+    OrganizationRecord
+      <$> (o .:  "id")
+      <*> (o .:  "name")
+      <*> (o .:  "createdAt")
+      <*> (o .:  "updatedAt")
+
+-- | ToJSON OrganizationRecord
+instance A.ToJSON OrganizationRecord where
+  toJSON OrganizationRecord {..} =
+   _omitNulls
+      [ "id" .= organizationRecordId
+      , "name" .= organizationRecordName
+      , "createdAt" .= organizationRecordCreatedAt
+      , "updatedAt" .= organizationRecordUpdatedAt
+      ]
+
+
+-- | Construct a value of type 'OrganizationRecord' (by applying it's required fields, if any)
+mkOrganizationRecord
+  :: Text -- ^ 'organizationRecordId' 
+  -> Text -- ^ 'organizationRecordName' 
+  -> DateTime -- ^ 'organizationRecordCreatedAt' 
+  -> DateTime -- ^ 'organizationRecordUpdatedAt' 
+  -> OrganizationRecord
+mkOrganizationRecord organizationRecordId organizationRecordName organizationRecordCreatedAt organizationRecordUpdatedAt =
+  OrganizationRecord
+  { organizationRecordId
+  , organizationRecordName
+  , organizationRecordCreatedAt
+  , organizationRecordUpdatedAt
+  }
+
+-- ** PasswordLoginInput
+-- | PasswordLoginInput
+data PasswordLoginInput = PasswordLoginInput
+  { passwordLoginInputEmail :: !(Text) -- ^ /Required/ "email"
+  , passwordLoginInputPassword :: !(Text) -- ^ /Required/ "password"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON PasswordLoginInput
+instance A.FromJSON PasswordLoginInput where
+  parseJSON = A.withObject "PasswordLoginInput" $ \o ->
+    PasswordLoginInput
+      <$> (o .:  "email")
+      <*> (o .:  "password")
+
+-- | ToJSON PasswordLoginInput
+instance A.ToJSON PasswordLoginInput where
+  toJSON PasswordLoginInput {..} =
+   _omitNulls
+      [ "email" .= passwordLoginInputEmail
+      , "password" .= passwordLoginInputPassword
+      ]
+
+
+-- | Construct a value of type 'PasswordLoginInput' (by applying it's required fields, if any)
+mkPasswordLoginInput
+  :: Text -- ^ 'passwordLoginInputEmail' 
+  -> Text -- ^ 'passwordLoginInputPassword' 
+  -> PasswordLoginInput
+mkPasswordLoginInput passwordLoginInputEmail passwordLoginInputPassword =
+  PasswordLoginInput
+  { passwordLoginInputEmail
+  , passwordLoginInputPassword
+  }
+
+-- ** PasswordResetCompleteInput
+-- | PasswordResetCompleteInput
+data PasswordResetCompleteInput = PasswordResetCompleteInput
+  { passwordResetCompleteInputToken :: !(Text) -- ^ /Required/ "token"
+  , passwordResetCompleteInputPassword :: !(Text) -- ^ /Required/ "password"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON PasswordResetCompleteInput
+instance A.FromJSON PasswordResetCompleteInput where
+  parseJSON = A.withObject "PasswordResetCompleteInput" $ \o ->
+    PasswordResetCompleteInput
+      <$> (o .:  "token")
+      <*> (o .:  "password")
+
+-- | ToJSON PasswordResetCompleteInput
+instance A.ToJSON PasswordResetCompleteInput where
+  toJSON PasswordResetCompleteInput {..} =
+   _omitNulls
+      [ "token" .= passwordResetCompleteInputToken
+      , "password" .= passwordResetCompleteInputPassword
+      ]
+
+
+-- | Construct a value of type 'PasswordResetCompleteInput' (by applying it's required fields, if any)
+mkPasswordResetCompleteInput
+  :: Text -- ^ 'passwordResetCompleteInputToken' 
+  -> Text -- ^ 'passwordResetCompleteInputPassword' 
+  -> PasswordResetCompleteInput
+mkPasswordResetCompleteInput passwordResetCompleteInputToken passwordResetCompleteInputPassword =
+  PasswordResetCompleteInput
+  { passwordResetCompleteInputToken
+  , passwordResetCompleteInputPassword
+  }
+
+-- ** PasswordResetRequestInput
+-- | PasswordResetRequestInput
+data PasswordResetRequestInput = PasswordResetRequestInput
+  { passwordResetRequestInputEmail :: !(Text) -- ^ /Required/ "email"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON PasswordResetRequestInput
+instance A.FromJSON PasswordResetRequestInput where
+  parseJSON = A.withObject "PasswordResetRequestInput" $ \o ->
+    PasswordResetRequestInput
+      <$> (o .:  "email")
+
+-- | ToJSON PasswordResetRequestInput
+instance A.ToJSON PasswordResetRequestInput where
+  toJSON PasswordResetRequestInput {..} =
+   _omitNulls
+      [ "email" .= passwordResetRequestInputEmail
+      ]
+
+
+-- | Construct a value of type 'PasswordResetRequestInput' (by applying it's required fields, if any)
+mkPasswordResetRequestInput
+  :: Text -- ^ 'passwordResetRequestInputEmail' 
+  -> PasswordResetRequestInput
+mkPasswordResetRequestInput passwordResetRequestInputEmail =
+  PasswordResetRequestInput
+  { passwordResetRequestInputEmail
+  }
+
+-- ** PreferenceRecord
+-- | PreferenceRecord
+data PreferenceRecord = PreferenceRecord
+  { preferenceRecordServiceId :: !(Text) -- ^ /Required/ "serviceId"
+  , preferenceRecordTypeKey :: !(Text) -- ^ /Required/ "typeKey"
+  , preferenceRecordEnabled :: !(Bool) -- ^ /Required/ "enabled"
+  , preferenceRecordUpdatedAt :: !(DateTime) -- ^ /Required/ "updatedAt"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON PreferenceRecord
+instance A.FromJSON PreferenceRecord where
+  parseJSON = A.withObject "PreferenceRecord" $ \o ->
+    PreferenceRecord
+      <$> (o .:  "serviceId")
+      <*> (o .:  "typeKey")
+      <*> (o .:  "enabled")
+      <*> (o .:  "updatedAt")
+
+-- | ToJSON PreferenceRecord
+instance A.ToJSON PreferenceRecord where
+  toJSON PreferenceRecord {..} =
+   _omitNulls
+      [ "serviceId" .= preferenceRecordServiceId
+      , "typeKey" .= preferenceRecordTypeKey
+      , "enabled" .= preferenceRecordEnabled
+      , "updatedAt" .= preferenceRecordUpdatedAt
+      ]
+
+
+-- | Construct a value of type 'PreferenceRecord' (by applying it's required fields, if any)
+mkPreferenceRecord
+  :: Text -- ^ 'preferenceRecordServiceId' 
+  -> Text -- ^ 'preferenceRecordTypeKey' 
+  -> Bool -- ^ 'preferenceRecordEnabled' 
+  -> DateTime -- ^ 'preferenceRecordUpdatedAt' 
+  -> PreferenceRecord
+mkPreferenceRecord preferenceRecordServiceId preferenceRecordTypeKey preferenceRecordEnabled preferenceRecordUpdatedAt =
+  PreferenceRecord
+  { preferenceRecordServiceId
+  , preferenceRecordTypeKey
+  , preferenceRecordEnabled
+  , preferenceRecordUpdatedAt
+  }
+
+-- ** ProviderLoginInput
+-- | ProviderLoginInput
+data ProviderLoginInput = ProviderLoginInput
+  { providerLoginInputIdToken :: !(Text) -- ^ /Required/ "idToken"
+  , providerLoginInputDisplayName :: !(Maybe Text) -- ^ "displayName"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON ProviderLoginInput
+instance A.FromJSON ProviderLoginInput where
+  parseJSON = A.withObject "ProviderLoginInput" $ \o ->
+    ProviderLoginInput
+      <$> (o .:  "idToken")
+      <*> (o .:? "displayName")
+
+-- | ToJSON ProviderLoginInput
+instance A.ToJSON ProviderLoginInput where
+  toJSON ProviderLoginInput {..} =
+   _omitNulls
+      [ "idToken" .= providerLoginInputIdToken
+      , "displayName" .= providerLoginInputDisplayName
+      ]
+
+
+-- | Construct a value of type 'ProviderLoginInput' (by applying it's required fields, if any)
+mkProviderLoginInput
+  :: Text -- ^ 'providerLoginInputIdToken' 
+  -> ProviderLoginInput
+mkProviderLoginInput providerLoginInputIdToken =
+  ProviderLoginInput
+  { providerLoginInputIdToken
+  , providerLoginInputDisplayName = Nothing
+  }
+
+-- ** RegisterDeviceInput
+-- | RegisterDeviceInput
+data RegisterDeviceInput = RegisterDeviceInput
+  { registerDeviceInputDeviceToken :: !(Text) -- ^ /Required/ "deviceToken"
+  , registerDeviceInputInstallationId :: !(Text) -- ^ /Required/ "installationId"
+  , registerDeviceInputEnvironment :: !(E'Environment) -- ^ /Required/ "environment"
+  , registerDeviceInputAppVersion :: !(Maybe Text) -- ^ "appVersion"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON RegisterDeviceInput
+instance A.FromJSON RegisterDeviceInput where
+  parseJSON = A.withObject "RegisterDeviceInput" $ \o ->
+    RegisterDeviceInput
+      <$> (o .:  "deviceToken")
+      <*> (o .:  "installationId")
+      <*> (o .:  "environment")
+      <*> (o .:? "appVersion")
+
+-- | ToJSON RegisterDeviceInput
+instance A.ToJSON RegisterDeviceInput where
+  toJSON RegisterDeviceInput {..} =
+   _omitNulls
+      [ "deviceToken" .= registerDeviceInputDeviceToken
+      , "installationId" .= registerDeviceInputInstallationId
+      , "environment" .= registerDeviceInputEnvironment
+      , "appVersion" .= registerDeviceInputAppVersion
+      ]
+
+
+-- | Construct a value of type 'RegisterDeviceInput' (by applying it's required fields, if any)
+mkRegisterDeviceInput
+  :: Text -- ^ 'registerDeviceInputDeviceToken' 
+  -> Text -- ^ 'registerDeviceInputInstallationId' 
+  -> E'Environment -- ^ 'registerDeviceInputEnvironment' 
+  -> RegisterDeviceInput
+mkRegisterDeviceInput registerDeviceInputDeviceToken registerDeviceInputInstallationId registerDeviceInputEnvironment =
+  RegisterDeviceInput
+  { registerDeviceInputDeviceToken
+  , registerDeviceInputInstallationId
+  , registerDeviceInputEnvironment
+  , registerDeviceInputAppVersion = Nothing
+  }
+
+-- ** RegisterInput
+-- | RegisterInput
+data RegisterInput = RegisterInput
+  { registerInputEmail :: !(Text) -- ^ /Required/ "email"
+  , registerInputPassword :: !(Text) -- ^ /Required/ "password"
+  , registerInputDisplayName :: !(Maybe Text) -- ^ "displayName"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON RegisterInput
+instance A.FromJSON RegisterInput where
+  parseJSON = A.withObject "RegisterInput" $ \o ->
+    RegisterInput
+      <$> (o .:  "email")
+      <*> (o .:  "password")
+      <*> (o .:? "displayName")
+
+-- | ToJSON RegisterInput
+instance A.ToJSON RegisterInput where
+  toJSON RegisterInput {..} =
+   _omitNulls
+      [ "email" .= registerInputEmail
+      , "password" .= registerInputPassword
+      , "displayName" .= registerInputDisplayName
+      ]
+
+
+-- | Construct a value of type 'RegisterInput' (by applying it's required fields, if any)
+mkRegisterInput
+  :: Text -- ^ 'registerInputEmail' 
+  -> Text -- ^ 'registerInputPassword' 
+  -> RegisterInput
+mkRegisterInput registerInputEmail registerInputPassword =
+  RegisterInput
+  { registerInputEmail
+  , registerInputPassword
+  , registerInputDisplayName = Nothing
+  }
+
+-- ** RegisterWebPushSubscriptionInput
+-- | RegisterWebPushSubscriptionInput
+data RegisterWebPushSubscriptionInput = RegisterWebPushSubscriptionInput
+  { registerWebPushSubscriptionInputEndpoint :: !(Text) -- ^ /Required/ "endpoint"
+  , registerWebPushSubscriptionInputKeys :: !(RegisterWebPushSubscriptionInputKeys) -- ^ /Required/ "keys"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON RegisterWebPushSubscriptionInput
+instance A.FromJSON RegisterWebPushSubscriptionInput where
+  parseJSON = A.withObject "RegisterWebPushSubscriptionInput" $ \o ->
+    RegisterWebPushSubscriptionInput
+      <$> (o .:  "endpoint")
+      <*> (o .:  "keys")
+
+-- | ToJSON RegisterWebPushSubscriptionInput
+instance A.ToJSON RegisterWebPushSubscriptionInput where
+  toJSON RegisterWebPushSubscriptionInput {..} =
+   _omitNulls
+      [ "endpoint" .= registerWebPushSubscriptionInputEndpoint
+      , "keys" .= registerWebPushSubscriptionInputKeys
+      ]
+
+
+-- | Construct a value of type 'RegisterWebPushSubscriptionInput' (by applying it's required fields, if any)
+mkRegisterWebPushSubscriptionInput
+  :: Text -- ^ 'registerWebPushSubscriptionInputEndpoint' 
+  -> RegisterWebPushSubscriptionInputKeys -- ^ 'registerWebPushSubscriptionInputKeys' 
+  -> RegisterWebPushSubscriptionInput
+mkRegisterWebPushSubscriptionInput registerWebPushSubscriptionInputEndpoint registerWebPushSubscriptionInputKeys =
+  RegisterWebPushSubscriptionInput
+  { registerWebPushSubscriptionInputEndpoint
+  , registerWebPushSubscriptionInputKeys
+  }
+
+-- ** RegisterWebPushSubscriptionInputKeys
+-- | RegisterWebPushSubscriptionInputKeys
+data RegisterWebPushSubscriptionInputKeys = RegisterWebPushSubscriptionInputKeys
+  { registerWebPushSubscriptionInputKeysP256dh :: !(Text) -- ^ /Required/ "p256dh"
+  , registerWebPushSubscriptionInputKeysAuth :: !(Text) -- ^ /Required/ "auth"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON RegisterWebPushSubscriptionInputKeys
+instance A.FromJSON RegisterWebPushSubscriptionInputKeys where
+  parseJSON = A.withObject "RegisterWebPushSubscriptionInputKeys" $ \o ->
+    RegisterWebPushSubscriptionInputKeys
+      <$> (o .:  "p256dh")
+      <*> (o .:  "auth")
+
+-- | ToJSON RegisterWebPushSubscriptionInputKeys
+instance A.ToJSON RegisterWebPushSubscriptionInputKeys where
+  toJSON RegisterWebPushSubscriptionInputKeys {..} =
+   _omitNulls
+      [ "p256dh" .= registerWebPushSubscriptionInputKeysP256dh
+      , "auth" .= registerWebPushSubscriptionInputKeysAuth
+      ]
+
+
+-- | Construct a value of type 'RegisterWebPushSubscriptionInputKeys' (by applying it's required fields, if any)
+mkRegisterWebPushSubscriptionInputKeys
+  :: Text -- ^ 'registerWebPushSubscriptionInputKeysP256dh' 
+  -> Text -- ^ 'registerWebPushSubscriptionInputKeysAuth' 
+  -> RegisterWebPushSubscriptionInputKeys
+mkRegisterWebPushSubscriptionInputKeys registerWebPushSubscriptionInputKeysP256dh registerWebPushSubscriptionInputKeysAuth =
+  RegisterWebPushSubscriptionInputKeys
+  { registerWebPushSubscriptionInputKeysP256dh
+  , registerWebPushSubscriptionInputKeysAuth
+  }
+
+-- ** RevokedResponse
+-- | RevokedResponse
+data RevokedResponse = RevokedResponse
+  { revokedResponseRevoked :: !(Bool) -- ^ /Required/ "revoked"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON RevokedResponse
+instance A.FromJSON RevokedResponse where
+  parseJSON = A.withObject "RevokedResponse" $ \o ->
+    RevokedResponse
+      <$> (o .:  "revoked")
+
+-- | ToJSON RevokedResponse
+instance A.ToJSON RevokedResponse where
+  toJSON RevokedResponse {..} =
+   _omitNulls
+      [ "revoked" .= revokedResponseRevoked
+      ]
+
+
+-- | Construct a value of type 'RevokedResponse' (by applying it's required fields, if any)
+mkRevokedResponse
+  :: Bool -- ^ 'revokedResponseRevoked' 
+  -> RevokedResponse
+mkRevokedResponse revokedResponseRevoked =
+  RevokedResponse
+  { revokedResponseRevoked
+  }
+
+-- ** SearchEventsInput
+-- | SearchEventsInput
+data SearchEventsInput = SearchEventsInput
+  { searchEventsInputFilter :: !(EventFilter) -- ^ /Required/ "filter"
+  , searchEventsInputCursor :: !(Maybe Text) -- ^ "cursor"
+  , searchEventsInputLimit :: !(Maybe Int) -- ^ "limit"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON SearchEventsInput
+instance A.FromJSON SearchEventsInput where
+  parseJSON = A.withObject "SearchEventsInput" $ \o ->
+    SearchEventsInput
+      <$> (o .:  "filter")
+      <*> (o .:? "cursor")
+      <*> (o .:? "limit")
+
+-- | ToJSON SearchEventsInput
+instance A.ToJSON SearchEventsInput where
+  toJSON SearchEventsInput {..} =
+   _omitNulls
+      [ "filter" .= searchEventsInputFilter
+      , "cursor" .= searchEventsInputCursor
+      , "limit" .= searchEventsInputLimit
+      ]
+
+
+-- | Construct a value of type 'SearchEventsInput' (by applying it's required fields, if any)
+mkSearchEventsInput
+  :: EventFilter -- ^ 'searchEventsInputFilter' 
+  -> SearchEventsInput
+mkSearchEventsInput searchEventsInputFilter =
+  SearchEventsInput
+  { searchEventsInputFilter
+  , searchEventsInputCursor = Nothing
+  , searchEventsInputLimit = Nothing
+  }
+
+-- ** SendEventInput
+-- | SendEventInput
+data SendEventInput = SendEventInput
+  { sendEventInputService :: !(Text) -- ^ /Required/ "service"
+  , sendEventInputServiceDisplayName :: !(Maybe Text) -- ^ "serviceDisplayName"
+  , sendEventInputType :: !(Text) -- ^ /Required/ "type"
+  , sendEventInputTitle :: !(Text) -- ^ /Required/ "title"
+  , sendEventInputBody :: !(Text) -- ^ /Required/ "body"
+  , sendEventInputMetadata :: !(Maybe (Map.Map String AnyType)) -- ^ "metadata"
+  , sendEventInputExternalId :: !(Maybe Text) -- ^ "externalId"
+  , sendEventInputActionUrl :: !(Maybe Text) -- ^ "actionUrl"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON SendEventInput
+instance A.FromJSON SendEventInput where
+  parseJSON = A.withObject "SendEventInput" $ \o ->
+    SendEventInput
+      <$> (o .:  "service")
+      <*> (o .:? "serviceDisplayName")
+      <*> (o .:  "type")
+      <*> (o .:  "title")
+      <*> (o .:  "body")
+      <*> (o .:? "metadata")
+      <*> (o .:? "externalId")
+      <*> (o .:? "actionUrl")
+
+-- | ToJSON SendEventInput
+instance A.ToJSON SendEventInput where
+  toJSON SendEventInput {..} =
+   _omitNulls
+      [ "service" .= sendEventInputService
+      , "serviceDisplayName" .= sendEventInputServiceDisplayName
+      , "type" .= sendEventInputType
+      , "title" .= sendEventInputTitle
+      , "body" .= sendEventInputBody
+      , "metadata" .= sendEventInputMetadata
+      , "externalId" .= sendEventInputExternalId
+      , "actionUrl" .= sendEventInputActionUrl
+      ]
+
+
+-- | Construct a value of type 'SendEventInput' (by applying it's required fields, if any)
+mkSendEventInput
+  :: Text -- ^ 'sendEventInputService' 
+  -> Text -- ^ 'sendEventInputType' 
+  -> Text -- ^ 'sendEventInputTitle' 
+  -> Text -- ^ 'sendEventInputBody' 
+  -> SendEventInput
+mkSendEventInput sendEventInputService sendEventInputType sendEventInputTitle sendEventInputBody =
+  SendEventInput
+  { sendEventInputService
+  , sendEventInputServiceDisplayName = Nothing
+  , sendEventInputType
+  , sendEventInputTitle
+  , sendEventInputBody
+  , sendEventInputMetadata = Nothing
+  , sendEventInputExternalId = Nothing
+  , sendEventInputActionUrl = Nothing
+  }
+
+-- ** Service
+-- | Service
+data Service = Service
+  { serviceId :: !(Text) -- ^ /Required/ "id"
+  , serviceName :: !(Text) -- ^ /Required/ "name"
+  , serviceDisplayName :: !(Text) -- ^ /Required/ "displayName"
+  , serviceCreatedAt :: !(DateTime) -- ^ /Required/ "createdAt"
+  , serviceCount :: !(ServiceAllOfCount) -- ^ /Required/ "_count"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON Service
+instance A.FromJSON Service where
+  parseJSON = A.withObject "Service" $ \o ->
+    Service
+      <$> (o .:  "id")
+      <*> (o .:  "name")
+      <*> (o .:  "displayName")
+      <*> (o .:  "createdAt")
+      <*> (o .:  "_count")
+
+-- | ToJSON Service
+instance A.ToJSON Service where
+  toJSON Service {..} =
+   _omitNulls
+      [ "id" .= serviceId
+      , "name" .= serviceName
+      , "displayName" .= serviceDisplayName
+      , "createdAt" .= serviceCreatedAt
+      , "_count" .= serviceCount
+      ]
+
+
+-- | Construct a value of type 'Service' (by applying it's required fields, if any)
+mkService
+  :: Text -- ^ 'serviceId' 
+  -> Text -- ^ 'serviceName' 
+  -> Text -- ^ 'serviceDisplayName' 
+  -> DateTime -- ^ 'serviceCreatedAt' 
+  -> ServiceAllOfCount -- ^ 'serviceCount' 
+  -> Service
+mkService serviceId serviceName serviceDisplayName serviceCreatedAt serviceCount =
+  Service
+  { serviceId
+  , serviceName
+  , serviceDisplayName
+  , serviceCreatedAt
+  , serviceCount
+  }
+
+-- ** ServiceAllOfCount
+-- | ServiceAllOfCount
+data ServiceAllOfCount = ServiceAllOfCount
+  { serviceAllOfCountEvents :: !(Int) -- ^ /Required/ "events"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON ServiceAllOfCount
+instance A.FromJSON ServiceAllOfCount where
+  parseJSON = A.withObject "ServiceAllOfCount" $ \o ->
+    ServiceAllOfCount
+      <$> (o .:  "events")
+
+-- | ToJSON ServiceAllOfCount
+instance A.ToJSON ServiceAllOfCount where
+  toJSON ServiceAllOfCount {..} =
+   _omitNulls
+      [ "events" .= serviceAllOfCountEvents
+      ]
+
+
+-- | Construct a value of type 'ServiceAllOfCount' (by applying it's required fields, if any)
+mkServiceAllOfCount
+  :: Int -- ^ 'serviceAllOfCountEvents' 
+  -> ServiceAllOfCount
+mkServiceAllOfCount serviceAllOfCountEvents =
+  ServiceAllOfCount
+  { serviceAllOfCountEvents
+  }
+
+-- ** ServicePreference
+-- | ServicePreference
+data ServicePreference = ServicePreference
+  { servicePreferenceId :: !(Text) -- ^ /Required/ "id"
+  , servicePreferenceName :: !(Text) -- ^ /Required/ "name"
+  , servicePreferenceDisplayName :: !(Text) -- ^ /Required/ "displayName"
+  , servicePreferenceEnabled :: !(Bool) -- ^ /Required/ "enabled"
+  , servicePreferenceTypeOverrides :: !([TypeOverride]) -- ^ /Required/ "typeOverrides"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON ServicePreference
+instance A.FromJSON ServicePreference where
+  parseJSON = A.withObject "ServicePreference" $ \o ->
+    ServicePreference
+      <$> (o .:  "id")
+      <*> (o .:  "name")
+      <*> (o .:  "displayName")
+      <*> (o .:  "enabled")
+      <*> (o .:  "typeOverrides")
+
+-- | ToJSON ServicePreference
+instance A.ToJSON ServicePreference where
+  toJSON ServicePreference {..} =
+   _omitNulls
+      [ "id" .= servicePreferenceId
+      , "name" .= servicePreferenceName
+      , "displayName" .= servicePreferenceDisplayName
+      , "enabled" .= servicePreferenceEnabled
+      , "typeOverrides" .= servicePreferenceTypeOverrides
+      ]
+
+
+-- | Construct a value of type 'ServicePreference' (by applying it's required fields, if any)
+mkServicePreference
+  :: Text -- ^ 'servicePreferenceId' 
+  -> Text -- ^ 'servicePreferenceName' 
+  -> Text -- ^ 'servicePreferenceDisplayName' 
+  -> Bool -- ^ 'servicePreferenceEnabled' 
+  -> [TypeOverride] -- ^ 'servicePreferenceTypeOverrides' 
+  -> ServicePreference
+mkServicePreference servicePreferenceId servicePreferenceName servicePreferenceDisplayName servicePreferenceEnabled servicePreferenceTypeOverrides =
+  ServicePreference
+  { servicePreferenceId
+  , servicePreferenceName
+  , servicePreferenceDisplayName
+  , servicePreferenceEnabled
+  , servicePreferenceTypeOverrides
+  }
+
+-- ** ServiceSummary
+-- | ServiceSummary
+data ServiceSummary = ServiceSummary
+  { serviceSummaryId :: !(Text) -- ^ /Required/ "id"
+  , serviceSummaryName :: !(Text) -- ^ /Required/ "name"
+  , serviceSummaryDisplayName :: !(Text) -- ^ /Required/ "displayName"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON ServiceSummary
+instance A.FromJSON ServiceSummary where
+  parseJSON = A.withObject "ServiceSummary" $ \o ->
+    ServiceSummary
+      <$> (o .:  "id")
+      <*> (o .:  "name")
+      <*> (o .:  "displayName")
+
+-- | ToJSON ServiceSummary
+instance A.ToJSON ServiceSummary where
+  toJSON ServiceSummary {..} =
+   _omitNulls
+      [ "id" .= serviceSummaryId
+      , "name" .= serviceSummaryName
+      , "displayName" .= serviceSummaryDisplayName
+      ]
+
+
+-- | Construct a value of type 'ServiceSummary' (by applying it's required fields, if any)
+mkServiceSummary
+  :: Text -- ^ 'serviceSummaryId' 
+  -> Text -- ^ 'serviceSummaryName' 
+  -> Text -- ^ 'serviceSummaryDisplayName' 
+  -> ServiceSummary
+mkServiceSummary serviceSummaryId serviceSummaryName serviceSummaryDisplayName =
+  ServiceSummary
+  { serviceSummaryId
+  , serviceSummaryName
+  , serviceSummaryDisplayName
+  }
+
+-- ** SetEnabledInput
+-- | SetEnabledInput
+data SetEnabledInput = SetEnabledInput
+  { setEnabledInputEnabled :: !(Bool) -- ^ /Required/ "enabled"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON SetEnabledInput
+instance A.FromJSON SetEnabledInput where
+  parseJSON = A.withObject "SetEnabledInput" $ \o ->
+    SetEnabledInput
+      <$> (o .:  "enabled")
+
+-- | ToJSON SetEnabledInput
+instance A.ToJSON SetEnabledInput where
+  toJSON SetEnabledInput {..} =
+   _omitNulls
+      [ "enabled" .= setEnabledInputEnabled
+      ]
+
+
+-- | Construct a value of type 'SetEnabledInput' (by applying it's required fields, if any)
+mkSetEnabledInput
+  :: Bool -- ^ 'setEnabledInputEnabled' 
+  -> SetEnabledInput
+mkSetEnabledInput setEnabledInputEnabled =
+  SetEnabledInput
+  { setEnabledInputEnabled
+  }
+
+-- ** TextFilterCondition
+-- | TextFilterCondition
+data TextFilterCondition = TextFilterCondition
+  { textFilterConditionField :: !(E'Field2) -- ^ /Required/ "field"
+  , textFilterConditionComparison :: !(E'Comparison2) -- ^ /Required/ "comparison"
+  , textFilterConditionValue :: !(Text) -- ^ /Required/ "value"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON TextFilterCondition
+instance A.FromJSON TextFilterCondition where
+  parseJSON = A.withObject "TextFilterCondition" $ \o ->
+    TextFilterCondition
+      <$> (o .:  "field")
+      <*> (o .:  "comparison")
+      <*> (o .:  "value")
+
+-- | ToJSON TextFilterCondition
+instance A.ToJSON TextFilterCondition where
+  toJSON TextFilterCondition {..} =
+   _omitNulls
+      [ "field" .= textFilterConditionField
+      , "comparison" .= textFilterConditionComparison
+      , "value" .= textFilterConditionValue
+      ]
+
+
+-- | Construct a value of type 'TextFilterCondition' (by applying it's required fields, if any)
+mkTextFilterCondition
+  :: E'Field2 -- ^ 'textFilterConditionField' 
+  -> E'Comparison2 -- ^ 'textFilterConditionComparison' 
+  -> Text -- ^ 'textFilterConditionValue' 
+  -> TextFilterCondition
+mkTextFilterCondition textFilterConditionField textFilterConditionComparison textFilterConditionValue =
+  TextFilterCondition
+  { textFilterConditionField
+  , textFilterConditionComparison
+  , textFilterConditionValue
+  }
+
+-- ** TimeFilterCondition
+-- | TimeFilterCondition
+data TimeFilterCondition = TimeFilterCondition
+  { timeFilterConditionField :: !(E'Field) -- ^ /Required/ "field"
+  , timeFilterConditionComparison :: !(E'Comparison) -- ^ /Required/ "comparison"
+  , timeFilterConditionValue :: !(DateTime) -- ^ /Required/ "value"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON TimeFilterCondition
+instance A.FromJSON TimeFilterCondition where
+  parseJSON = A.withObject "TimeFilterCondition" $ \o ->
+    TimeFilterCondition
+      <$> (o .:  "field")
+      <*> (o .:  "comparison")
+      <*> (o .:  "value")
+
+-- | ToJSON TimeFilterCondition
+instance A.ToJSON TimeFilterCondition where
+  toJSON TimeFilterCondition {..} =
+   _omitNulls
+      [ "field" .= timeFilterConditionField
+      , "comparison" .= timeFilterConditionComparison
+      , "value" .= timeFilterConditionValue
+      ]
+
+
+-- | Construct a value of type 'TimeFilterCondition' (by applying it's required fields, if any)
+mkTimeFilterCondition
+  :: E'Field -- ^ 'timeFilterConditionField' 
+  -> E'Comparison -- ^ 'timeFilterConditionComparison' 
+  -> DateTime -- ^ 'timeFilterConditionValue' 
+  -> TimeFilterCondition
+mkTimeFilterCondition timeFilterConditionField timeFilterConditionComparison timeFilterConditionValue =
+  TimeFilterCondition
+  { timeFilterConditionField
+  , timeFilterConditionComparison
+  , timeFilterConditionValue
+  }
+
+-- ** TypeOverride
+-- | TypeOverride
+data TypeOverride = TypeOverride
+  { typeOverrideType :: !(Text) -- ^ /Required/ "type"
+  , typeOverrideEnabled :: !(Bool) -- ^ /Required/ "enabled"
+  , typeOverrideUpdatedAt :: !(DateTime) -- ^ /Required/ "updatedAt"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON TypeOverride
+instance A.FromJSON TypeOverride where
+  parseJSON = A.withObject "TypeOverride" $ \o ->
+    TypeOverride
+      <$> (o .:  "type")
+      <*> (o .:  "enabled")
+      <*> (o .:  "updatedAt")
+
+-- | ToJSON TypeOverride
+instance A.ToJSON TypeOverride where
+  toJSON TypeOverride {..} =
+   _omitNulls
+      [ "type" .= typeOverrideType
+      , "enabled" .= typeOverrideEnabled
+      , "updatedAt" .= typeOverrideUpdatedAt
+      ]
+
+
+-- | Construct a value of type 'TypeOverride' (by applying it's required fields, if any)
+mkTypeOverride
+  :: Text -- ^ 'typeOverrideType' 
+  -> Bool -- ^ 'typeOverrideEnabled' 
+  -> DateTime -- ^ 'typeOverrideUpdatedAt' 
+  -> TypeOverride
+mkTypeOverride typeOverrideType typeOverrideEnabled typeOverrideUpdatedAt =
+  TypeOverride
+  { typeOverrideType
+  , typeOverrideEnabled
+  , typeOverrideUpdatedAt
+  }
+
+-- ** User
+-- | User
+data User = User
+  { userId :: !(Text) -- ^ /Required/ "id"
+  , userEmail :: !(Text) -- ^ /Required/ "email"
+  , userDisplayName :: !(Maybe Text) -- ^ "displayName"
+  , userHasPassword :: !(Bool) -- ^ /Required/ "hasPassword"
+  , userHasGoogle :: !(Bool) -- ^ /Required/ "hasGoogle"
+  , userHasApple :: !(Bool) -- ^ /Required/ "hasApple"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON User
+instance A.FromJSON User where
+  parseJSON = A.withObject "User" $ \o ->
+    User
+      <$> (o .:  "id")
+      <*> (o .:  "email")
+      <*> (o .:? "displayName")
+      <*> (o .:  "hasPassword")
+      <*> (o .:  "hasGoogle")
+      <*> (o .:  "hasApple")
+
+-- | ToJSON User
+instance A.ToJSON User where
+  toJSON User {..} =
+   _omitNulls
+      [ "id" .= userId
+      , "email" .= userEmail
+      , "displayName" .= userDisplayName
+      , "hasPassword" .= userHasPassword
+      , "hasGoogle" .= userHasGoogle
+      , "hasApple" .= userHasApple
+      ]
+
+
+-- | Construct a value of type 'User' (by applying it's required fields, if any)
+mkUser
+  :: Text -- ^ 'userId' 
+  -> Text -- ^ 'userEmail' 
+  -> Bool -- ^ 'userHasPassword' 
+  -> Bool -- ^ 'userHasGoogle' 
+  -> Bool -- ^ 'userHasApple' 
+  -> User
+mkUser userId userEmail userHasPassword userHasGoogle userHasApple =
+  User
+  { userId
+  , userEmail
+  , userDisplayName = Nothing
+  , userHasPassword
+  , userHasGoogle
+  , userHasApple
+  }
+
+-- ** WebPushConfiguration
+-- | WebPushConfiguration
+data WebPushConfiguration = WebPushConfiguration
+  { webPushConfigurationEnabled :: !(Bool) -- ^ /Required/ "enabled"
+  , webPushConfigurationPublicKey :: !(Maybe Text) -- ^ "publicKey"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON WebPushConfiguration
+instance A.FromJSON WebPushConfiguration where
+  parseJSON = A.withObject "WebPushConfiguration" $ \o ->
+    WebPushConfiguration
+      <$> (o .:  "enabled")
+      <*> (o .:? "publicKey")
+
+-- | ToJSON WebPushConfiguration
+instance A.ToJSON WebPushConfiguration where
+  toJSON WebPushConfiguration {..} =
+   _omitNulls
+      [ "enabled" .= webPushConfigurationEnabled
+      , "publicKey" .= webPushConfigurationPublicKey
+      ]
+
+
+-- | Construct a value of type 'WebPushConfiguration' (by applying it's required fields, if any)
+mkWebPushConfiguration
+  :: Bool -- ^ 'webPushConfigurationEnabled' 
+  -> WebPushConfiguration
+mkWebPushConfiguration webPushConfigurationEnabled =
+  WebPushConfiguration
+  { webPushConfigurationEnabled
+  , webPushConfigurationPublicKey = Nothing
+  }
+
+-- ** WebPushSubscription
+-- | WebPushSubscription
+data WebPushSubscription = WebPushSubscription
+  { webPushSubscriptionId :: !(Text) -- ^ /Required/ "id"
+  , webPushSubscriptionEnabled :: !(Bool) -- ^ /Required/ "enabled"
+  , webPushSubscriptionLastSeenAt :: !(DateTime) -- ^ /Required/ "lastSeenAt"
+  } deriving (P.Show, P.Eq, P.Typeable)
+
+-- | FromJSON WebPushSubscription
+instance A.FromJSON WebPushSubscription where
+  parseJSON = A.withObject "WebPushSubscription" $ \o ->
+    WebPushSubscription
+      <$> (o .:  "id")
+      <*> (o .:  "enabled")
+      <*> (o .:  "lastSeenAt")
+
+-- | ToJSON WebPushSubscription
+instance A.ToJSON WebPushSubscription where
+  toJSON WebPushSubscription {..} =
+   _omitNulls
+      [ "id" .= webPushSubscriptionId
+      , "enabled" .= webPushSubscriptionEnabled
+      , "lastSeenAt" .= webPushSubscriptionLastSeenAt
+      ]
+
+
+-- | Construct a value of type 'WebPushSubscription' (by applying it's required fields, if any)
+mkWebPushSubscription
+  :: Text -- ^ 'webPushSubscriptionId' 
+  -> Bool -- ^ 'webPushSubscriptionEnabled' 
+  -> DateTime -- ^ 'webPushSubscriptionLastSeenAt' 
+  -> WebPushSubscription
+mkWebPushSubscription webPushSubscriptionId webPushSubscriptionEnabled webPushSubscriptionLastSeenAt =
+  WebPushSubscription
+  { webPushSubscriptionId
+  , webPushSubscriptionEnabled
+  , webPushSubscriptionLastSeenAt
+  }
+
+
+-- * Enums
+
+
+-- ** E'Comparison
+
+-- | Enum of 'Text'
+data E'Comparison
+  = E'Comparison'Before -- ^ @"before"@
+  | E'Comparison'After -- ^ @"after"@
+  | E'Comparison'OnOrBefore -- ^ @"onOrBefore"@
+  | E'Comparison'OnOrAfter -- ^ @"onOrAfter"@
+  | E'Comparison'Equals -- ^ @"equals"@
+  deriving (P.Show, P.Eq, P.Typeable, P.Ord, P.Bounded, P.Enum)
+
+instance A.ToJSON E'Comparison where toJSON = A.toJSON . fromE'Comparison
+instance A.FromJSON E'Comparison where parseJSON o = P.either P.fail (pure . P.id) . toE'Comparison =<< A.parseJSON o
+instance WH.ToHttpApiData E'Comparison where toQueryParam = WH.toQueryParam . fromE'Comparison
+instance WH.FromHttpApiData E'Comparison where parseQueryParam o = WH.parseQueryParam o >>= P.left T.pack . toE'Comparison
+instance MimeRender MimeMultipartFormData E'Comparison where mimeRender _ = mimeRenderDefaultMultipartFormData
+
+-- | unwrap 'E'Comparison' enum
+fromE'Comparison :: E'Comparison -> Text
+fromE'Comparison = \case
+  E'Comparison'Before -> "before"
+  E'Comparison'After -> "after"
+  E'Comparison'OnOrBefore -> "onOrBefore"
+  E'Comparison'OnOrAfter -> "onOrAfter"
+  E'Comparison'Equals -> "equals"
+
+-- | parse 'E'Comparison' enum
+toE'Comparison :: Text -> P.Either String E'Comparison
+toE'Comparison = \case
+  "before" -> P.Right E'Comparison'Before
+  "after" -> P.Right E'Comparison'After
+  "onOrBefore" -> P.Right E'Comparison'OnOrBefore
+  "onOrAfter" -> P.Right E'Comparison'OnOrAfter
+  "equals" -> P.Right E'Comparison'Equals
+  s -> P.Left $ "toE'Comparison: enum parse failure: " P.++ P.show s
+
+
+-- ** E'Comparison2
+
+-- | Enum of 'Text'
+data E'Comparison2
+  = E'Comparison2'Equals -- ^ @"equals"@
+  | E'Comparison2'Contains -- ^ @"contains"@
+  deriving (P.Show, P.Eq, P.Typeable, P.Ord, P.Bounded, P.Enum)
+
+instance A.ToJSON E'Comparison2 where toJSON = A.toJSON . fromE'Comparison2
+instance A.FromJSON E'Comparison2 where parseJSON o = P.either P.fail (pure . P.id) . toE'Comparison2 =<< A.parseJSON o
+instance WH.ToHttpApiData E'Comparison2 where toQueryParam = WH.toQueryParam . fromE'Comparison2
+instance WH.FromHttpApiData E'Comparison2 where parseQueryParam o = WH.parseQueryParam o >>= P.left T.pack . toE'Comparison2
+instance MimeRender MimeMultipartFormData E'Comparison2 where mimeRender _ = mimeRenderDefaultMultipartFormData
+
+-- | unwrap 'E'Comparison2' enum
+fromE'Comparison2 :: E'Comparison2 -> Text
+fromE'Comparison2 = \case
+  E'Comparison2'Equals -> "equals"
+  E'Comparison2'Contains -> "contains"
+
+-- | parse 'E'Comparison2' enum
+toE'Comparison2 :: Text -> P.Either String E'Comparison2
+toE'Comparison2 = \case
+  "equals" -> P.Right E'Comparison2'Equals
+  "contains" -> P.Right E'Comparison2'Contains
+  s -> P.Left $ "toE'Comparison2: enum parse failure: " P.++ P.show s
+
+
+-- ** E'Environment
+
+-- | Enum of 'Text'
+data E'Environment
+  = E'Environment'SANDBOX -- ^ @"SANDBOX"@
+  | E'Environment'PRODUCTION -- ^ @"PRODUCTION"@
+  deriving (P.Show, P.Eq, P.Typeable, P.Ord, P.Bounded, P.Enum)
+
+instance A.ToJSON E'Environment where toJSON = A.toJSON . fromE'Environment
+instance A.FromJSON E'Environment where parseJSON o = P.either P.fail (pure . P.id) . toE'Environment =<< A.parseJSON o
+instance WH.ToHttpApiData E'Environment where toQueryParam = WH.toQueryParam . fromE'Environment
+instance WH.FromHttpApiData E'Environment where parseQueryParam o = WH.parseQueryParam o >>= P.left T.pack . toE'Environment
+instance MimeRender MimeMultipartFormData E'Environment where mimeRender _ = mimeRenderDefaultMultipartFormData
+
+-- | unwrap 'E'Environment' enum
+fromE'Environment :: E'Environment -> Text
+fromE'Environment = \case
+  E'Environment'SANDBOX -> "SANDBOX"
+  E'Environment'PRODUCTION -> "PRODUCTION"
+
+-- | parse 'E'Environment' enum
+toE'Environment :: Text -> P.Either String E'Environment
+toE'Environment = \case
+  "SANDBOX" -> P.Right E'Environment'SANDBOX
+  "PRODUCTION" -> P.Right E'Environment'PRODUCTION
+  s -> P.Left $ "toE'Environment: enum parse failure: " P.++ P.show s
+
+
+-- ** E'Field
+
+-- | Enum of 'Text'
+data E'Field
+  = E'Field'CreatedAt -- ^ @"createdAt"@
+  deriving (P.Show, P.Eq, P.Typeable, P.Ord, P.Bounded, P.Enum)
+
+instance A.ToJSON E'Field where toJSON = A.toJSON . fromE'Field
+instance A.FromJSON E'Field where parseJSON o = P.either P.fail (pure . P.id) . toE'Field =<< A.parseJSON o
+instance WH.ToHttpApiData E'Field where toQueryParam = WH.toQueryParam . fromE'Field
+instance WH.FromHttpApiData E'Field where parseQueryParam o = WH.parseQueryParam o >>= P.left T.pack . toE'Field
+instance MimeRender MimeMultipartFormData E'Field where mimeRender _ = mimeRenderDefaultMultipartFormData
+
+-- | unwrap 'E'Field' enum
+fromE'Field :: E'Field -> Text
+fromE'Field = \case
+  E'Field'CreatedAt -> "createdAt"
+
+-- | parse 'E'Field' enum
+toE'Field :: Text -> P.Either String E'Field
+toE'Field = \case
+  "createdAt" -> P.Right E'Field'CreatedAt
+  s -> P.Left $ "toE'Field: enum parse failure: " P.++ P.show s
+
+
+-- ** E'Field2
+
+-- | Enum of 'Text'
+data E'Field2
+  = E'Field2'Service -- ^ @"service"@
+  | E'Field2'Type -- ^ @"type"@
+  | E'Field2'Title -- ^ @"title"@
+  | E'Field2'Body -- ^ @"body"@
+  deriving (P.Show, P.Eq, P.Typeable, P.Ord, P.Bounded, P.Enum)
+
+instance A.ToJSON E'Field2 where toJSON = A.toJSON . fromE'Field2
+instance A.FromJSON E'Field2 where parseJSON o = P.either P.fail (pure . P.id) . toE'Field2 =<< A.parseJSON o
+instance WH.ToHttpApiData E'Field2 where toQueryParam = WH.toQueryParam . fromE'Field2
+instance WH.FromHttpApiData E'Field2 where parseQueryParam o = WH.parseQueryParam o >>= P.left T.pack . toE'Field2
+instance MimeRender MimeMultipartFormData E'Field2 where mimeRender _ = mimeRenderDefaultMultipartFormData
+
+-- | unwrap 'E'Field2' enum
+fromE'Field2 :: E'Field2 -> Text
+fromE'Field2 = \case
+  E'Field2'Service -> "service"
+  E'Field2'Type -> "type"
+  E'Field2'Title -> "title"
+  E'Field2'Body -> "body"
+
+-- | parse 'E'Field2' enum
+toE'Field2 :: Text -> P.Either String E'Field2
+toE'Field2 = \case
+  "service" -> P.Right E'Field2'Service
+  "type" -> P.Right E'Field2'Type
+  "title" -> P.Right E'Field2'Title
+  "body" -> P.Right E'Field2'Body
+  s -> P.Left $ "toE'Field2: enum parse failure: " P.++ P.show s
+
+
+-- ** E'Operator
+
+-- | Enum of 'Text'
+data E'Operator
+  = E'Operator'NOT -- ^ @"NOT"@
+  deriving (P.Show, P.Eq, P.Typeable, P.Ord, P.Bounded, P.Enum)
+
+instance A.ToJSON E'Operator where toJSON = A.toJSON . fromE'Operator
+instance A.FromJSON E'Operator where parseJSON o = P.either P.fail (pure . P.id) . toE'Operator =<< A.parseJSON o
+instance WH.ToHttpApiData E'Operator where toQueryParam = WH.toQueryParam . fromE'Operator
+instance WH.FromHttpApiData E'Operator where parseQueryParam o = WH.parseQueryParam o >>= P.left T.pack . toE'Operator
+instance MimeRender MimeMultipartFormData E'Operator where mimeRender _ = mimeRenderDefaultMultipartFormData
+
+-- | unwrap 'E'Operator' enum
+fromE'Operator :: E'Operator -> Text
+fromE'Operator = \case
+  E'Operator'NOT -> "NOT"
+
+-- | parse 'E'Operator' enum
+toE'Operator :: Text -> P.Either String E'Operator
+toE'Operator = \case
+  "NOT" -> P.Right E'Operator'NOT
+  s -> P.Left $ "toE'Operator: enum parse failure: " P.++ P.show s
+
+
+-- ** E'Operator2
+
+-- | Enum of 'Text'
+data E'Operator2
+  = E'Operator2'AND -- ^ @"AND"@
+  | E'Operator2'OR -- ^ @"OR"@
+  deriving (P.Show, P.Eq, P.Typeable, P.Ord, P.Bounded, P.Enum)
+
+instance A.ToJSON E'Operator2 where toJSON = A.toJSON . fromE'Operator2
+instance A.FromJSON E'Operator2 where parseJSON o = P.either P.fail (pure . P.id) . toE'Operator2 =<< A.parseJSON o
+instance WH.ToHttpApiData E'Operator2 where toQueryParam = WH.toQueryParam . fromE'Operator2
+instance WH.FromHttpApiData E'Operator2 where parseQueryParam o = WH.parseQueryParam o >>= P.left T.pack . toE'Operator2
+instance MimeRender MimeMultipartFormData E'Operator2 where mimeRender _ = mimeRenderDefaultMultipartFormData
+
+-- | unwrap 'E'Operator2' enum
+fromE'Operator2 :: E'Operator2 -> Text
+fromE'Operator2 = \case
+  E'Operator2'AND -> "AND"
+  E'Operator2'OR -> "OR"
+
+-- | parse 'E'Operator2' enum
+toE'Operator2 :: Text -> P.Either String E'Operator2
+toE'Operator2 = \case
+  "AND" -> P.Right E'Operator2'AND
+  "OR" -> P.Right E'Operator2'OR
+  s -> P.Left $ "toE'Operator2: enum parse failure: " P.++ P.show s
+
+
+-- ** E'Role
+
+-- | Enum of 'Text'
+data E'Role
+  = E'Role'OWNER -- ^ @"OWNER"@
+  | E'Role'MEMBER -- ^ @"MEMBER"@
+  deriving (P.Show, P.Eq, P.Typeable, P.Ord, P.Bounded, P.Enum)
+
+instance A.ToJSON E'Role where toJSON = A.toJSON . fromE'Role
+instance A.FromJSON E'Role where parseJSON o = P.either P.fail (pure . P.id) . toE'Role =<< A.parseJSON o
+instance WH.ToHttpApiData E'Role where toQueryParam = WH.toQueryParam . fromE'Role
+instance WH.FromHttpApiData E'Role where parseQueryParam o = WH.parseQueryParam o >>= P.left T.pack . toE'Role
+instance MimeRender MimeMultipartFormData E'Role where mimeRender _ = mimeRenderDefaultMultipartFormData
+
+-- | unwrap 'E'Role' enum
+fromE'Role :: E'Role -> Text
+fromE'Role = \case
+  E'Role'OWNER -> "OWNER"
+  E'Role'MEMBER -> "MEMBER"
+
+-- | parse 'E'Role' enum
+toE'Role :: Text -> P.Either String E'Role
+toE'Role = \case
+  "OWNER" -> P.Right E'Role'OWNER
+  "MEMBER" -> P.Right E'Role'MEMBER
+  s -> P.Left $ "toE'Role: enum parse failure: " P.++ P.show s
+
+
+-- ** E'Service
+
+-- | Enum of 'Text'
+data E'Service
+  = E'Service'Agent_push_kit -- ^ @"agent-push-kit"@
+  deriving (P.Show, P.Eq, P.Typeable, P.Ord, P.Bounded, P.Enum)
+
+instance A.ToJSON E'Service where toJSON = A.toJSON . fromE'Service
+instance A.FromJSON E'Service where parseJSON o = P.either P.fail (pure . P.id) . toE'Service =<< A.parseJSON o
+instance WH.ToHttpApiData E'Service where toQueryParam = WH.toQueryParam . fromE'Service
+instance WH.FromHttpApiData E'Service where parseQueryParam o = WH.parseQueryParam o >>= P.left T.pack . toE'Service
+instance MimeRender MimeMultipartFormData E'Service where mimeRender _ = mimeRenderDefaultMultipartFormData
+
+-- | unwrap 'E'Service' enum
+fromE'Service :: E'Service -> Text
+fromE'Service = \case
+  E'Service'Agent_push_kit -> "agent-push-kit"
+
+-- | parse 'E'Service' enum
+toE'Service :: Text -> P.Either String E'Service
+toE'Service = \case
+  "agent-push-kit" -> P.Right E'Service'Agent_push_kit
+  s -> P.Left $ "toE'Service: enum parse failure: " P.++ P.show s
+
+
+-- ** E'Status
+
+-- | Enum of 'Text'
+data E'Status
+  = E'Status'Ok -- ^ @"ok"@
+  deriving (P.Show, P.Eq, P.Typeable, P.Ord, P.Bounded, P.Enum)
+
+instance A.ToJSON E'Status where toJSON = A.toJSON . fromE'Status
+instance A.FromJSON E'Status where parseJSON o = P.either P.fail (pure . P.id) . toE'Status =<< A.parseJSON o
+instance WH.ToHttpApiData E'Status where toQueryParam = WH.toQueryParam . fromE'Status
+instance WH.FromHttpApiData E'Status where parseQueryParam o = WH.parseQueryParam o >>= P.left T.pack . toE'Status
+instance MimeRender MimeMultipartFormData E'Status where mimeRender _ = mimeRenderDefaultMultipartFormData
+
+-- | unwrap 'E'Status' enum
+fromE'Status :: E'Status -> Text
+fromE'Status = \case
+  E'Status'Ok -> "ok"
+
+-- | parse 'E'Status' enum
+toE'Status :: Text -> P.Either String E'Status
+toE'Status = \case
+  "ok" -> P.Right E'Status'Ok
+  s -> P.Left $ "toE'Status: enum parse failure: " P.++ P.show s
+
+
+-- * Auth Methods
+
+
diff --git a/lib/AgentPushKit/ModelLens.hs b/lib/AgentPushKit/ModelLens.hs
new file mode 100644
--- /dev/null
+++ b/lib/AgentPushKit/ModelLens.hs
@@ -0,0 +1,1124 @@
+{-
+   Agent Push Kit API
+
+   The complete Agent Push Kit REST API. Application event ingestion uses an organization key beginning with `apk_`. Authenticated user operations accept either an Agent Push Kit login JWT or an agent access token beginning with `apt_`.
+
+   OpenAPI Version: 3.1.0
+   Agent Push Kit API API version: 0.1.0
+   Generated by OpenAPI Generator (https://openapi-generator.tech)
+-}
+
+{-|
+Module : AgentPushKit.Lens
+-}
+
+{-# LANGUAGE KindSignatures #-}
+{-# LANGUAGE NamedFieldPuns #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# OPTIONS_GHC -fno-warn-name-shadowing -fno-warn-unused-matches -fno-warn-unused-binds -fno-warn-unused-imports #-}
+
+module AgentPushKit.ModelLens where
+
+import qualified Data.Aeson as A
+import qualified Data.ByteString.Lazy as BL
+import qualified Data.Data as P (Data, Typeable)
+import qualified Data.Map as Map
+import qualified Data.Set as Set
+import qualified Data.Time as TI
+
+import Data.Text (Text)
+
+import Prelude (($), (.),(<$>),(<*>),(=<<),Maybe(..),Bool(..),Char,Double,FilePath,Float,Int,Integer,String,fmap,undefined,mempty,maybe,pure,Monad,Applicative,Functor)
+import qualified Prelude as P
+
+import AgentPushKit.Model
+import AgentPushKit.Core
+
+
+-- * AcceptedResponse
+
+-- | 'acceptedResponseAccepted' Lens
+acceptedResponseAcceptedL :: Lens_' AcceptedResponse (Bool)
+acceptedResponseAcceptedL f AcceptedResponse{..} = (\acceptedResponseAccepted -> AcceptedResponse { acceptedResponseAccepted, ..} ) <$> f acceptedResponseAccepted
+{-# INLINE acceptedResponseAcceptedL #-}
+
+
+
+-- * AddMemberInput
+
+-- | 'addMemberInputEmail' Lens
+addMemberInputEmailL :: Lens_' AddMemberInput (Text)
+addMemberInputEmailL f AddMemberInput{..} = (\addMemberInputEmail -> AddMemberInput { addMemberInputEmail, ..} ) <$> f addMemberInputEmail
+{-# INLINE addMemberInputEmailL #-}
+
+
+
+-- * AgentToken
+
+-- | 'agentTokenId' Lens
+agentTokenIdL :: Lens_' AgentToken (Text)
+agentTokenIdL f AgentToken{..} = (\agentTokenId -> AgentToken { agentTokenId, ..} ) <$> f agentTokenId
+{-# INLINE agentTokenIdL #-}
+
+-- | 'agentTokenName' Lens
+agentTokenNameL :: Lens_' AgentToken (Text)
+agentTokenNameL f AgentToken{..} = (\agentTokenName -> AgentToken { agentTokenName, ..} ) <$> f agentTokenName
+{-# INLINE agentTokenNameL #-}
+
+-- | 'agentTokenKeyPrefix' Lens
+agentTokenKeyPrefixL :: Lens_' AgentToken (Text)
+agentTokenKeyPrefixL f AgentToken{..} = (\agentTokenKeyPrefix -> AgentToken { agentTokenKeyPrefix, ..} ) <$> f agentTokenKeyPrefix
+{-# INLINE agentTokenKeyPrefixL #-}
+
+-- | 'agentTokenLastFour' Lens
+agentTokenLastFourL :: Lens_' AgentToken (Text)
+agentTokenLastFourL f AgentToken{..} = (\agentTokenLastFour -> AgentToken { agentTokenLastFour, ..} ) <$> f agentTokenLastFour
+{-# INLINE agentTokenLastFourL #-}
+
+-- | 'agentTokenCreatedAt' Lens
+agentTokenCreatedAtL :: Lens_' AgentToken (DateTime)
+agentTokenCreatedAtL f AgentToken{..} = (\agentTokenCreatedAt -> AgentToken { agentTokenCreatedAt, ..} ) <$> f agentTokenCreatedAt
+{-# INLINE agentTokenCreatedAtL #-}
+
+-- | 'agentTokenLastUsedAt' Lens
+agentTokenLastUsedAtL :: Lens_' AgentToken (Maybe DateTime)
+agentTokenLastUsedAtL f AgentToken{..} = (\agentTokenLastUsedAt -> AgentToken { agentTokenLastUsedAt, ..} ) <$> f agentTokenLastUsedAt
+{-# INLINE agentTokenLastUsedAtL #-}
+
+-- | 'agentTokenRevokedAt' Lens
+agentTokenRevokedAtL :: Lens_' AgentToken (Maybe DateTime)
+agentTokenRevokedAtL f AgentToken{..} = (\agentTokenRevokedAt -> AgentToken { agentTokenRevokedAt, ..} ) <$> f agentTokenRevokedAt
+{-# INLINE agentTokenRevokedAtL #-}
+
+
+
+-- * AgentTokenCreated
+
+-- | 'agentTokenCreatedId' Lens
+agentTokenCreatedIdL :: Lens_' AgentTokenCreated (Text)
+agentTokenCreatedIdL f AgentTokenCreated{..} = (\agentTokenCreatedId -> AgentTokenCreated { agentTokenCreatedId, ..} ) <$> f agentTokenCreatedId
+{-# INLINE agentTokenCreatedIdL #-}
+
+-- | 'agentTokenCreatedName' Lens
+agentTokenCreatedNameL :: Lens_' AgentTokenCreated (Text)
+agentTokenCreatedNameL f AgentTokenCreated{..} = (\agentTokenCreatedName -> AgentTokenCreated { agentTokenCreatedName, ..} ) <$> f agentTokenCreatedName
+{-# INLINE agentTokenCreatedNameL #-}
+
+-- | 'agentTokenCreatedKeyPrefix' Lens
+agentTokenCreatedKeyPrefixL :: Lens_' AgentTokenCreated (Text)
+agentTokenCreatedKeyPrefixL f AgentTokenCreated{..} = (\agentTokenCreatedKeyPrefix -> AgentTokenCreated { agentTokenCreatedKeyPrefix, ..} ) <$> f agentTokenCreatedKeyPrefix
+{-# INLINE agentTokenCreatedKeyPrefixL #-}
+
+-- | 'agentTokenCreatedLastFour' Lens
+agentTokenCreatedLastFourL :: Lens_' AgentTokenCreated (Text)
+agentTokenCreatedLastFourL f AgentTokenCreated{..} = (\agentTokenCreatedLastFour -> AgentTokenCreated { agentTokenCreatedLastFour, ..} ) <$> f agentTokenCreatedLastFour
+{-# INLINE agentTokenCreatedLastFourL #-}
+
+-- | 'agentTokenCreatedCreatedAt' Lens
+agentTokenCreatedCreatedAtL :: Lens_' AgentTokenCreated (DateTime)
+agentTokenCreatedCreatedAtL f AgentTokenCreated{..} = (\agentTokenCreatedCreatedAt -> AgentTokenCreated { agentTokenCreatedCreatedAt, ..} ) <$> f agentTokenCreatedCreatedAt
+{-# INLINE agentTokenCreatedCreatedAtL #-}
+
+-- | 'agentTokenCreatedLastUsedAt' Lens
+agentTokenCreatedLastUsedAtL :: Lens_' AgentTokenCreated (Maybe DateTime)
+agentTokenCreatedLastUsedAtL f AgentTokenCreated{..} = (\agentTokenCreatedLastUsedAt -> AgentTokenCreated { agentTokenCreatedLastUsedAt, ..} ) <$> f agentTokenCreatedLastUsedAt
+{-# INLINE agentTokenCreatedLastUsedAtL #-}
+
+-- | 'agentTokenCreatedRevokedAt' Lens
+agentTokenCreatedRevokedAtL :: Lens_' AgentTokenCreated (Maybe DateTime)
+agentTokenCreatedRevokedAtL f AgentTokenCreated{..} = (\agentTokenCreatedRevokedAt -> AgentTokenCreated { agentTokenCreatedRevokedAt, ..} ) <$> f agentTokenCreatedRevokedAt
+{-# INLINE agentTokenCreatedRevokedAtL #-}
+
+-- | 'agentTokenCreatedToken' Lens
+agentTokenCreatedTokenL :: Lens_' AgentTokenCreated (Text)
+agentTokenCreatedTokenL f AgentTokenCreated{..} = (\agentTokenCreatedToken -> AgentTokenCreated { agentTokenCreatedToken, ..} ) <$> f agentTokenCreatedToken
+{-# INLINE agentTokenCreatedTokenL #-}
+
+
+
+-- * ApiKeySummary
+
+-- | 'apiKeySummaryKeyPrefix' Lens
+apiKeySummaryKeyPrefixL :: Lens_' ApiKeySummary (Maybe Text)
+apiKeySummaryKeyPrefixL f ApiKeySummary{..} = (\apiKeySummaryKeyPrefix -> ApiKeySummary { apiKeySummaryKeyPrefix, ..} ) <$> f apiKeySummaryKeyPrefix
+{-# INLINE apiKeySummaryKeyPrefixL #-}
+
+-- | 'apiKeySummaryLastFour' Lens
+apiKeySummaryLastFourL :: Lens_' ApiKeySummary (Maybe Text)
+apiKeySummaryLastFourL f ApiKeySummary{..} = (\apiKeySummaryLastFour -> ApiKeySummary { apiKeySummaryLastFour, ..} ) <$> f apiKeySummaryLastFour
+{-# INLINE apiKeySummaryLastFourL #-}
+
+-- | 'apiKeySummaryUpdatedAt' Lens
+apiKeySummaryUpdatedAtL :: Lens_' ApiKeySummary (Maybe DateTime)
+apiKeySummaryUpdatedAtL f ApiKeySummary{..} = (\apiKeySummaryUpdatedAt -> ApiKeySummary { apiKeySummaryUpdatedAt, ..} ) <$> f apiKeySummaryUpdatedAt
+{-# INLINE apiKeySummaryUpdatedAtL #-}
+
+
+
+-- * AuthResponse
+
+-- | 'authResponseAccessToken' Lens
+authResponseAccessTokenL :: Lens_' AuthResponse (Text)
+authResponseAccessTokenL f AuthResponse{..} = (\authResponseAccessToken -> AuthResponse { authResponseAccessToken, ..} ) <$> f authResponseAccessToken
+{-# INLINE authResponseAccessTokenL #-}
+
+-- | 'authResponseUser' Lens
+authResponseUserL :: Lens_' AuthResponse (User)
+authResponseUserL f AuthResponse{..} = (\authResponseUser -> AuthResponse { authResponseUser, ..} ) <$> f authResponseUser
+{-# INLINE authResponseUserL #-}
+
+-- | 'authResponseOrganizations' Lens
+authResponseOrganizationsL :: Lens_' AuthResponse ([Organization])
+authResponseOrganizationsL f AuthResponse{..} = (\authResponseOrganizations -> AuthResponse { authResponseOrganizations, ..} ) <$> f authResponseOrganizations
+{-# INLINE authResponseOrganizationsL #-}
+
+-- | 'authResponseBootstrapApiKey' Lens
+authResponseBootstrapApiKeyL :: Lens_' AuthResponse (Maybe Text)
+authResponseBootstrapApiKeyL f AuthResponse{..} = (\authResponseBootstrapApiKey -> AuthResponse { authResponseBootstrapApiKey, ..} ) <$> f authResponseBootstrapApiKey
+{-# INLINE authResponseBootstrapApiKeyL #-}
+
+
+
+-- * CreateAgentTokenInput
+
+-- | 'createAgentTokenInputName' Lens
+createAgentTokenInputNameL :: Lens_' CreateAgentTokenInput (Text)
+createAgentTokenInputNameL f CreateAgentTokenInput{..} = (\createAgentTokenInputName -> CreateAgentTokenInput { createAgentTokenInputName, ..} ) <$> f createAgentTokenInputName
+{-# INLINE createAgentTokenInputNameL #-}
+
+
+
+-- * CreateOrganizationInput
+
+-- | 'createOrganizationInputName' Lens
+createOrganizationInputNameL :: Lens_' CreateOrganizationInput (Text)
+createOrganizationInputNameL f CreateOrganizationInput{..} = (\createOrganizationInputName -> CreateOrganizationInput { createOrganizationInputName, ..} ) <$> f createOrganizationInputName
+{-# INLINE createOrganizationInputNameL #-}
+
+
+
+-- * CurrentAccount
+
+-- | 'currentAccountUser' Lens
+currentAccountUserL :: Lens_' CurrentAccount (User)
+currentAccountUserL f CurrentAccount{..} = (\currentAccountUser -> CurrentAccount { currentAccountUser, ..} ) <$> f currentAccountUser
+{-# INLINE currentAccountUserL #-}
+
+-- | 'currentAccountOrganizations' Lens
+currentAccountOrganizationsL :: Lens_' CurrentAccount ([Organization])
+currentAccountOrganizationsL f CurrentAccount{..} = (\currentAccountOrganizations -> CurrentAccount { currentAccountOrganizations, ..} ) <$> f currentAccountOrganizations
+{-# INLINE currentAccountOrganizationsL #-}
+
+
+
+-- * DeletedResponse
+
+-- | 'deletedResponseDeleted' Lens
+deletedResponseDeletedL :: Lens_' DeletedResponse (Bool)
+deletedResponseDeletedL f DeletedResponse{..} = (\deletedResponseDeleted -> DeletedResponse { deletedResponseDeleted, ..} ) <$> f deletedResponseDeleted
+{-# INLINE deletedResponseDeletedL #-}
+
+
+
+-- * DeliverySummary
+
+-- | 'deliverySummarySent' Lens
+deliverySummarySentL :: Lens_' DeliverySummary (Int)
+deliverySummarySentL f DeliverySummary{..} = (\deliverySummarySent -> DeliverySummary { deliverySummarySent, ..} ) <$> f deliverySummarySent
+{-# INLINE deliverySummarySentL #-}
+
+-- | 'deliverySummaryFailed' Lens
+deliverySummaryFailedL :: Lens_' DeliverySummary (Int)
+deliverySummaryFailedL f DeliverySummary{..} = (\deliverySummaryFailed -> DeliverySummary { deliverySummaryFailed, ..} ) <$> f deliverySummaryFailed
+{-# INLINE deliverySummaryFailedL #-}
+
+-- | 'deliverySummarySuppressedUsers' Lens
+deliverySummarySuppressedUsersL :: Lens_' DeliverySummary (Int)
+deliverySummarySuppressedUsersL f DeliverySummary{..} = (\deliverySummarySuppressedUsers -> DeliverySummary { deliverySummarySuppressedUsers, ..} ) <$> f deliverySummarySuppressedUsers
+{-# INLINE deliverySummarySuppressedUsersL #-}
+
+-- | 'deliverySummaryEligibleDevices' Lens
+deliverySummaryEligibleDevicesL :: Lens_' DeliverySummary (Int)
+deliverySummaryEligibleDevicesL f DeliverySummary{..} = (\deliverySummaryEligibleDevices -> DeliverySummary { deliverySummaryEligibleDevices, ..} ) <$> f deliverySummaryEligibleDevices
+{-# INLINE deliverySummaryEligibleDevicesL #-}
+
+
+
+-- * Device
+
+-- | 'deviceId' Lens
+deviceIdL :: Lens_' Device (Text)
+deviceIdL f Device{..} = (\deviceId -> Device { deviceId, ..} ) <$> f deviceId
+{-# INLINE deviceIdL #-}
+
+-- | 'deviceInstallationId' Lens
+deviceInstallationIdL :: Lens_' Device (Text)
+deviceInstallationIdL f Device{..} = (\deviceInstallationId -> Device { deviceInstallationId, ..} ) <$> f deviceInstallationId
+{-# INLINE deviceInstallationIdL #-}
+
+-- | 'deviceEnvironment' Lens
+deviceEnvironmentL :: Lens_' Device (E'Environment)
+deviceEnvironmentL f Device{..} = (\deviceEnvironment -> Device { deviceEnvironment, ..} ) <$> f deviceEnvironment
+{-# INLINE deviceEnvironmentL #-}
+
+-- | 'deviceAppVersion' Lens
+deviceAppVersionL :: Lens_' Device (Maybe Text)
+deviceAppVersionL f Device{..} = (\deviceAppVersion -> Device { deviceAppVersion, ..} ) <$> f deviceAppVersion
+{-# INLINE deviceAppVersionL #-}
+
+-- | 'deviceEnabled' Lens
+deviceEnabledL :: Lens_' Device (Bool)
+deviceEnabledL f Device{..} = (\deviceEnabled -> Device { deviceEnabled, ..} ) <$> f deviceEnabled
+{-# INLINE deviceEnabledL #-}
+
+-- | 'deviceLastSeenAt' Lens
+deviceLastSeenAtL :: Lens_' Device (DateTime)
+deviceLastSeenAtL f Device{..} = (\deviceLastSeenAt -> Device { deviceLastSeenAt, ..} ) <$> f deviceLastSeenAt
+{-# INLINE deviceLastSeenAtL #-}
+
+
+
+-- * DisabledResponse
+
+-- | 'disabledResponseDisabled' Lens
+disabledResponseDisabledL :: Lens_' DisabledResponse (Bool)
+disabledResponseDisabledL f DisabledResponse{..} = (\disabledResponseDisabled -> DisabledResponse { disabledResponseDisabled, ..} ) <$> f disabledResponseDisabled
+{-# INLINE disabledResponseDisabledL #-}
+
+
+
+-- * ErrorResponse
+
+-- | 'errorResponseStatusCode' Lens
+errorResponseStatusCodeL :: Lens_' ErrorResponse (Int)
+errorResponseStatusCodeL f ErrorResponse{..} = (\errorResponseStatusCode -> ErrorResponse { errorResponseStatusCode, ..} ) <$> f errorResponseStatusCode
+{-# INLINE errorResponseStatusCodeL #-}
+
+-- | 'errorResponseMessage' Lens
+errorResponseMessageL :: Lens_' ErrorResponse (Text)
+errorResponseMessageL f ErrorResponse{..} = (\errorResponseMessage -> ErrorResponse { errorResponseMessage, ..} ) <$> f errorResponseMessage
+{-# INLINE errorResponseMessageL #-}
+
+-- | 'errorResponseError' Lens
+errorResponseErrorL :: Lens_' ErrorResponse (Maybe Text)
+errorResponseErrorL f ErrorResponse{..} = (\errorResponseError -> ErrorResponse { errorResponseError, ..} ) <$> f errorResponseError
+{-# INLINE errorResponseErrorL #-}
+
+
+
+-- * EventDetail
+
+-- | 'eventDetailId' Lens
+eventDetailIdL :: Lens_' EventDetail (Text)
+eventDetailIdL f EventDetail{..} = (\eventDetailId -> EventDetail { eventDetailId, ..} ) <$> f eventDetailId
+{-# INLINE eventDetailIdL #-}
+
+-- | 'eventDetailType' Lens
+eventDetailTypeL :: Lens_' EventDetail (Text)
+eventDetailTypeL f EventDetail{..} = (\eventDetailType -> EventDetail { eventDetailType, ..} ) <$> f eventDetailType
+{-# INLINE eventDetailTypeL #-}
+
+-- | 'eventDetailTitle' Lens
+eventDetailTitleL :: Lens_' EventDetail (Text)
+eventDetailTitleL f EventDetail{..} = (\eventDetailTitle -> EventDetail { eventDetailTitle, ..} ) <$> f eventDetailTitle
+{-# INLINE eventDetailTitleL #-}
+
+-- | 'eventDetailBody' Lens
+eventDetailBodyL :: Lens_' EventDetail (Text)
+eventDetailBodyL f EventDetail{..} = (\eventDetailBody -> EventDetail { eventDetailBody, ..} ) <$> f eventDetailBody
+{-# INLINE eventDetailBodyL #-}
+
+-- | 'eventDetailExternalId' Lens
+eventDetailExternalIdL :: Lens_' EventDetail (Maybe Text)
+eventDetailExternalIdL f EventDetail{..} = (\eventDetailExternalId -> EventDetail { eventDetailExternalId, ..} ) <$> f eventDetailExternalId
+{-# INLINE eventDetailExternalIdL #-}
+
+-- | 'eventDetailActionUrl' Lens
+eventDetailActionUrlL :: Lens_' EventDetail (Maybe Text)
+eventDetailActionUrlL f EventDetail{..} = (\eventDetailActionUrl -> EventDetail { eventDetailActionUrl, ..} ) <$> f eventDetailActionUrl
+{-# INLINE eventDetailActionUrlL #-}
+
+-- | 'eventDetailCreatedAt' Lens
+eventDetailCreatedAtL :: Lens_' EventDetail (DateTime)
+eventDetailCreatedAtL f EventDetail{..} = (\eventDetailCreatedAt -> EventDetail { eventDetailCreatedAt, ..} ) <$> f eventDetailCreatedAt
+{-# INLINE eventDetailCreatedAtL #-}
+
+-- | 'eventDetailService' Lens
+eventDetailServiceL :: Lens_' EventDetail (ServiceSummary)
+eventDetailServiceL f EventDetail{..} = (\eventDetailService -> EventDetail { eventDetailService, ..} ) <$> f eventDetailService
+{-# INLINE eventDetailServiceL #-}
+
+-- | 'eventDetailServiceId' Lens
+eventDetailServiceIdL :: Lens_' EventDetail (Text)
+eventDetailServiceIdL f EventDetail{..} = (\eventDetailServiceId -> EventDetail { eventDetailServiceId, ..} ) <$> f eventDetailServiceId
+{-# INLINE eventDetailServiceIdL #-}
+
+-- | 'eventDetailMetadata' Lens
+eventDetailMetadataL :: Lens_' EventDetail (Maybe (Map.Map String AnyType))
+eventDetailMetadataL f EventDetail{..} = (\eventDetailMetadata -> EventDetail { eventDetailMetadata, ..} ) <$> f eventDetailMetadata
+{-# INLINE eventDetailMetadataL #-}
+
+
+
+-- * EventFilter
+
+-- | 'eventFilterOperator' Lens
+eventFilterOperatorL :: Lens_' EventFilter (E'Operator)
+eventFilterOperatorL f EventFilter{..} = (\eventFilterOperator -> EventFilter { eventFilterOperator, ..} ) <$> f eventFilterOperator
+{-# INLINE eventFilterOperatorL #-}
+
+-- | 'eventFilterChildren' Lens
+eventFilterChildrenL :: Lens_' EventFilter ([EventFilter])
+eventFilterChildrenL f EventFilter{..} = (\eventFilterChildren -> EventFilter { eventFilterChildren, ..} ) <$> f eventFilterChildren
+{-# INLINE eventFilterChildrenL #-}
+
+-- | 'eventFilterChild' Lens
+eventFilterChildL :: Lens_' EventFilter (EventFilter)
+eventFilterChildL f EventFilter{..} = (\eventFilterChild -> EventFilter { eventFilterChild, ..} ) <$> f eventFilterChild
+{-# INLINE eventFilterChildL #-}
+
+-- | 'eventFilterField' Lens
+eventFilterFieldL :: Lens_' EventFilter (E'Field)
+eventFilterFieldL f EventFilter{..} = (\eventFilterField -> EventFilter { eventFilterField, ..} ) <$> f eventFilterField
+{-# INLINE eventFilterFieldL #-}
+
+-- | 'eventFilterComparison' Lens
+eventFilterComparisonL :: Lens_' EventFilter (E'Comparison)
+eventFilterComparisonL f EventFilter{..} = (\eventFilterComparison -> EventFilter { eventFilterComparison, ..} ) <$> f eventFilterComparison
+{-# INLINE eventFilterComparisonL #-}
+
+-- | 'eventFilterValue' Lens
+eventFilterValueL :: Lens_' EventFilter (DateTime)
+eventFilterValueL f EventFilter{..} = (\eventFilterValue -> EventFilter { eventFilterValue, ..} ) <$> f eventFilterValue
+{-# INLINE eventFilterValueL #-}
+
+
+
+-- * EventPage
+
+-- | 'eventPageEvents' Lens
+eventPageEventsL :: Lens_' EventPage ([EventSummary])
+eventPageEventsL f EventPage{..} = (\eventPageEvents -> EventPage { eventPageEvents, ..} ) <$> f eventPageEvents
+{-# INLINE eventPageEventsL #-}
+
+-- | 'eventPageNextCursor' Lens
+eventPageNextCursorL :: Lens_' EventPage (Maybe Text)
+eventPageNextCursorL f EventPage{..} = (\eventPageNextCursor -> EventPage { eventPageNextCursor, ..} ) <$> f eventPageNextCursor
+{-# INLINE eventPageNextCursorL #-}
+
+
+
+-- * EventSummary
+
+-- | 'eventSummaryId' Lens
+eventSummaryIdL :: Lens_' EventSummary (Text)
+eventSummaryIdL f EventSummary{..} = (\eventSummaryId -> EventSummary { eventSummaryId, ..} ) <$> f eventSummaryId
+{-# INLINE eventSummaryIdL #-}
+
+-- | 'eventSummaryType' Lens
+eventSummaryTypeL :: Lens_' EventSummary (Text)
+eventSummaryTypeL f EventSummary{..} = (\eventSummaryType -> EventSummary { eventSummaryType, ..} ) <$> f eventSummaryType
+{-# INLINE eventSummaryTypeL #-}
+
+-- | 'eventSummaryTitle' Lens
+eventSummaryTitleL :: Lens_' EventSummary (Text)
+eventSummaryTitleL f EventSummary{..} = (\eventSummaryTitle -> EventSummary { eventSummaryTitle, ..} ) <$> f eventSummaryTitle
+{-# INLINE eventSummaryTitleL #-}
+
+-- | 'eventSummaryBody' Lens
+eventSummaryBodyL :: Lens_' EventSummary (Text)
+eventSummaryBodyL f EventSummary{..} = (\eventSummaryBody -> EventSummary { eventSummaryBody, ..} ) <$> f eventSummaryBody
+{-# INLINE eventSummaryBodyL #-}
+
+-- | 'eventSummaryExternalId' Lens
+eventSummaryExternalIdL :: Lens_' EventSummary (Maybe Text)
+eventSummaryExternalIdL f EventSummary{..} = (\eventSummaryExternalId -> EventSummary { eventSummaryExternalId, ..} ) <$> f eventSummaryExternalId
+{-# INLINE eventSummaryExternalIdL #-}
+
+-- | 'eventSummaryActionUrl' Lens
+eventSummaryActionUrlL :: Lens_' EventSummary (Maybe Text)
+eventSummaryActionUrlL f EventSummary{..} = (\eventSummaryActionUrl -> EventSummary { eventSummaryActionUrl, ..} ) <$> f eventSummaryActionUrl
+{-# INLINE eventSummaryActionUrlL #-}
+
+-- | 'eventSummaryCreatedAt' Lens
+eventSummaryCreatedAtL :: Lens_' EventSummary (DateTime)
+eventSummaryCreatedAtL f EventSummary{..} = (\eventSummaryCreatedAt -> EventSummary { eventSummaryCreatedAt, ..} ) <$> f eventSummaryCreatedAt
+{-# INLINE eventSummaryCreatedAtL #-}
+
+-- | 'eventSummaryService' Lens
+eventSummaryServiceL :: Lens_' EventSummary (ServiceSummary)
+eventSummaryServiceL f EventSummary{..} = (\eventSummaryService -> EventSummary { eventSummaryService, ..} ) <$> f eventSummaryService
+{-# INLINE eventSummaryServiceL #-}
+
+
+
+-- * FilterGroup
+
+-- | 'filterGroupOperator' Lens
+filterGroupOperatorL :: Lens_' FilterGroup (E'Operator2)
+filterGroupOperatorL f FilterGroup{..} = (\filterGroupOperator -> FilterGroup { filterGroupOperator, ..} ) <$> f filterGroupOperator
+{-# INLINE filterGroupOperatorL #-}
+
+-- | 'filterGroupChildren' Lens
+filterGroupChildrenL :: Lens_' FilterGroup ([EventFilter])
+filterGroupChildrenL f FilterGroup{..} = (\filterGroupChildren -> FilterGroup { filterGroupChildren, ..} ) <$> f filterGroupChildren
+{-# INLINE filterGroupChildrenL #-}
+
+
+
+-- * FilterNot
+
+-- | 'filterNotOperator' Lens
+filterNotOperatorL :: Lens_' FilterNot (E'Operator)
+filterNotOperatorL f FilterNot{..} = (\filterNotOperator -> FilterNot { filterNotOperator, ..} ) <$> f filterNotOperator
+{-# INLINE filterNotOperatorL #-}
+
+-- | 'filterNotChild' Lens
+filterNotChildL :: Lens_' FilterNot (EventFilter)
+filterNotChildL f FilterNot{..} = (\filterNotChild -> FilterNot { filterNotChild, ..} ) <$> f filterNotChild
+{-# INLINE filterNotChildL #-}
+
+
+
+-- * HealthResponse
+
+-- | 'healthResponseStatus' Lens
+healthResponseStatusL :: Lens_' HealthResponse (E'Status)
+healthResponseStatusL f HealthResponse{..} = (\healthResponseStatus -> HealthResponse { healthResponseStatus, ..} ) <$> f healthResponseStatus
+{-# INLINE healthResponseStatusL #-}
+
+-- | 'healthResponseService' Lens
+healthResponseServiceL :: Lens_' HealthResponse (E'Service)
+healthResponseServiceL f HealthResponse{..} = (\healthResponseService -> HealthResponse { healthResponseService, ..} ) <$> f healthResponseService
+{-# INLINE healthResponseServiceL #-}
+
+
+
+-- * IngestionResult
+
+-- | 'ingestionResultEvent' Lens
+ingestionResultEventL :: Lens_' IngestionResult (EventDetail)
+ingestionResultEventL f IngestionResult{..} = (\ingestionResultEvent -> IngestionResult { ingestionResultEvent, ..} ) <$> f ingestionResultEvent
+{-# INLINE ingestionResultEventL #-}
+
+-- | 'ingestionResultDuplicate' Lens
+ingestionResultDuplicateL :: Lens_' IngestionResult (Bool)
+ingestionResultDuplicateL f IngestionResult{..} = (\ingestionResultDuplicate -> IngestionResult { ingestionResultDuplicate, ..} ) <$> f ingestionResultDuplicate
+{-# INLINE ingestionResultDuplicateL #-}
+
+-- | 'ingestionResultDelivery' Lens
+ingestionResultDeliveryL :: Lens_' IngestionResult (DeliverySummary)
+ingestionResultDeliveryL f IngestionResult{..} = (\ingestionResultDelivery -> IngestionResult { ingestionResultDelivery, ..} ) <$> f ingestionResultDelivery
+{-# INLINE ingestionResultDeliveryL #-}
+
+
+
+-- * InheritedResponse
+
+-- | 'inheritedResponseInherited' Lens
+inheritedResponseInheritedL :: Lens_' InheritedResponse (Bool)
+inheritedResponseInheritedL f InheritedResponse{..} = (\inheritedResponseInherited -> InheritedResponse { inheritedResponseInherited, ..} ) <$> f inheritedResponseInherited
+{-# INLINE inheritedResponseInheritedL #-}
+
+
+
+-- * Membership
+
+-- | 'membershipId' Lens
+membershipIdL :: Lens_' Membership (Text)
+membershipIdL f Membership{..} = (\membershipId -> Membership { membershipId, ..} ) <$> f membershipId
+{-# INLINE membershipIdL #-}
+
+-- | 'membershipRole' Lens
+membershipRoleL :: Lens_' Membership (E'Role)
+membershipRoleL f Membership{..} = (\membershipRole -> Membership { membershipRole, ..} ) <$> f membershipRole
+{-# INLINE membershipRoleL #-}
+
+-- | 'membershipCreatedAt' Lens
+membershipCreatedAtL :: Lens_' Membership (DateTime)
+membershipCreatedAtL f Membership{..} = (\membershipCreatedAt -> Membership { membershipCreatedAt, ..} ) <$> f membershipCreatedAt
+{-# INLINE membershipCreatedAtL #-}
+
+-- | 'membershipUser' Lens
+membershipUserL :: Lens_' Membership (MembershipUser)
+membershipUserL f Membership{..} = (\membershipUser -> Membership { membershipUser, ..} ) <$> f membershipUser
+{-# INLINE membershipUserL #-}
+
+
+
+-- * MembershipUser
+
+-- | 'membershipUserId' Lens
+membershipUserIdL :: Lens_' MembershipUser (Text)
+membershipUserIdL f MembershipUser{..} = (\membershipUserId -> MembershipUser { membershipUserId, ..} ) <$> f membershipUserId
+{-# INLINE membershipUserIdL #-}
+
+-- | 'membershipUserEmail' Lens
+membershipUserEmailL :: Lens_' MembershipUser (Text)
+membershipUserEmailL f MembershipUser{..} = (\membershipUserEmail -> MembershipUser { membershipUserEmail, ..} ) <$> f membershipUserEmail
+{-# INLINE membershipUserEmailL #-}
+
+-- | 'membershipUserDisplayName' Lens
+membershipUserDisplayNameL :: Lens_' MembershipUser (Maybe Text)
+membershipUserDisplayNameL f MembershipUser{..} = (\membershipUserDisplayName -> MembershipUser { membershipUserDisplayName, ..} ) <$> f membershipUserDisplayName
+{-# INLINE membershipUserDisplayNameL #-}
+
+
+
+-- * Organization
+
+-- | 'organizationId' Lens
+organizationIdL :: Lens_' Organization (Text)
+organizationIdL f Organization{..} = (\organizationId -> Organization { organizationId, ..} ) <$> f organizationId
+{-# INLINE organizationIdL #-}
+
+-- | 'organizationName' Lens
+organizationNameL :: Lens_' Organization (Text)
+organizationNameL f Organization{..} = (\organizationName -> Organization { organizationName, ..} ) <$> f organizationName
+{-# INLINE organizationNameL #-}
+
+-- | 'organizationRole' Lens
+organizationRoleL :: Lens_' Organization (E'Role)
+organizationRoleL f Organization{..} = (\organizationRole -> Organization { organizationRole, ..} ) <$> f organizationRole
+{-# INLINE organizationRoleL #-}
+
+-- | 'organizationCreatedAt' Lens
+organizationCreatedAtL :: Lens_' Organization (DateTime)
+organizationCreatedAtL f Organization{..} = (\organizationCreatedAt -> Organization { organizationCreatedAt, ..} ) <$> f organizationCreatedAt
+{-# INLINE organizationCreatedAtL #-}
+
+-- | 'organizationUpdatedAt' Lens
+organizationUpdatedAtL :: Lens_' Organization (DateTime)
+organizationUpdatedAtL f Organization{..} = (\organizationUpdatedAt -> Organization { organizationUpdatedAt, ..} ) <$> f organizationUpdatedAt
+{-# INLINE organizationUpdatedAtL #-}
+
+-- | 'organizationJoinedAt' Lens
+organizationJoinedAtL :: Lens_' Organization (DateTime)
+organizationJoinedAtL f Organization{..} = (\organizationJoinedAt -> Organization { organizationJoinedAt, ..} ) <$> f organizationJoinedAt
+{-# INLINE organizationJoinedAtL #-}
+
+-- | 'organizationApiKey' Lens
+organizationApiKeyL :: Lens_' Organization (Maybe ApiKeySummary)
+organizationApiKeyL f Organization{..} = (\organizationApiKey -> Organization { organizationApiKey, ..} ) <$> f organizationApiKey
+{-# INLINE organizationApiKeyL #-}
+
+-- | 'organizationCount' Lens
+organizationCountL :: Lens_' Organization (Maybe OrganizationCount)
+organizationCountL f Organization{..} = (\organizationCount -> Organization { organizationCount, ..} ) <$> f organizationCount
+{-# INLINE organizationCountL #-}
+
+
+
+-- * OrganizationApiKeyCreated
+
+-- | 'organizationApiKeyCreatedKeyPrefix' Lens
+organizationApiKeyCreatedKeyPrefixL :: Lens_' OrganizationApiKeyCreated (Text)
+organizationApiKeyCreatedKeyPrefixL f OrganizationApiKeyCreated{..} = (\organizationApiKeyCreatedKeyPrefix -> OrganizationApiKeyCreated { organizationApiKeyCreatedKeyPrefix, ..} ) <$> f organizationApiKeyCreatedKeyPrefix
+{-# INLINE organizationApiKeyCreatedKeyPrefixL #-}
+
+-- | 'organizationApiKeyCreatedLastFour' Lens
+organizationApiKeyCreatedLastFourL :: Lens_' OrganizationApiKeyCreated (Text)
+organizationApiKeyCreatedLastFourL f OrganizationApiKeyCreated{..} = (\organizationApiKeyCreatedLastFour -> OrganizationApiKeyCreated { organizationApiKeyCreatedLastFour, ..} ) <$> f organizationApiKeyCreatedLastFour
+{-# INLINE organizationApiKeyCreatedLastFourL #-}
+
+-- | 'organizationApiKeyCreatedUpdatedAt' Lens
+organizationApiKeyCreatedUpdatedAtL :: Lens_' OrganizationApiKeyCreated (DateTime)
+organizationApiKeyCreatedUpdatedAtL f OrganizationApiKeyCreated{..} = (\organizationApiKeyCreatedUpdatedAt -> OrganizationApiKeyCreated { organizationApiKeyCreatedUpdatedAt, ..} ) <$> f organizationApiKeyCreatedUpdatedAt
+{-# INLINE organizationApiKeyCreatedUpdatedAtL #-}
+
+-- | 'organizationApiKeyCreatedApiKey' Lens
+organizationApiKeyCreatedApiKeyL :: Lens_' OrganizationApiKeyCreated (Text)
+organizationApiKeyCreatedApiKeyL f OrganizationApiKeyCreated{..} = (\organizationApiKeyCreatedApiKey -> OrganizationApiKeyCreated { organizationApiKeyCreatedApiKey, ..} ) <$> f organizationApiKeyCreatedApiKey
+{-# INLINE organizationApiKeyCreatedApiKeyL #-}
+
+
+
+-- * OrganizationCount
+
+-- | 'organizationCountMemberships' Lens
+organizationCountMembershipsL :: Lens_' OrganizationCount (Maybe Int)
+organizationCountMembershipsL f OrganizationCount{..} = (\organizationCountMemberships -> OrganizationCount { organizationCountMemberships, ..} ) <$> f organizationCountMemberships
+{-# INLINE organizationCountMembershipsL #-}
+
+-- | 'organizationCountServices' Lens
+organizationCountServicesL :: Lens_' OrganizationCount (Maybe Int)
+organizationCountServicesL f OrganizationCount{..} = (\organizationCountServices -> OrganizationCount { organizationCountServices, ..} ) <$> f organizationCountServices
+{-# INLINE organizationCountServicesL #-}
+
+
+
+-- * OrganizationCreated
+
+-- | 'organizationCreatedOrganization' Lens
+organizationCreatedOrganizationL :: Lens_' OrganizationCreated (OrganizationRecord)
+organizationCreatedOrganizationL f OrganizationCreated{..} = (\organizationCreatedOrganization -> OrganizationCreated { organizationCreatedOrganization, ..} ) <$> f organizationCreatedOrganization
+{-# INLINE organizationCreatedOrganizationL #-}
+
+-- | 'organizationCreatedApiKey' Lens
+organizationCreatedApiKeyL :: Lens_' OrganizationCreated (Text)
+organizationCreatedApiKeyL f OrganizationCreated{..} = (\organizationCreatedApiKey -> OrganizationCreated { organizationCreatedApiKey, ..} ) <$> f organizationCreatedApiKey
+{-# INLINE organizationCreatedApiKeyL #-}
+
+
+
+-- * OrganizationRecord
+
+-- | 'organizationRecordId' Lens
+organizationRecordIdL :: Lens_' OrganizationRecord (Text)
+organizationRecordIdL f OrganizationRecord{..} = (\organizationRecordId -> OrganizationRecord { organizationRecordId, ..} ) <$> f organizationRecordId
+{-# INLINE organizationRecordIdL #-}
+
+-- | 'organizationRecordName' Lens
+organizationRecordNameL :: Lens_' OrganizationRecord (Text)
+organizationRecordNameL f OrganizationRecord{..} = (\organizationRecordName -> OrganizationRecord { organizationRecordName, ..} ) <$> f organizationRecordName
+{-# INLINE organizationRecordNameL #-}
+
+-- | 'organizationRecordCreatedAt' Lens
+organizationRecordCreatedAtL :: Lens_' OrganizationRecord (DateTime)
+organizationRecordCreatedAtL f OrganizationRecord{..} = (\organizationRecordCreatedAt -> OrganizationRecord { organizationRecordCreatedAt, ..} ) <$> f organizationRecordCreatedAt
+{-# INLINE organizationRecordCreatedAtL #-}
+
+-- | 'organizationRecordUpdatedAt' Lens
+organizationRecordUpdatedAtL :: Lens_' OrganizationRecord (DateTime)
+organizationRecordUpdatedAtL f OrganizationRecord{..} = (\organizationRecordUpdatedAt -> OrganizationRecord { organizationRecordUpdatedAt, ..} ) <$> f organizationRecordUpdatedAt
+{-# INLINE organizationRecordUpdatedAtL #-}
+
+
+
+-- * PasswordLoginInput
+
+-- | 'passwordLoginInputEmail' Lens
+passwordLoginInputEmailL :: Lens_' PasswordLoginInput (Text)
+passwordLoginInputEmailL f PasswordLoginInput{..} = (\passwordLoginInputEmail -> PasswordLoginInput { passwordLoginInputEmail, ..} ) <$> f passwordLoginInputEmail
+{-# INLINE passwordLoginInputEmailL #-}
+
+-- | 'passwordLoginInputPassword' Lens
+passwordLoginInputPasswordL :: Lens_' PasswordLoginInput (Text)
+passwordLoginInputPasswordL f PasswordLoginInput{..} = (\passwordLoginInputPassword -> PasswordLoginInput { passwordLoginInputPassword, ..} ) <$> f passwordLoginInputPassword
+{-# INLINE passwordLoginInputPasswordL #-}
+
+
+
+-- * PasswordResetCompleteInput
+
+-- | 'passwordResetCompleteInputToken' Lens
+passwordResetCompleteInputTokenL :: Lens_' PasswordResetCompleteInput (Text)
+passwordResetCompleteInputTokenL f PasswordResetCompleteInput{..} = (\passwordResetCompleteInputToken -> PasswordResetCompleteInput { passwordResetCompleteInputToken, ..} ) <$> f passwordResetCompleteInputToken
+{-# INLINE passwordResetCompleteInputTokenL #-}
+
+-- | 'passwordResetCompleteInputPassword' Lens
+passwordResetCompleteInputPasswordL :: Lens_' PasswordResetCompleteInput (Text)
+passwordResetCompleteInputPasswordL f PasswordResetCompleteInput{..} = (\passwordResetCompleteInputPassword -> PasswordResetCompleteInput { passwordResetCompleteInputPassword, ..} ) <$> f passwordResetCompleteInputPassword
+{-# INLINE passwordResetCompleteInputPasswordL #-}
+
+
+
+-- * PasswordResetRequestInput
+
+-- | 'passwordResetRequestInputEmail' Lens
+passwordResetRequestInputEmailL :: Lens_' PasswordResetRequestInput (Text)
+passwordResetRequestInputEmailL f PasswordResetRequestInput{..} = (\passwordResetRequestInputEmail -> PasswordResetRequestInput { passwordResetRequestInputEmail, ..} ) <$> f passwordResetRequestInputEmail
+{-# INLINE passwordResetRequestInputEmailL #-}
+
+
+
+-- * PreferenceRecord
+
+-- | 'preferenceRecordServiceId' Lens
+preferenceRecordServiceIdL :: Lens_' PreferenceRecord (Text)
+preferenceRecordServiceIdL f PreferenceRecord{..} = (\preferenceRecordServiceId -> PreferenceRecord { preferenceRecordServiceId, ..} ) <$> f preferenceRecordServiceId
+{-# INLINE preferenceRecordServiceIdL #-}
+
+-- | 'preferenceRecordTypeKey' Lens
+preferenceRecordTypeKeyL :: Lens_' PreferenceRecord (Text)
+preferenceRecordTypeKeyL f PreferenceRecord{..} = (\preferenceRecordTypeKey -> PreferenceRecord { preferenceRecordTypeKey, ..} ) <$> f preferenceRecordTypeKey
+{-# INLINE preferenceRecordTypeKeyL #-}
+
+-- | 'preferenceRecordEnabled' Lens
+preferenceRecordEnabledL :: Lens_' PreferenceRecord (Bool)
+preferenceRecordEnabledL f PreferenceRecord{..} = (\preferenceRecordEnabled -> PreferenceRecord { preferenceRecordEnabled, ..} ) <$> f preferenceRecordEnabled
+{-# INLINE preferenceRecordEnabledL #-}
+
+-- | 'preferenceRecordUpdatedAt' Lens
+preferenceRecordUpdatedAtL :: Lens_' PreferenceRecord (DateTime)
+preferenceRecordUpdatedAtL f PreferenceRecord{..} = (\preferenceRecordUpdatedAt -> PreferenceRecord { preferenceRecordUpdatedAt, ..} ) <$> f preferenceRecordUpdatedAt
+{-# INLINE preferenceRecordUpdatedAtL #-}
+
+
+
+-- * ProviderLoginInput
+
+-- | 'providerLoginInputIdToken' Lens
+providerLoginInputIdTokenL :: Lens_' ProviderLoginInput (Text)
+providerLoginInputIdTokenL f ProviderLoginInput{..} = (\providerLoginInputIdToken -> ProviderLoginInput { providerLoginInputIdToken, ..} ) <$> f providerLoginInputIdToken
+{-# INLINE providerLoginInputIdTokenL #-}
+
+-- | 'providerLoginInputDisplayName' Lens
+providerLoginInputDisplayNameL :: Lens_' ProviderLoginInput (Maybe Text)
+providerLoginInputDisplayNameL f ProviderLoginInput{..} = (\providerLoginInputDisplayName -> ProviderLoginInput { providerLoginInputDisplayName, ..} ) <$> f providerLoginInputDisplayName
+{-# INLINE providerLoginInputDisplayNameL #-}
+
+
+
+-- * RegisterDeviceInput
+
+-- | 'registerDeviceInputDeviceToken' Lens
+registerDeviceInputDeviceTokenL :: Lens_' RegisterDeviceInput (Text)
+registerDeviceInputDeviceTokenL f RegisterDeviceInput{..} = (\registerDeviceInputDeviceToken -> RegisterDeviceInput { registerDeviceInputDeviceToken, ..} ) <$> f registerDeviceInputDeviceToken
+{-# INLINE registerDeviceInputDeviceTokenL #-}
+
+-- | 'registerDeviceInputInstallationId' Lens
+registerDeviceInputInstallationIdL :: Lens_' RegisterDeviceInput (Text)
+registerDeviceInputInstallationIdL f RegisterDeviceInput{..} = (\registerDeviceInputInstallationId -> RegisterDeviceInput { registerDeviceInputInstallationId, ..} ) <$> f registerDeviceInputInstallationId
+{-# INLINE registerDeviceInputInstallationIdL #-}
+
+-- | 'registerDeviceInputEnvironment' Lens
+registerDeviceInputEnvironmentL :: Lens_' RegisterDeviceInput (E'Environment)
+registerDeviceInputEnvironmentL f RegisterDeviceInput{..} = (\registerDeviceInputEnvironment -> RegisterDeviceInput { registerDeviceInputEnvironment, ..} ) <$> f registerDeviceInputEnvironment
+{-# INLINE registerDeviceInputEnvironmentL #-}
+
+-- | 'registerDeviceInputAppVersion' Lens
+registerDeviceInputAppVersionL :: Lens_' RegisterDeviceInput (Maybe Text)
+registerDeviceInputAppVersionL f RegisterDeviceInput{..} = (\registerDeviceInputAppVersion -> RegisterDeviceInput { registerDeviceInputAppVersion, ..} ) <$> f registerDeviceInputAppVersion
+{-# INLINE registerDeviceInputAppVersionL #-}
+
+
+
+-- * RegisterInput
+
+-- | 'registerInputEmail' Lens
+registerInputEmailL :: Lens_' RegisterInput (Text)
+registerInputEmailL f RegisterInput{..} = (\registerInputEmail -> RegisterInput { registerInputEmail, ..} ) <$> f registerInputEmail
+{-# INLINE registerInputEmailL #-}
+
+-- | 'registerInputPassword' Lens
+registerInputPasswordL :: Lens_' RegisterInput (Text)
+registerInputPasswordL f RegisterInput{..} = (\registerInputPassword -> RegisterInput { registerInputPassword, ..} ) <$> f registerInputPassword
+{-# INLINE registerInputPasswordL #-}
+
+-- | 'registerInputDisplayName' Lens
+registerInputDisplayNameL :: Lens_' RegisterInput (Maybe Text)
+registerInputDisplayNameL f RegisterInput{..} = (\registerInputDisplayName -> RegisterInput { registerInputDisplayName, ..} ) <$> f registerInputDisplayName
+{-# INLINE registerInputDisplayNameL #-}
+
+
+
+-- * RegisterWebPushSubscriptionInput
+
+-- | 'registerWebPushSubscriptionInputEndpoint' Lens
+registerWebPushSubscriptionInputEndpointL :: Lens_' RegisterWebPushSubscriptionInput (Text)
+registerWebPushSubscriptionInputEndpointL f RegisterWebPushSubscriptionInput{..} = (\registerWebPushSubscriptionInputEndpoint -> RegisterWebPushSubscriptionInput { registerWebPushSubscriptionInputEndpoint, ..} ) <$> f registerWebPushSubscriptionInputEndpoint
+{-# INLINE registerWebPushSubscriptionInputEndpointL #-}
+
+-- | 'registerWebPushSubscriptionInputKeys' Lens
+registerWebPushSubscriptionInputKeysL :: Lens_' RegisterWebPushSubscriptionInput (RegisterWebPushSubscriptionInputKeys)
+registerWebPushSubscriptionInputKeysL f RegisterWebPushSubscriptionInput{..} = (\registerWebPushSubscriptionInputKeys -> RegisterWebPushSubscriptionInput { registerWebPushSubscriptionInputKeys, ..} ) <$> f registerWebPushSubscriptionInputKeys
+{-# INLINE registerWebPushSubscriptionInputKeysL #-}
+
+
+
+-- * RegisterWebPushSubscriptionInputKeys
+
+-- | 'registerWebPushSubscriptionInputKeysP256dh' Lens
+registerWebPushSubscriptionInputKeysP256dhL :: Lens_' RegisterWebPushSubscriptionInputKeys (Text)
+registerWebPushSubscriptionInputKeysP256dhL f RegisterWebPushSubscriptionInputKeys{..} = (\registerWebPushSubscriptionInputKeysP256dh -> RegisterWebPushSubscriptionInputKeys { registerWebPushSubscriptionInputKeysP256dh, ..} ) <$> f registerWebPushSubscriptionInputKeysP256dh
+{-# INLINE registerWebPushSubscriptionInputKeysP256dhL #-}
+
+-- | 'registerWebPushSubscriptionInputKeysAuth' Lens
+registerWebPushSubscriptionInputKeysAuthL :: Lens_' RegisterWebPushSubscriptionInputKeys (Text)
+registerWebPushSubscriptionInputKeysAuthL f RegisterWebPushSubscriptionInputKeys{..} = (\registerWebPushSubscriptionInputKeysAuth -> RegisterWebPushSubscriptionInputKeys { registerWebPushSubscriptionInputKeysAuth, ..} ) <$> f registerWebPushSubscriptionInputKeysAuth
+{-# INLINE registerWebPushSubscriptionInputKeysAuthL #-}
+
+
+
+-- * RevokedResponse
+
+-- | 'revokedResponseRevoked' Lens
+revokedResponseRevokedL :: Lens_' RevokedResponse (Bool)
+revokedResponseRevokedL f RevokedResponse{..} = (\revokedResponseRevoked -> RevokedResponse { revokedResponseRevoked, ..} ) <$> f revokedResponseRevoked
+{-# INLINE revokedResponseRevokedL #-}
+
+
+
+-- * SearchEventsInput
+
+-- | 'searchEventsInputFilter' Lens
+searchEventsInputFilterL :: Lens_' SearchEventsInput (EventFilter)
+searchEventsInputFilterL f SearchEventsInput{..} = (\searchEventsInputFilter -> SearchEventsInput { searchEventsInputFilter, ..} ) <$> f searchEventsInputFilter
+{-# INLINE searchEventsInputFilterL #-}
+
+-- | 'searchEventsInputCursor' Lens
+searchEventsInputCursorL :: Lens_' SearchEventsInput (Maybe Text)
+searchEventsInputCursorL f SearchEventsInput{..} = (\searchEventsInputCursor -> SearchEventsInput { searchEventsInputCursor, ..} ) <$> f searchEventsInputCursor
+{-# INLINE searchEventsInputCursorL #-}
+
+-- | 'searchEventsInputLimit' Lens
+searchEventsInputLimitL :: Lens_' SearchEventsInput (Maybe Int)
+searchEventsInputLimitL f SearchEventsInput{..} = (\searchEventsInputLimit -> SearchEventsInput { searchEventsInputLimit, ..} ) <$> f searchEventsInputLimit
+{-# INLINE searchEventsInputLimitL #-}
+
+
+
+-- * SendEventInput
+
+-- | 'sendEventInputService' Lens
+sendEventInputServiceL :: Lens_' SendEventInput (Text)
+sendEventInputServiceL f SendEventInput{..} = (\sendEventInputService -> SendEventInput { sendEventInputService, ..} ) <$> f sendEventInputService
+{-# INLINE sendEventInputServiceL #-}
+
+-- | 'sendEventInputServiceDisplayName' Lens
+sendEventInputServiceDisplayNameL :: Lens_' SendEventInput (Maybe Text)
+sendEventInputServiceDisplayNameL f SendEventInput{..} = (\sendEventInputServiceDisplayName -> SendEventInput { sendEventInputServiceDisplayName, ..} ) <$> f sendEventInputServiceDisplayName
+{-# INLINE sendEventInputServiceDisplayNameL #-}
+
+-- | 'sendEventInputType' Lens
+sendEventInputTypeL :: Lens_' SendEventInput (Text)
+sendEventInputTypeL f SendEventInput{..} = (\sendEventInputType -> SendEventInput { sendEventInputType, ..} ) <$> f sendEventInputType
+{-# INLINE sendEventInputTypeL #-}
+
+-- | 'sendEventInputTitle' Lens
+sendEventInputTitleL :: Lens_' SendEventInput (Text)
+sendEventInputTitleL f SendEventInput{..} = (\sendEventInputTitle -> SendEventInput { sendEventInputTitle, ..} ) <$> f sendEventInputTitle
+{-# INLINE sendEventInputTitleL #-}
+
+-- | 'sendEventInputBody' Lens
+sendEventInputBodyL :: Lens_' SendEventInput (Text)
+sendEventInputBodyL f SendEventInput{..} = (\sendEventInputBody -> SendEventInput { sendEventInputBody, ..} ) <$> f sendEventInputBody
+{-# INLINE sendEventInputBodyL #-}
+
+-- | 'sendEventInputMetadata' Lens
+sendEventInputMetadataL :: Lens_' SendEventInput (Maybe (Map.Map String AnyType))
+sendEventInputMetadataL f SendEventInput{..} = (\sendEventInputMetadata -> SendEventInput { sendEventInputMetadata, ..} ) <$> f sendEventInputMetadata
+{-# INLINE sendEventInputMetadataL #-}
+
+-- | 'sendEventInputExternalId' Lens
+sendEventInputExternalIdL :: Lens_' SendEventInput (Maybe Text)
+sendEventInputExternalIdL f SendEventInput{..} = (\sendEventInputExternalId -> SendEventInput { sendEventInputExternalId, ..} ) <$> f sendEventInputExternalId
+{-# INLINE sendEventInputExternalIdL #-}
+
+-- | 'sendEventInputActionUrl' Lens
+sendEventInputActionUrlL :: Lens_' SendEventInput (Maybe Text)
+sendEventInputActionUrlL f SendEventInput{..} = (\sendEventInputActionUrl -> SendEventInput { sendEventInputActionUrl, ..} ) <$> f sendEventInputActionUrl
+{-# INLINE sendEventInputActionUrlL #-}
+
+
+
+-- * Service
+
+-- | 'serviceId' Lens
+serviceIdL :: Lens_' Service (Text)
+serviceIdL f Service{..} = (\serviceId -> Service { serviceId, ..} ) <$> f serviceId
+{-# INLINE serviceIdL #-}
+
+-- | 'serviceName' Lens
+serviceNameL :: Lens_' Service (Text)
+serviceNameL f Service{..} = (\serviceName -> Service { serviceName, ..} ) <$> f serviceName
+{-# INLINE serviceNameL #-}
+
+-- | 'serviceDisplayName' Lens
+serviceDisplayNameL :: Lens_' Service (Text)
+serviceDisplayNameL f Service{..} = (\serviceDisplayName -> Service { serviceDisplayName, ..} ) <$> f serviceDisplayName
+{-# INLINE serviceDisplayNameL #-}
+
+-- | 'serviceCreatedAt' Lens
+serviceCreatedAtL :: Lens_' Service (DateTime)
+serviceCreatedAtL f Service{..} = (\serviceCreatedAt -> Service { serviceCreatedAt, ..} ) <$> f serviceCreatedAt
+{-# INLINE serviceCreatedAtL #-}
+
+-- | 'serviceCount' Lens
+serviceCountL :: Lens_' Service (ServiceAllOfCount)
+serviceCountL f Service{..} = (\serviceCount -> Service { serviceCount, ..} ) <$> f serviceCount
+{-# INLINE serviceCountL #-}
+
+
+
+-- * ServiceAllOfCount
+
+-- | 'serviceAllOfCountEvents' Lens
+serviceAllOfCountEventsL :: Lens_' ServiceAllOfCount (Int)
+serviceAllOfCountEventsL f ServiceAllOfCount{..} = (\serviceAllOfCountEvents -> ServiceAllOfCount { serviceAllOfCountEvents, ..} ) <$> f serviceAllOfCountEvents
+{-# INLINE serviceAllOfCountEventsL #-}
+
+
+
+-- * ServicePreference
+
+-- | 'servicePreferenceId' Lens
+servicePreferenceIdL :: Lens_' ServicePreference (Text)
+servicePreferenceIdL f ServicePreference{..} = (\servicePreferenceId -> ServicePreference { servicePreferenceId, ..} ) <$> f servicePreferenceId
+{-# INLINE servicePreferenceIdL #-}
+
+-- | 'servicePreferenceName' Lens
+servicePreferenceNameL :: Lens_' ServicePreference (Text)
+servicePreferenceNameL f ServicePreference{..} = (\servicePreferenceName -> ServicePreference { servicePreferenceName, ..} ) <$> f servicePreferenceName
+{-# INLINE servicePreferenceNameL #-}
+
+-- | 'servicePreferenceDisplayName' Lens
+servicePreferenceDisplayNameL :: Lens_' ServicePreference (Text)
+servicePreferenceDisplayNameL f ServicePreference{..} = (\servicePreferenceDisplayName -> ServicePreference { servicePreferenceDisplayName, ..} ) <$> f servicePreferenceDisplayName
+{-# INLINE servicePreferenceDisplayNameL #-}
+
+-- | 'servicePreferenceEnabled' Lens
+servicePreferenceEnabledL :: Lens_' ServicePreference (Bool)
+servicePreferenceEnabledL f ServicePreference{..} = (\servicePreferenceEnabled -> ServicePreference { servicePreferenceEnabled, ..} ) <$> f servicePreferenceEnabled
+{-# INLINE servicePreferenceEnabledL #-}
+
+-- | 'servicePreferenceTypeOverrides' Lens
+servicePreferenceTypeOverridesL :: Lens_' ServicePreference ([TypeOverride])
+servicePreferenceTypeOverridesL f ServicePreference{..} = (\servicePreferenceTypeOverrides -> ServicePreference { servicePreferenceTypeOverrides, ..} ) <$> f servicePreferenceTypeOverrides
+{-# INLINE servicePreferenceTypeOverridesL #-}
+
+
+
+-- * ServiceSummary
+
+-- | 'serviceSummaryId' Lens
+serviceSummaryIdL :: Lens_' ServiceSummary (Text)
+serviceSummaryIdL f ServiceSummary{..} = (\serviceSummaryId -> ServiceSummary { serviceSummaryId, ..} ) <$> f serviceSummaryId
+{-# INLINE serviceSummaryIdL #-}
+
+-- | 'serviceSummaryName' Lens
+serviceSummaryNameL :: Lens_' ServiceSummary (Text)
+serviceSummaryNameL f ServiceSummary{..} = (\serviceSummaryName -> ServiceSummary { serviceSummaryName, ..} ) <$> f serviceSummaryName
+{-# INLINE serviceSummaryNameL #-}
+
+-- | 'serviceSummaryDisplayName' Lens
+serviceSummaryDisplayNameL :: Lens_' ServiceSummary (Text)
+serviceSummaryDisplayNameL f ServiceSummary{..} = (\serviceSummaryDisplayName -> ServiceSummary { serviceSummaryDisplayName, ..} ) <$> f serviceSummaryDisplayName
+{-# INLINE serviceSummaryDisplayNameL #-}
+
+
+
+-- * SetEnabledInput
+
+-- | 'setEnabledInputEnabled' Lens
+setEnabledInputEnabledL :: Lens_' SetEnabledInput (Bool)
+setEnabledInputEnabledL f SetEnabledInput{..} = (\setEnabledInputEnabled -> SetEnabledInput { setEnabledInputEnabled, ..} ) <$> f setEnabledInputEnabled
+{-# INLINE setEnabledInputEnabledL #-}
+
+
+
+-- * TextFilterCondition
+
+-- | 'textFilterConditionField' Lens
+textFilterConditionFieldL :: Lens_' TextFilterCondition (E'Field2)
+textFilterConditionFieldL f TextFilterCondition{..} = (\textFilterConditionField -> TextFilterCondition { textFilterConditionField, ..} ) <$> f textFilterConditionField
+{-# INLINE textFilterConditionFieldL #-}
+
+-- | 'textFilterConditionComparison' Lens
+textFilterConditionComparisonL :: Lens_' TextFilterCondition (E'Comparison2)
+textFilterConditionComparisonL f TextFilterCondition{..} = (\textFilterConditionComparison -> TextFilterCondition { textFilterConditionComparison, ..} ) <$> f textFilterConditionComparison
+{-# INLINE textFilterConditionComparisonL #-}
+
+-- | 'textFilterConditionValue' Lens
+textFilterConditionValueL :: Lens_' TextFilterCondition (Text)
+textFilterConditionValueL f TextFilterCondition{..} = (\textFilterConditionValue -> TextFilterCondition { textFilterConditionValue, ..} ) <$> f textFilterConditionValue
+{-# INLINE textFilterConditionValueL #-}
+
+
+
+-- * TimeFilterCondition
+
+-- | 'timeFilterConditionField' Lens
+timeFilterConditionFieldL :: Lens_' TimeFilterCondition (E'Field)
+timeFilterConditionFieldL f TimeFilterCondition{..} = (\timeFilterConditionField -> TimeFilterCondition { timeFilterConditionField, ..} ) <$> f timeFilterConditionField
+{-# INLINE timeFilterConditionFieldL #-}
+
+-- | 'timeFilterConditionComparison' Lens
+timeFilterConditionComparisonL :: Lens_' TimeFilterCondition (E'Comparison)
+timeFilterConditionComparisonL f TimeFilterCondition{..} = (\timeFilterConditionComparison -> TimeFilterCondition { timeFilterConditionComparison, ..} ) <$> f timeFilterConditionComparison
+{-# INLINE timeFilterConditionComparisonL #-}
+
+-- | 'timeFilterConditionValue' Lens
+timeFilterConditionValueL :: Lens_' TimeFilterCondition (DateTime)
+timeFilterConditionValueL f TimeFilterCondition{..} = (\timeFilterConditionValue -> TimeFilterCondition { timeFilterConditionValue, ..} ) <$> f timeFilterConditionValue
+{-# INLINE timeFilterConditionValueL #-}
+
+
+
+-- * TypeOverride
+
+-- | 'typeOverrideType' Lens
+typeOverrideTypeL :: Lens_' TypeOverride (Text)
+typeOverrideTypeL f TypeOverride{..} = (\typeOverrideType -> TypeOverride { typeOverrideType, ..} ) <$> f typeOverrideType
+{-# INLINE typeOverrideTypeL #-}
+
+-- | 'typeOverrideEnabled' Lens
+typeOverrideEnabledL :: Lens_' TypeOverride (Bool)
+typeOverrideEnabledL f TypeOverride{..} = (\typeOverrideEnabled -> TypeOverride { typeOverrideEnabled, ..} ) <$> f typeOverrideEnabled
+{-# INLINE typeOverrideEnabledL #-}
+
+-- | 'typeOverrideUpdatedAt' Lens
+typeOverrideUpdatedAtL :: Lens_' TypeOverride (DateTime)
+typeOverrideUpdatedAtL f TypeOverride{..} = (\typeOverrideUpdatedAt -> TypeOverride { typeOverrideUpdatedAt, ..} ) <$> f typeOverrideUpdatedAt
+{-# INLINE typeOverrideUpdatedAtL #-}
+
+
+
+-- * User
+
+-- | 'userId' Lens
+userIdL :: Lens_' User (Text)
+userIdL f User{..} = (\userId -> User { userId, ..} ) <$> f userId
+{-# INLINE userIdL #-}
+
+-- | 'userEmail' Lens
+userEmailL :: Lens_' User (Text)
+userEmailL f User{..} = (\userEmail -> User { userEmail, ..} ) <$> f userEmail
+{-# INLINE userEmailL #-}
+
+-- | 'userDisplayName' Lens
+userDisplayNameL :: Lens_' User (Maybe Text)
+userDisplayNameL f User{..} = (\userDisplayName -> User { userDisplayName, ..} ) <$> f userDisplayName
+{-# INLINE userDisplayNameL #-}
+
+-- | 'userHasPassword' Lens
+userHasPasswordL :: Lens_' User (Bool)
+userHasPasswordL f User{..} = (\userHasPassword -> User { userHasPassword, ..} ) <$> f userHasPassword
+{-# INLINE userHasPasswordL #-}
+
+-- | 'userHasGoogle' Lens
+userHasGoogleL :: Lens_' User (Bool)
+userHasGoogleL f User{..} = (\userHasGoogle -> User { userHasGoogle, ..} ) <$> f userHasGoogle
+{-# INLINE userHasGoogleL #-}
+
+-- | 'userHasApple' Lens
+userHasAppleL :: Lens_' User (Bool)
+userHasAppleL f User{..} = (\userHasApple -> User { userHasApple, ..} ) <$> f userHasApple
+{-# INLINE userHasAppleL #-}
+
+
+
+-- * WebPushConfiguration
+
+-- | 'webPushConfigurationEnabled' Lens
+webPushConfigurationEnabledL :: Lens_' WebPushConfiguration (Bool)
+webPushConfigurationEnabledL f WebPushConfiguration{..} = (\webPushConfigurationEnabled -> WebPushConfiguration { webPushConfigurationEnabled, ..} ) <$> f webPushConfigurationEnabled
+{-# INLINE webPushConfigurationEnabledL #-}
+
+-- | 'webPushConfigurationPublicKey' Lens
+webPushConfigurationPublicKeyL :: Lens_' WebPushConfiguration (Maybe Text)
+webPushConfigurationPublicKeyL f WebPushConfiguration{..} = (\webPushConfigurationPublicKey -> WebPushConfiguration { webPushConfigurationPublicKey, ..} ) <$> f webPushConfigurationPublicKey
+{-# INLINE webPushConfigurationPublicKeyL #-}
+
+
+
+-- * WebPushSubscription
+
+-- | 'webPushSubscriptionId' Lens
+webPushSubscriptionIdL :: Lens_' WebPushSubscription (Text)
+webPushSubscriptionIdL f WebPushSubscription{..} = (\webPushSubscriptionId -> WebPushSubscription { webPushSubscriptionId, ..} ) <$> f webPushSubscriptionId
+{-# INLINE webPushSubscriptionIdL #-}
+
+-- | 'webPushSubscriptionEnabled' Lens
+webPushSubscriptionEnabledL :: Lens_' WebPushSubscription (Bool)
+webPushSubscriptionEnabledL f WebPushSubscription{..} = (\webPushSubscriptionEnabled -> WebPushSubscription { webPushSubscriptionEnabled, ..} ) <$> f webPushSubscriptionEnabled
+{-# INLINE webPushSubscriptionEnabledL #-}
+
+-- | 'webPushSubscriptionLastSeenAt' Lens
+webPushSubscriptionLastSeenAtL :: Lens_' WebPushSubscription (DateTime)
+webPushSubscriptionLastSeenAtL f WebPushSubscription{..} = (\webPushSubscriptionLastSeenAt -> WebPushSubscription { webPushSubscriptionLastSeenAt, ..} ) <$> f webPushSubscriptionLastSeenAt
+{-# INLINE webPushSubscriptionLastSeenAtL #-}
+
+
diff --git a/openapi.yaml b/openapi.yaml
new file mode 100644
--- /dev/null
+++ b/openapi.yaml
@@ -0,0 +1,2082 @@
+openapi: 3.1.0
+info:
+  contact:
+    name: Agent Push Kit
+    url: https://agentpushkit.com
+  description: The complete Agent Push Kit REST API. Application event ingestion uses
+    an organization key beginning with `apk_`. Authenticated user operations accept
+    either an Agent Push Kit login JWT or an agent access token beginning with `apt_`.
+  license:
+    name: MIT
+    url: https://opensource.org/license/mit
+  title: Agent Push Kit API
+  version: 0.1.0
+servers:
+- description: Production
+  url: https://api.chatdna.co/agent-push-kit/v1
+security:
+- UserOrAgent: []
+tags:
+- name: Authentication
+- name: Account
+- name: Customer accounts
+- name: Agent tokens
+- name: Events
+- name: Preferences
+- name: Devices
+- name: Health
+paths:
+  /auth/register:
+    post:
+      operationId: register
+      requestBody:
+        $ref: "#/components/requestBodies/Register"
+      responses:
+        "201":
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/AuthResponse"
+          description: Registered and authenticated
+        "400":
+          $ref: "#/components/responses/BadRequest"
+        "409":
+          $ref: "#/components/responses/Conflict"
+      security: []
+      summary: Create a user and first customer account
+      tags:
+      - Authentication
+  /auth/login:
+    post:
+      operationId: loginWithPassword
+      requestBody:
+        $ref: "#/components/requestBodies/PasswordLogin"
+      responses:
+        "201":
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/AuthResponse"
+          description: Authenticated
+        "400":
+          $ref: "#/components/responses/BadRequest"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+      security: []
+      summary: Log in with email and password
+      tags:
+      - Authentication
+  /auth/google:
+    post:
+      operationId: loginWithGoogle
+      requestBody:
+        $ref: "#/components/requestBodies/ProviderLogin"
+      responses:
+        "201":
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/AuthResponse"
+          description: Authenticated
+        "400":
+          $ref: "#/components/responses/BadRequest"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "409":
+          $ref: "#/components/responses/Conflict"
+      security: []
+      summary: Log in or attach an account using a verified Google ID token
+      tags:
+      - Authentication
+  /auth/apple:
+    post:
+      operationId: loginWithApple
+      requestBody:
+        $ref: "#/components/requestBodies/ProviderLogin"
+      responses:
+        "201":
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/AuthResponse"
+          description: Authenticated
+        "400":
+          $ref: "#/components/responses/BadRequest"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "409":
+          $ref: "#/components/responses/Conflict"
+      security: []
+      summary: Log in or attach an account using a Sign in with Apple identity token
+      tags:
+      - Authentication
+  /auth/password-reset/request:
+    post:
+      operationId: requestPasswordReset
+      requestBody:
+        $ref: "#/components/requestBodies/PasswordResetRequest"
+      responses:
+        "201":
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/AcceptedResponse"
+          description: Accepted whether or not the email exists
+        "400":
+          $ref: "#/components/responses/BadRequest"
+      security: []
+      summary: Email a single-use password reset token
+      tags:
+      - Authentication
+  /auth/password-reset/complete:
+    post:
+      operationId: completePasswordReset
+      requestBody:
+        $ref: "#/components/requestBodies/PasswordResetComplete"
+      responses:
+        "201":
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/AuthResponse"
+          description: Password changed and authenticated
+        "400":
+          $ref: "#/components/responses/BadRequest"
+      security: []
+      summary: Choose a new password and log in
+      tags:
+      - Authentication
+  /me:
+    delete:
+      operationId: deleteCurrentAccount
+      responses:
+        "200":
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/DeletedResponse"
+          description: Deleted
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+      summary: Delete the current user and customer accounts they own
+      tags:
+      - Account
+    get:
+      operationId: getCurrentAccount
+      responses:
+        "200":
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/CurrentAccount"
+          description: Current account
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+      summary: Get the current user and customer accounts
+      tags:
+      - Account
+  /organizations:
+    get:
+      operationId: listOrganizations
+      responses:
+        "200":
+          content:
+            application/json:
+              schema:
+                items:
+                  $ref: "#/components/schemas/Organization"
+                type: array
+                default: null
+          description: Customer accounts
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+      summary: List customer accounts available to the current user
+      tags:
+      - Customer accounts
+    post:
+      operationId: createOrganization
+      requestBody:
+        $ref: "#/components/requestBodies/CreateOrganization"
+      responses:
+        "201":
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/OrganizationCreated"
+          description: Created; the organization API key is returned only now
+        "400":
+          $ref: "#/components/responses/BadRequest"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+      summary: Create another Agent Push Kit customer account
+      tags:
+      - Customer accounts
+  /organizations/{organizationId}/members:
+    get:
+      operationId: listOrganizationMembers
+      parameters:
+      - $ref: "#/components/parameters/OrganizationId"
+      responses:
+        "200":
+          content:
+            application/json:
+              schema:
+                items:
+                  $ref: "#/components/schemas/Membership"
+                type: array
+                default: null
+          description: Members
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "404":
+          $ref: "#/components/responses/NotFound"
+      summary: List members of a customer account
+      tags:
+      - Customer accounts
+    post:
+      operationId: addOrganizationMember
+      parameters:
+      - $ref: "#/components/parameters/OrganizationId"
+      requestBody:
+        $ref: "#/components/requestBodies/AddMember"
+      responses:
+        "201":
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/Membership"
+          description: Member added
+        "400":
+          $ref: "#/components/responses/BadRequest"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "403":
+          $ref: "#/components/responses/Forbidden"
+        "404":
+          $ref: "#/components/responses/NotFound"
+        "409":
+          $ref: "#/components/responses/Conflict"
+      summary: Add an already-registered user to a customer account
+      tags:
+      - Customer accounts
+  /organizations/{organizationId}/api-key/regenerate:
+    post:
+      description: The previous `apk_` key stops working immediately. The replacement
+        is returned only in this response.
+      operationId: regenerateOrganizationApiKey
+      parameters:
+      - $ref: "#/components/parameters/OrganizationId"
+      responses:
+        "201":
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/OrganizationApiKeyCreated"
+          description: Key regenerated
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "403":
+          $ref: "#/components/responses/Forbidden"
+        "404":
+          $ref: "#/components/responses/NotFound"
+      summary: Rotate the application event-ingestion key
+      tags:
+      - Customer accounts
+  /agent-tokens:
+    get:
+      operationId: listAgentTokens
+      responses:
+        "200":
+          content:
+            application/json:
+              schema:
+                items:
+                  $ref: "#/components/schemas/AgentToken"
+                type: array
+                default: null
+          description: Agent tokens
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+      summary: List agent access tokens without their secrets
+      tags:
+      - Agent tokens
+    post:
+      description: The raw `apt_` token is shown once. Store it before dismissing
+        the response.
+      operationId: createAgentToken
+      requestBody:
+        $ref: "#/components/requestBodies/CreateAgentToken"
+      responses:
+        "201":
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/AgentTokenCreated"
+          description: Token created
+        "400":
+          $ref: "#/components/responses/BadRequest"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+      summary: Create a named non-expiring agent token
+      tags:
+      - Agent tokens
+  /agent-tokens/{tokenId}:
+    delete:
+      operationId: revokeAgentToken
+      parameters:
+      - $ref: "#/components/parameters/TokenId"
+      responses:
+        "200":
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/RevokedResponse"
+          description: Revoked or already absent
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+      summary: Revoke one of the current user's agent tokens
+      tags:
+      - Agent tokens
+  /events:
+    post:
+      operationId: sendEvent
+      requestBody:
+        $ref: "#/components/requestBodies/SendEvent"
+      responses:
+        "201":
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/IngestionResult"
+          description: Event stored and push delivery attempted
+        "400":
+          $ref: "#/components/responses/BadRequest"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+      security:
+      - OrganizationApiKey: []
+      summary: Send an event using an application ingestion key
+      tags:
+      - Events
+  /organizations/{organizationId}/events:
+    get:
+      operationId: listEvents
+      parameters:
+      - $ref: "#/components/parameters/OrganizationId"
+      - $ref: "#/components/parameters/ServiceName"
+      - $ref: "#/components/parameters/EventType"
+      - $ref: "#/components/parameters/SearchText"
+      - $ref: "#/components/parameters/Cursor"
+      - $ref: "#/components/parameters/Limit"
+      responses:
+        "200":
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/EventPage"
+          description: Event page
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "404":
+          $ref: "#/components/responses/NotFound"
+      summary: List a paginated inbox
+      tags:
+      - Events
+    post:
+      operationId: sendEventAsUser
+      parameters:
+      - $ref: "#/components/parameters/OrganizationId"
+      requestBody:
+        $ref: "#/components/requestBodies/SendEvent"
+      responses:
+        "201":
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/IngestionResult"
+          description: Event stored and push delivery attempted
+        "400":
+          $ref: "#/components/responses/BadRequest"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "404":
+          $ref: "#/components/responses/NotFound"
+      summary: Send an event as an authenticated user or agent
+      tags:
+      - Events
+  /organizations/{organizationId}/events/search:
+    post:
+      operationId: searchEvents
+      parameters:
+      - $ref: "#/components/parameters/OrganizationId"
+      requestBody:
+        $ref: "#/components/requestBodies/SearchEvents"
+      responses:
+        "201":
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/EventPage"
+          description: Event page
+        "400":
+          $ref: "#/components/responses/BadRequest"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "404":
+          $ref: "#/components/responses/NotFound"
+      summary: Search events with a validated Boolean filter tree
+      tags:
+      - Events
+  /organizations/{organizationId}/events/{eventId}:
+    get:
+      operationId: getEvent
+      parameters:
+      - $ref: "#/components/parameters/OrganizationId"
+      - $ref: "#/components/parameters/EventId"
+      responses:
+        "200":
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/EventDetail"
+          description: Event
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "404":
+          $ref: "#/components/responses/NotFound"
+      summary: Get one event including metadata
+      tags:
+      - Events
+  /organizations/{organizationId}/services:
+    get:
+      operationId: listServices
+      parameters:
+      - $ref: "#/components/parameters/OrganizationId"
+      responses:
+        "200":
+          content:
+            application/json:
+              schema:
+                items:
+                  $ref: "#/components/schemas/Service"
+                type: array
+                default: null
+          description: Services
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "404":
+          $ref: "#/components/responses/NotFound"
+      summary: List services discovered from ingested events
+      tags:
+      - Events
+  /organizations/{organizationId}/types:
+    get:
+      operationId: listNotificationTypes
+      parameters:
+      - $ref: "#/components/parameters/OrganizationId"
+      - description: Optionally restrict types to one service ID.
+        explode: true
+        in: query
+        name: serviceId
+        required: false
+        schema:
+          type: string
+        style: form
+      responses:
+        "200":
+          content:
+            application/json:
+              schema:
+                items:
+                  type: string
+                type: array
+                default: null
+          description: Notification types
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "404":
+          $ref: "#/components/responses/NotFound"
+      summary: List distinct notification types
+      tags:
+      - Events
+  /organizations/{organizationId}/preferences:
+    get:
+      operationId: listPreferences
+      parameters:
+      - $ref: "#/components/parameters/OrganizationId"
+      responses:
+        "200":
+          content:
+            application/json:
+              schema:
+                items:
+                  $ref: "#/components/schemas/ServicePreference"
+                type: array
+                default: null
+          description: Preferences
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "404":
+          $ref: "#/components/responses/NotFound"
+      summary: List service defaults and exact-type overrides
+      tags:
+      - Preferences
+  /services/{serviceId}/preference:
+    put:
+      operationId: setServicePreference
+      parameters:
+      - $ref: "#/components/parameters/ServiceId"
+      requestBody:
+        $ref: "#/components/requestBodies/SetEnabled"
+      responses:
+        "200":
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/PreferenceRecord"
+          description: Preference saved
+        "400":
+          $ref: "#/components/responses/BadRequest"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "404":
+          $ref: "#/components/responses/NotFound"
+      summary: Enable or disable pushes for a service by default
+      tags:
+      - Preferences
+  /services/{serviceId}/types/{type}/preference:
+    delete:
+      operationId: removeTypePreference
+      parameters:
+      - $ref: "#/components/parameters/ServiceId"
+      - $ref: "#/components/parameters/TypePath"
+      responses:
+        "200":
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/InheritedResponse"
+          description: Override removed
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "404":
+          $ref: "#/components/responses/NotFound"
+      summary: Remove an exact-type override so it inherits the service default
+      tags:
+      - Preferences
+    put:
+      operationId: setTypePreference
+      parameters:
+      - $ref: "#/components/parameters/ServiceId"
+      - $ref: "#/components/parameters/TypePath"
+      requestBody:
+        $ref: "#/components/requestBodies/SetEnabled"
+      responses:
+        "200":
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/PreferenceRecord"
+          description: Preference saved
+        "400":
+          $ref: "#/components/responses/BadRequest"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+        "404":
+          $ref: "#/components/responses/NotFound"
+      summary: Override push delivery for one exact notification type
+      tags:
+      - Preferences
+  /devices:
+    post:
+      operationId: registerDevice
+      requestBody:
+        $ref: "#/components/requestBodies/RegisterDevice"
+      responses:
+        "201":
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/Device"
+          description: Device registered
+        "400":
+          $ref: "#/components/responses/BadRequest"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+      summary: Register or refresh an APNs device
+      tags:
+      - Devices
+  /devices/{installationId}:
+    delete:
+      operationId: removeDevice
+      parameters:
+      - $ref: "#/components/parameters/InstallationId"
+      responses:
+        "200":
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/DisabledResponse"
+          description: Device disabled
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+      summary: Disable push delivery to one installation
+      tags:
+      - Devices
+  /web-push/configuration:
+    get:
+      operationId: getWebPushConfiguration
+      responses:
+        "200":
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/WebPushConfiguration"
+          description: Browser push configuration
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+      summary: Get browser push availability and its public VAPID key
+      tags:
+      - Devices
+  /web-push/subscriptions:
+    post:
+      operationId: registerWebPushSubscription
+      requestBody:
+        $ref: "#/components/requestBodies/RegisterWebPushSubscription"
+      responses:
+        "201":
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/WebPushSubscription"
+          description: Browser subscription registered
+        "400":
+          $ref: "#/components/responses/BadRequest"
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+      summary: Register or refresh a browser push subscription
+      tags:
+      - Devices
+  /web-push/subscriptions/{subscriptionId}:
+    delete:
+      operationId: removeWebPushSubscription
+      parameters:
+      - $ref: "#/components/parameters/SubscriptionId"
+      responses:
+        "200":
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/DisabledResponse"
+          description: Browser subscription disabled
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+      summary: Disable a browser push subscription
+      tags:
+      - Devices
+  /health:
+    get:
+      operationId: getHealth
+      responses:
+        "200":
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/HealthResponse"
+          description: Healthy
+      security: []
+      summary: Check Agent Push Kit API health
+      tags:
+      - Health
+  /mcp:
+    post:
+      description: This endpoint accepts only an `apt_` agent access token.
+      operationId: callMcp
+      requestBody:
+        content:
+          application/json:
+            schema:
+              additionalProperties: true
+              type: object
+        required: true
+      responses:
+        "200":
+          description: MCP JSON-RPC or SSE response
+        "202":
+          description: MCP notification accepted
+        "401":
+          $ref: "#/components/responses/Unauthorized"
+      security:
+      - AgentToken: []
+      summary: Connect through stateless MCP Streamable HTTP
+      tags:
+      - Agent tokens
+components:
+  parameters:
+    OrganizationId:
+      explode: false
+      in: path
+      name: organizationId
+      required: true
+      schema:
+        type: string
+      style: simple
+    TokenId:
+      explode: false
+      in: path
+      name: tokenId
+      required: true
+      schema:
+        type: string
+      style: simple
+    EventId:
+      explode: false
+      in: path
+      name: eventId
+      required: true
+      schema:
+        type: string
+      style: simple
+    ServiceId:
+      explode: false
+      in: path
+      name: serviceId
+      required: true
+      schema:
+        type: string
+      style: simple
+    TypePath:
+      explode: false
+      in: path
+      name: type
+      required: true
+      schema:
+        maxLength: 120
+        type: string
+      style: simple
+    InstallationId:
+      explode: false
+      in: path
+      name: installationId
+      required: true
+      schema:
+        maxLength: 200
+        minLength: 4
+        type: string
+      style: simple
+    SubscriptionId:
+      explode: false
+      in: path
+      name: subscriptionId
+      required: true
+      schema:
+        type: string
+      style: simple
+    ServiceName:
+      explode: true
+      in: query
+      name: service
+      required: false
+      schema:
+        maxLength: 120
+        type: string
+      style: form
+    EventType:
+      explode: true
+      in: query
+      name: type
+      required: false
+      schema:
+        maxLength: 120
+        type: string
+      style: form
+    SearchText:
+      explode: true
+      in: query
+      name: search
+      required: false
+      schema:
+        maxLength: 200
+        type: string
+      style: form
+    Cursor:
+      explode: true
+      in: query
+      name: cursor
+      required: false
+      schema:
+        type: string
+      style: form
+    Limit:
+      explode: true
+      in: query
+      name: limit
+      required: false
+      schema:
+        default: 50
+        maximum: 100
+        minimum: 1
+        type: integer
+      style: form
+  requestBodies:
+    Register:
+      content:
+        application/json:
+          example:
+            email: alex@example.com
+            password: correct horse battery staple
+            displayName: Alex
+          schema:
+            $ref: "#/components/schemas/RegisterInput"
+      required: true
+    PasswordLogin:
+      content:
+        application/json:
+          schema:
+            $ref: "#/components/schemas/PasswordLoginInput"
+      required: true
+    ProviderLogin:
+      content:
+        application/json:
+          schema:
+            $ref: "#/components/schemas/ProviderLoginInput"
+      required: true
+    PasswordResetRequest:
+      content:
+        application/json:
+          schema:
+            $ref: "#/components/schemas/PasswordResetRequestInput"
+      required: true
+    PasswordResetComplete:
+      content:
+        application/json:
+          schema:
+            $ref: "#/components/schemas/PasswordResetCompleteInput"
+      required: true
+    CreateOrganization:
+      content:
+        application/json:
+          schema:
+            $ref: "#/components/schemas/CreateOrganizationInput"
+      required: true
+    AddMember:
+      content:
+        application/json:
+          schema:
+            $ref: "#/components/schemas/AddMemberInput"
+      required: true
+    CreateAgentToken:
+      content:
+        application/json:
+          schema:
+            $ref: "#/components/schemas/CreateAgentTokenInput"
+      required: true
+    SendEvent:
+      content:
+        application/json:
+          example:
+            service: chatdna
+            type: user.signup
+            title: New user signup
+            body: alex@example.com created an account
+            externalId: signup_user_123
+            actionUrl: https://example.com/users/123
+            metadata:
+              userId: "123"
+              plan: trial
+          schema:
+            $ref: "#/components/schemas/SendEventInput"
+      required: true
+    SearchEvents:
+      content:
+        application/json:
+          example:
+            filter:
+              operator: AND
+              children:
+              - field: service
+                comparison: equals
+                value: chatdna
+              - field: body
+                comparison: contains
+                value: alex
+            limit: 50
+          schema:
+            $ref: "#/components/schemas/SearchEventsInput"
+      required: true
+    SetEnabled:
+      content:
+        application/json:
+          schema:
+            $ref: "#/components/schemas/SetEnabledInput"
+      required: true
+    RegisterDevice:
+      content:
+        application/json:
+          schema:
+            $ref: "#/components/schemas/RegisterDeviceInput"
+      required: true
+    RegisterWebPushSubscription:
+      content:
+        application/json:
+          schema:
+            $ref: "#/components/schemas/RegisterWebPushSubscriptionInput"
+      required: true
+  responses:
+    BadRequest:
+      content:
+        application/json:
+          schema:
+            $ref: "#/components/schemas/ErrorResponse"
+      description: Invalid request
+    Unauthorized:
+      content:
+        application/json:
+          schema:
+            $ref: "#/components/schemas/ErrorResponse"
+      description: "Missing, invalid, or revoked credentials"
+    Forbidden:
+      content:
+        application/json:
+          schema:
+            $ref: "#/components/schemas/ErrorResponse"
+      description: The operation requires an owner
+    NotFound:
+      content:
+        application/json:
+          schema:
+            $ref: "#/components/schemas/ErrorResponse"
+      description: The resource is absent or outside the current user's customer accounts
+    Conflict:
+      content:
+        application/json:
+          schema:
+            $ref: "#/components/schemas/ErrorResponse"
+      description: The requested identity or membership already exists
+  schemas:
+    RegisterInput:
+      additionalProperties: false
+      example:
+        email: email
+        password: password
+        displayName: displayName
+      properties:
+        email:
+          format: email
+          maxLength: 320
+          type: string
+        password:
+          maxLength: 200
+          minLength: 8
+          type: string
+        displayName:
+          maxLength: 120
+          type: string
+      required:
+      - email
+      - password
+    PasswordLoginInput:
+      additionalProperties: false
+      example:
+        email: email
+        password: password
+      properties:
+        email:
+          format: email
+          maxLength: 320
+          type: string
+        password:
+          maxLength: 200
+          minLength: 1
+          type: string
+      required:
+      - email
+      - password
+    ProviderLoginInput:
+      additionalProperties: false
+      example:
+        idToken: idToken
+        displayName: displayName
+      properties:
+        idToken:
+          minLength: 20
+          type: string
+        displayName:
+          maxLength: 120
+          type: string
+      required:
+      - idToken
+    PasswordResetRequestInput:
+      additionalProperties: false
+      example:
+        email: email
+      properties:
+        email:
+          format: email
+          maxLength: 320
+          type: string
+      required:
+      - email
+    PasswordResetCompleteInput:
+      additionalProperties: false
+      example:
+        token: token
+        password: password
+      properties:
+        token:
+          minLength: 20
+          type: string
+        password:
+          maxLength: 200
+          minLength: 8
+          type: string
+      required:
+      - password
+      - token
+    CreateOrganizationInput:
+      additionalProperties: false
+      example:
+        name: name
+      properties:
+        name:
+          maxLength: 120
+          minLength: 1
+          type: string
+      required:
+      - name
+    AddMemberInput:
+      additionalProperties: false
+      example:
+        email: email
+      properties:
+        email:
+          format: email
+          maxLength: 320
+          type: string
+      required:
+      - email
+    CreateAgentTokenInput:
+      additionalProperties: false
+      example:
+        name: name
+      properties:
+        name:
+          maxLength: 120
+          minLength: 1
+          type: string
+      required:
+      - name
+    SendEventInput:
+      additionalProperties: {}
+      example:
+        service: service
+        serviceDisplayName: serviceDisplayName
+        type: type
+        title: title
+        body: body
+        metadata:
+          key: ""
+        externalId: externalId
+        actionUrl: https://openapi-generator.tech
+      properties:
+        service:
+          maxLength: 120
+          minLength: 1
+          type: string
+        serviceDisplayName:
+          maxLength: 120
+          minLength: 1
+          type: string
+        type:
+          maxLength: 120
+          minLength: 1
+          type: string
+        title:
+          maxLength: 200
+          minLength: 1
+          type: string
+        body:
+          maxLength: 10000
+          minLength: 1
+          type: string
+        metadata:
+          additionalProperties: true
+          type: object
+        externalId:
+          maxLength: 300
+          minLength: 1
+          type: string
+        actionUrl:
+          format: uri
+          maxLength: 2000
+          type: string
+      required:
+      - body
+      - service
+      - title
+      - type
+    SearchEventsInput:
+      additionalProperties: false
+      example:
+        filter:
+          operator: AND
+          children:
+          - null
+          - null
+          - null
+          - null
+          - null
+        cursor: cursor
+        limit: 8
+      properties:
+        filter:
+          $ref: "#/components/schemas/EventFilter"
+        cursor:
+          type: string
+        limit:
+          default: 50
+          maximum: 100
+          minimum: 1
+          type: integer
+      required:
+      - filter
+    EventFilter:
+      oneOf:
+      - $ref: "#/components/schemas/FilterGroup"
+      - $ref: "#/components/schemas/FilterNot"
+      - $ref: "#/components/schemas/TextFilterCondition"
+      - $ref: "#/components/schemas/TimeFilterCondition"
+    FilterGroup:
+      additionalProperties: false
+      example:
+        operator: AND
+        children:
+        - null
+        - null
+        - null
+        - null
+        - null
+      properties:
+        operator:
+          enum:
+          - AND
+          - OR
+          type: string
+        children:
+          items:
+            $ref: "#/components/schemas/EventFilter"
+          maxItems: 10
+          minItems: 1
+          type: array
+          default: null
+      required:
+      - children
+      - operator
+    FilterNot:
+      additionalProperties: false
+      properties:
+        operator:
+          enum:
+          - NOT
+          type: string
+        child:
+          $ref: "#/components/schemas/EventFilter"
+      required:
+      - child
+      - operator
+    TextFilterCondition:
+      additionalProperties: false
+      properties:
+        field:
+          enum:
+          - service
+          - type
+          - title
+          - body
+          type: string
+        comparison:
+          enum:
+          - equals
+          - contains
+          type: string
+        value:
+          maxLength: 200
+          minLength: 1
+          type: string
+      required:
+      - comparison
+      - field
+      - value
+    TimeFilterCondition:
+      additionalProperties: false
+      properties:
+        field:
+          enum:
+          - createdAt
+          type: string
+        comparison:
+          enum:
+          - before
+          - after
+          - onOrBefore
+          - onOrAfter
+          - equals
+          type: string
+        value:
+          format: date-time
+          type: string
+      required:
+      - comparison
+      - field
+      - value
+    SetEnabledInput:
+      additionalProperties: false
+      example:
+        enabled: true
+      properties:
+        enabled:
+          type: boolean
+      required:
+      - enabled
+    RegisterDeviceInput:
+      additionalProperties: false
+      example:
+        deviceToken: deviceToken
+        installationId: installationId
+        environment: SANDBOX
+        appVersion: appVersion
+      properties:
+        deviceToken:
+          maxLength: 256
+          minLength: 32
+          type: string
+        installationId:
+          maxLength: 200
+          minLength: 4
+          type: string
+        environment:
+          enum:
+          - SANDBOX
+          - PRODUCTION
+          type: string
+        appVersion:
+          maxLength: 50
+          type: string
+      required:
+      - deviceToken
+      - environment
+      - installationId
+    RegisterWebPushSubscriptionInput:
+      additionalProperties: {}
+      example:
+        endpoint: https://openapi-generator.tech
+        keys:
+          p256dh: p256dh
+          auth: auth
+      properties:
+        endpoint:
+          format: uri
+          maxLength: 4000
+          type: string
+        keys:
+          $ref: "#/components/schemas/RegisterWebPushSubscriptionInput_keys"
+      required:
+      - endpoint
+      - keys
+    User:
+      example:
+        id: id
+        email: email
+        displayName: displayName
+        hasPassword: true
+        hasGoogle: true
+        hasApple: true
+      properties:
+        id:
+          type: string
+        email:
+          format: email
+          type: string
+        displayName:
+          nullable: true
+          type: string
+        hasPassword:
+          type: boolean
+        hasGoogle:
+          type: boolean
+        hasApple:
+          type: boolean
+      required:
+      - email
+      - hasApple
+      - hasGoogle
+      - hasPassword
+      - id
+    Organization:
+      example:
+        id: id
+        name: name
+        role: OWNER
+        createdAt: 2000-01-23T04:56:07.000+00:00
+        updatedAt: 2000-01-23T04:56:07.000+00:00
+        joinedAt: 2000-01-23T04:56:07.000+00:00
+        apiKey:
+          keyPrefix: keyPrefix
+          lastFour: lastFour
+          updatedAt: 2000-01-23T04:56:07.000+00:00
+        _count:
+          memberships: 0
+          services: 6
+      properties:
+        id:
+          type: string
+        name:
+          type: string
+        role:
+          enum:
+          - OWNER
+          - MEMBER
+          type: string
+        createdAt:
+          format: date-time
+          type: string
+        updatedAt:
+          format: date-time
+          type: string
+        joinedAt:
+          format: date-time
+          type: string
+        apiKey:
+          $ref: "#/components/schemas/ApiKeySummary"
+        _count:
+          $ref: "#/components/schemas/Organization__count"
+      required:
+      - createdAt
+      - id
+      - joinedAt
+      - name
+      - role
+      - updatedAt
+    ApiKeySummary:
+      example:
+        keyPrefix: keyPrefix
+        lastFour: lastFour
+        updatedAt: 2000-01-23T04:56:07.000+00:00
+      nullable: true
+      properties:
+        keyPrefix:
+          type: string
+        lastFour:
+          type: string
+        updatedAt:
+          format: date-time
+          type: string
+      type: object
+    Membership:
+      example:
+        id: id
+        role: OWNER
+        createdAt: 2000-01-23T04:56:07.000+00:00
+        user:
+          id: id
+          email: email
+          displayName: displayName
+      properties:
+        id:
+          type: string
+        role:
+          enum:
+          - OWNER
+          - MEMBER
+          type: string
+        createdAt:
+          format: date-time
+          type: string
+        user:
+          $ref: "#/components/schemas/Membership_user"
+      required:
+      - createdAt
+      - id
+      - role
+      - user
+    AgentToken:
+      example:
+        id: id
+        name: name
+        keyPrefix: keyPrefix
+        lastFour: lastFour
+        createdAt: 2000-01-23T04:56:07.000+00:00
+        lastUsedAt: 2000-01-23T04:56:07.000+00:00
+        revokedAt: 2000-01-23T04:56:07.000+00:00
+      properties:
+        id:
+          type: string
+        name:
+          type: string
+        keyPrefix:
+          type: string
+        lastFour:
+          type: string
+        createdAt:
+          format: date-time
+          type: string
+        lastUsedAt:
+          format: date-time
+          nullable: true
+          type: string
+        revokedAt:
+          format: date-time
+          nullable: true
+          type: string
+      required:
+      - createdAt
+      - id
+      - keyPrefix
+      - lastFour
+      - name
+    ServiceSummary:
+      example:
+        id: id
+        name: name
+        displayName: displayName
+      properties:
+        id:
+          type: string
+        name:
+          type: string
+        displayName:
+          type: string
+      required:
+      - displayName
+      - id
+      - name
+    Service:
+      allOf:
+      - $ref: "#/components/schemas/ServiceSummary"
+      - properties:
+          createdAt:
+            format: date-time
+            type: string
+          _count:
+            $ref: "#/components/schemas/Service_allOf__count"
+        required:
+        - _count
+        - createdAt
+      example:
+        id: id
+        name: name
+        displayName: displayName
+        createdAt: 2000-01-23T04:56:07.000+00:00
+        _count:
+          events: 0
+    EventSummary:
+      example:
+        id: id
+        type: type
+        title: title
+        body: body
+        externalId: externalId
+        actionUrl: https://openapi-generator.tech
+        createdAt: 2000-01-23T04:56:07.000+00:00
+        service:
+          id: id
+          name: name
+          displayName: displayName
+      properties:
+        id:
+          type: string
+        type:
+          type: string
+        title:
+          type: string
+        body:
+          type: string
+        externalId:
+          nullable: true
+          type: string
+        actionUrl:
+          format: uri
+          nullable: true
+          type: string
+        createdAt:
+          format: date-time
+          type: string
+        service:
+          $ref: "#/components/schemas/ServiceSummary"
+      required:
+      - body
+      - createdAt
+      - id
+      - service
+      - title
+      - type
+    EventDetail:
+      allOf:
+      - $ref: "#/components/schemas/EventSummary"
+      - properties:
+          serviceId:
+            type: string
+          metadata:
+            additionalProperties: true
+            nullable: true
+            type: object
+        required:
+        - serviceId
+      example:
+        id: id
+        type: type
+        title: title
+        body: body
+        externalId: externalId
+        actionUrl: https://openapi-generator.tech
+        createdAt: 2000-01-23T04:56:07.000+00:00
+        service:
+          id: id
+          name: name
+          displayName: displayName
+        serviceId: serviceId
+        metadata:
+          key: ""
+    EventPage:
+      example:
+        events:
+        - id: id
+          type: type
+          title: title
+          body: body
+          externalId: externalId
+          actionUrl: https://openapi-generator.tech
+          createdAt: 2000-01-23T04:56:07.000+00:00
+          service:
+            id: id
+            name: name
+            displayName: displayName
+        - id: id
+          type: type
+          title: title
+          body: body
+          externalId: externalId
+          actionUrl: https://openapi-generator.tech
+          createdAt: 2000-01-23T04:56:07.000+00:00
+          service:
+            id: id
+            name: name
+            displayName: displayName
+        nextCursor: nextCursor
+      properties:
+        events:
+          items:
+            $ref: "#/components/schemas/EventSummary"
+          type: array
+          default: null
+        nextCursor:
+          nullable: true
+          type: string
+      required:
+      - events
+    DeliverySummary:
+      example:
+        sent: 0
+        failed: 6
+        suppressedUsers: 1
+        eligibleDevices: 5
+      properties:
+        sent:
+          type: integer
+        failed:
+          type: integer
+        suppressedUsers:
+          type: integer
+        eligibleDevices:
+          type: integer
+      required:
+      - eligibleDevices
+      - failed
+      - sent
+      - suppressedUsers
+    IngestionResult:
+      example:
+        event:
+          id: id
+          type: type
+          title: title
+          body: body
+          externalId: externalId
+          actionUrl: https://openapi-generator.tech
+          createdAt: 2000-01-23T04:56:07.000+00:00
+          service:
+            id: id
+            name: name
+            displayName: displayName
+          serviceId: serviceId
+          metadata:
+            key: ""
+        duplicate: true
+        delivery:
+          sent: 0
+          failed: 6
+          suppressedUsers: 1
+          eligibleDevices: 5
+      properties:
+        event:
+          $ref: "#/components/schemas/EventDetail"
+        duplicate:
+          type: boolean
+        delivery:
+          $ref: "#/components/schemas/DeliverySummary"
+      required:
+      - delivery
+      - duplicate
+      - event
+    TypeOverride:
+      example:
+        type: type
+        enabled: true
+        updatedAt: 2000-01-23T04:56:07.000+00:00
+      properties:
+        type:
+          type: string
+        enabled:
+          type: boolean
+        updatedAt:
+          format: date-time
+          type: string
+      required:
+      - enabled
+      - type
+      - updatedAt
+    ServicePreference:
+      example:
+        id: id
+        name: name
+        displayName: displayName
+        enabled: true
+        typeOverrides:
+        - type: type
+          enabled: true
+          updatedAt: 2000-01-23T04:56:07.000+00:00
+        - type: type
+          enabled: true
+          updatedAt: 2000-01-23T04:56:07.000+00:00
+      properties:
+        id:
+          type: string
+        name:
+          type: string
+        displayName:
+          type: string
+        enabled:
+          type: boolean
+        typeOverrides:
+          items:
+            $ref: "#/components/schemas/TypeOverride"
+          type: array
+          default: null
+      required:
+      - displayName
+      - enabled
+      - id
+      - name
+      - typeOverrides
+    PreferenceRecord:
+      example:
+        serviceId: serviceId
+        typeKey: typeKey
+        enabled: true
+        updatedAt: 2000-01-23T04:56:07.000+00:00
+      properties:
+        serviceId:
+          type: string
+        typeKey:
+          type: string
+        enabled:
+          type: boolean
+        updatedAt:
+          format: date-time
+          type: string
+      required:
+      - enabled
+      - serviceId
+      - typeKey
+      - updatedAt
+    Device:
+      example:
+        id: id
+        installationId: installationId
+        environment: SANDBOX
+        appVersion: appVersion
+        enabled: true
+        lastSeenAt: 2000-01-23T04:56:07.000+00:00
+      properties:
+        id:
+          type: string
+        installationId:
+          type: string
+        environment:
+          enum:
+          - SANDBOX
+          - PRODUCTION
+          type: string
+        appVersion:
+          nullable: true
+          type: string
+        enabled:
+          type: boolean
+        lastSeenAt:
+          format: date-time
+          type: string
+      required:
+      - enabled
+      - environment
+      - id
+      - installationId
+      - lastSeenAt
+    WebPushConfiguration:
+      example:
+        enabled: true
+        publicKey: publicKey
+      properties:
+        enabled:
+          type: boolean
+        publicKey:
+          nullable: true
+          type: string
+      required:
+      - enabled
+    WebPushSubscription:
+      example:
+        id: id
+        enabled: true
+        lastSeenAt: 2000-01-23T04:56:07.000+00:00
+      properties:
+        id:
+          type: string
+        enabled:
+          type: boolean
+        lastSeenAt:
+          format: date-time
+          type: string
+      required:
+      - enabled
+      - id
+      - lastSeenAt
+    HealthResponse:
+      example:
+        status: ok
+        service: agent-push-kit
+      properties:
+        status:
+          enum:
+          - ok
+          type: string
+        service:
+          enum:
+          - agent-push-kit
+          type: string
+      required:
+      - service
+      - status
+    AuthResponse:
+      example:
+        accessToken: accessToken
+        user:
+          id: id
+          email: email
+          displayName: displayName
+          hasPassword: true
+          hasGoogle: true
+          hasApple: true
+        organizations:
+        - id: id
+          name: name
+          role: OWNER
+          createdAt: 2000-01-23T04:56:07.000+00:00
+          updatedAt: 2000-01-23T04:56:07.000+00:00
+          joinedAt: 2000-01-23T04:56:07.000+00:00
+          apiKey:
+            keyPrefix: keyPrefix
+            lastFour: lastFour
+            updatedAt: 2000-01-23T04:56:07.000+00:00
+          _count:
+            memberships: 0
+            services: 6
+        - id: id
+          name: name
+          role: OWNER
+          createdAt: 2000-01-23T04:56:07.000+00:00
+          updatedAt: 2000-01-23T04:56:07.000+00:00
+          joinedAt: 2000-01-23T04:56:07.000+00:00
+          apiKey:
+            keyPrefix: keyPrefix
+            lastFour: lastFour
+            updatedAt: 2000-01-23T04:56:07.000+00:00
+          _count:
+            memberships: 0
+            services: 6
+        bootstrapApiKey: bootstrapApiKey
+      properties:
+        accessToken:
+          type: string
+        user:
+          $ref: "#/components/schemas/User"
+        organizations:
+          items:
+            $ref: "#/components/schemas/Organization"
+          type: array
+          default: null
+        bootstrapApiKey:
+          description: Present only when a new customer account was created.
+          type: string
+      required:
+      - accessToken
+      - organizations
+      - user
+    CurrentAccount:
+      example:
+        user:
+          id: id
+          email: email
+          displayName: displayName
+          hasPassword: true
+          hasGoogle: true
+          hasApple: true
+        organizations:
+        - id: id
+          name: name
+          role: OWNER
+          createdAt: 2000-01-23T04:56:07.000+00:00
+          updatedAt: 2000-01-23T04:56:07.000+00:00
+          joinedAt: 2000-01-23T04:56:07.000+00:00
+          apiKey:
+            keyPrefix: keyPrefix
+            lastFour: lastFour
+            updatedAt: 2000-01-23T04:56:07.000+00:00
+          _count:
+            memberships: 0
+            services: 6
+        - id: id
+          name: name
+          role: OWNER
+          createdAt: 2000-01-23T04:56:07.000+00:00
+          updatedAt: 2000-01-23T04:56:07.000+00:00
+          joinedAt: 2000-01-23T04:56:07.000+00:00
+          apiKey:
+            keyPrefix: keyPrefix
+            lastFour: lastFour
+            updatedAt: 2000-01-23T04:56:07.000+00:00
+          _count:
+            memberships: 0
+            services: 6
+      properties:
+        user:
+          $ref: "#/components/schemas/User"
+        organizations:
+          items:
+            $ref: "#/components/schemas/Organization"
+          type: array
+          default: null
+      required:
+      - organizations
+      - user
+    OrganizationRecord:
+      example:
+        id: id
+        name: name
+        createdAt: 2000-01-23T04:56:07.000+00:00
+        updatedAt: 2000-01-23T04:56:07.000+00:00
+      properties:
+        id:
+          type: string
+        name:
+          type: string
+        createdAt:
+          format: date-time
+          type: string
+        updatedAt:
+          format: date-time
+          type: string
+      required:
+      - createdAt
+      - id
+      - name
+      - updatedAt
+    OrganizationCreated:
+      example:
+        organization:
+          id: id
+          name: name
+          createdAt: 2000-01-23T04:56:07.000+00:00
+          updatedAt: 2000-01-23T04:56:07.000+00:00
+        apiKey: apiKey
+      properties:
+        organization:
+          $ref: "#/components/schemas/OrganizationRecord"
+        apiKey:
+          pattern: ^apk_
+          type: string
+      required:
+      - apiKey
+      - organization
+    OrganizationApiKeyCreated:
+      example:
+        keyPrefix: keyPrefix
+        lastFour: lastFour
+        updatedAt: 2000-01-23T04:56:07.000+00:00
+        apiKey: apiKey
+      properties:
+        keyPrefix:
+          type: string
+        lastFour:
+          type: string
+        updatedAt:
+          format: date-time
+          type: string
+        apiKey:
+          pattern: ^apk_
+          type: string
+      required:
+      - apiKey
+      - keyPrefix
+      - lastFour
+      - updatedAt
+    AgentTokenCreated:
+      allOf:
+      - $ref: "#/components/schemas/AgentToken"
+      - properties:
+          token:
+            pattern: ^apt_
+            type: string
+        required:
+        - token
+      example:
+        id: id
+        name: name
+        keyPrefix: keyPrefix
+        lastFour: lastFour
+        createdAt: 2000-01-23T04:56:07.000+00:00
+        lastUsedAt: 2000-01-23T04:56:07.000+00:00
+        revokedAt: 2000-01-23T04:56:07.000+00:00
+        token: token
+    AcceptedResponse:
+      example:
+        accepted: true
+      properties:
+        accepted:
+          type: boolean
+      required:
+      - accepted
+    DeletedResponse:
+      example:
+        deleted: true
+      properties:
+        deleted:
+          type: boolean
+      required:
+      - deleted
+    RevokedResponse:
+      example:
+        revoked: true
+      properties:
+        revoked:
+          type: boolean
+      required:
+      - revoked
+    InheritedResponse:
+      example:
+        inherited: true
+      properties:
+        inherited:
+          type: boolean
+      required:
+      - inherited
+    DisabledResponse:
+      example:
+        disabled: true
+      properties:
+        disabled:
+          type: boolean
+      required:
+      - disabled
+    ErrorResponse:
+      example:
+        statusCode: 1
+        message: message
+        error: error
+      properties:
+        statusCode:
+          type: integer
+        message:
+          type: string
+        error:
+          type: string
+      required:
+      - message
+      - statusCode
+    RegisterWebPushSubscriptionInput_keys:
+      additionalProperties: false
+      example:
+        p256dh: p256dh
+        auth: auth
+      properties:
+        p256dh:
+          maxLength: 500
+          minLength: 20
+          type: string
+        auth:
+          maxLength: 200
+          minLength: 8
+          type: string
+      required:
+      - auth
+      - p256dh
+    Organization__count:
+      example:
+        memberships: 0
+        services: 6
+      properties:
+        memberships:
+          type: integer
+        services:
+          type: integer
+    Membership_user:
+      example:
+        id: id
+        email: email
+        displayName: displayName
+      properties:
+        id:
+          type: string
+        email:
+          format: email
+          type: string
+        displayName:
+          nullable: true
+          type: string
+      required:
+      - email
+      - id
+    Service_allOf__count:
+      example:
+        events: 0
+      properties:
+        events:
+          type: integer
+      required:
+      - events
+  securitySchemes:
+    UserOrAgent:
+      bearerFormat: Agent Push Kit JWT or apt_ token
+      description: Use the login JWT in the human app or a named `apt_` token for
+        agents.
+      scheme: bearer
+      type: http
+    AgentToken:
+      bearerFormat: apt_
+      description: A named agent access token created by an authenticated user.
+      scheme: bearer
+      type: http
+    OrganizationApiKey:
+      bearerFormat: apk_
+      description: An organization-level application ingestion key.
+      scheme: bearer
+      type: http
diff --git a/tests/ApproxEq.hs b/tests/ApproxEq.hs
new file mode 100644
--- /dev/null
+++ b/tests/ApproxEq.hs
@@ -0,0 +1,81 @@
+{-# LANGUAGE DefaultSignatures #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE TypeOperators #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+
+module ApproxEq where
+
+import Data.Text (Text)
+import Data.Time.Clock
+import Test.QuickCheck
+import GHC.Generics as G
+
+(==~)
+  :: (ApproxEq a, Show a)
+  => a -> a -> Property
+a ==~ b = counterexample (show a ++ " !=~ " ++ show b) (a =~ b)
+
+class GApproxEq f  where
+  gApproxEq :: f a -> f a -> Bool
+
+instance GApproxEq U1 where
+  gApproxEq U1 U1 = True
+
+instance (GApproxEq a, GApproxEq b) =>
+         GApproxEq (a :+: b) where
+  gApproxEq (L1 a) (L1 b) = gApproxEq a b
+  gApproxEq (R1 a) (R1 b) = gApproxEq a b
+  gApproxEq _ _ = False
+
+instance (GApproxEq a, GApproxEq b) =>
+         GApproxEq (a :*: b) where
+  gApproxEq (a1 :*: b1) (a2 :*: b2) = gApproxEq a1 a2 && gApproxEq b1 b2
+
+instance (ApproxEq a) =>
+         GApproxEq (K1 i a) where
+  gApproxEq (K1 a) (K1 b) = a =~ b
+
+instance (GApproxEq f) =>
+         GApproxEq (M1 i t f) where
+  gApproxEq (M1 a) (M1 b) = gApproxEq a b
+
+class ApproxEq a  where
+  (=~) :: a -> a -> Bool
+  default (=~) :: (Generic a, GApproxEq (Rep a)) => a -> a -> Bool
+  a =~ b = gApproxEq (G.from a) (G.from b)
+
+instance ApproxEq Text where
+  (=~) = (==)
+
+instance ApproxEq Char where
+  (=~) = (==)
+
+instance ApproxEq Bool where
+  (=~) = (==)
+
+instance ApproxEq Int where
+  (=~) = (==)
+
+instance ApproxEq Double where
+  (=~) = (==)
+
+instance ApproxEq a =>
+         ApproxEq (Maybe a)
+
+instance ApproxEq UTCTime where
+  (=~) = (==)
+
+instance ApproxEq a =>
+         ApproxEq [a] where
+  as =~ bs = and (zipWith (=~) as bs)
+
+instance (ApproxEq l, ApproxEq r) =>
+         ApproxEq (Either l r) where
+  Left a =~ Left b = a =~ b
+  Right a =~ Right b = a =~ b
+  _ =~ _ = False
+
+instance (ApproxEq l, ApproxEq r) =>
+         ApproxEq (l, r) where
+  (=~) (l1, r1) (l2, r2) = l1 =~ l2 && r1 =~ r2
diff --git a/tests/Instances.hs b/tests/Instances.hs
new file mode 100644
--- /dev/null
+++ b/tests/Instances.hs
@@ -0,0 +1,694 @@
+{-# LANGUAGE CPP #-}
+{-# OPTIONS_GHC -fno-warn-unused-imports -fno-warn-unused-matches #-}
+
+module Instances where
+
+import AgentPushKit.Model
+import AgentPushKit.Core
+
+import qualified Data.Aeson as A
+import qualified Data.ByteString.Lazy as BL
+import qualified Data.HashMap.Strict as HM
+import qualified Data.Set as Set
+import qualified Data.Text as T
+import qualified Data.Time as TI
+import qualified Data.Vector as V
+import Data.String (fromString)
+
+import Control.Monad
+import Data.Char (isSpace)
+import Data.List (sort)
+import Test.QuickCheck
+
+import ApproxEq
+
+instance Arbitrary T.Text where
+  arbitrary = T.pack <$> arbitrary
+
+instance Arbitrary TI.Day where
+  arbitrary = TI.ModifiedJulianDay . (2000 +) <$> arbitrary
+  shrink = (TI.ModifiedJulianDay <$>) . shrink . TI.toModifiedJulianDay
+
+instance Arbitrary TI.UTCTime where
+  arbitrary =
+    TI.UTCTime <$> arbitrary <*> (TI.secondsToDiffTime <$> choose (0, 86401))
+
+instance Arbitrary BL.ByteString where
+    arbitrary = BL.pack <$> arbitrary
+    shrink xs = BL.pack <$> shrink (BL.unpack xs)
+
+instance Arbitrary ByteArray where
+    arbitrary = ByteArray <$> arbitrary
+    shrink (ByteArray xs) = ByteArray <$> shrink xs
+
+instance Arbitrary Binary where
+    arbitrary = Binary <$> arbitrary
+    shrink (Binary xs) = Binary <$> shrink xs
+
+instance Arbitrary DateTime where
+    arbitrary = DateTime <$> arbitrary
+    shrink (DateTime xs) = DateTime <$> shrink xs
+
+instance Arbitrary Date where
+    arbitrary = Date <$> arbitrary
+    shrink (Date xs) = Date <$> shrink xs
+
+#if MIN_VERSION_aeson(2,0,0)
+#else
+-- | A naive Arbitrary instance for A.Value:
+instance Arbitrary A.Value where
+  arbitrary = arbitraryValue
+#endif
+
+arbitraryValue :: Gen A.Value
+arbitraryValue =
+  frequency [(3, simpleTypes), (1, arrayTypes), (1, objectTypes)]
+    where
+      simpleTypes :: Gen A.Value
+      simpleTypes =
+        frequency
+          [ (1, return A.Null)
+          , (2, liftM A.Bool (arbitrary :: Gen Bool))
+          , (2, liftM (A.Number . fromIntegral) (arbitrary :: Gen Int))
+          , (2, liftM (A.String . T.pack) (arbitrary :: Gen String))
+          ]
+      mapF (k, v) = (fromString k, v)
+      simpleAndArrays = frequency [(1, sized sizedArray), (4, simpleTypes)]
+      arrayTypes = sized sizedArray
+      objectTypes = sized sizedObject
+      sizedArray n = liftM (A.Array . V.fromList) $ replicateM n simpleTypes
+      sizedObject n =
+        liftM (A.object . map mapF) $
+        replicateM n $ (,) <$> (arbitrary :: Gen String) <*> simpleAndArrays
+
+-- | Checks if a given list has no duplicates in _O(n log n)_.
+hasNoDups
+  :: (Ord a)
+  => [a] -> Bool
+hasNoDups = go Set.empty
+  where
+    go _ [] = True
+    go s (x:xs)
+      | s' <- Set.insert x s
+      , Set.size s' > Set.size s = go s' xs
+      | otherwise = False
+
+instance ApproxEq TI.Day where
+  (=~) = (==)
+
+arbitraryReduced :: Arbitrary a => Int -> Gen a
+arbitraryReduced n = resize (n `div` 2) arbitrary
+
+arbitraryReducedMaybe :: Arbitrary a => Int -> Gen (Maybe a)
+arbitraryReducedMaybe 0 = elements [Nothing]
+arbitraryReducedMaybe n = arbitraryReduced n
+
+arbitraryReducedMaybeValue :: Int -> Gen (Maybe A.Value)
+arbitraryReducedMaybeValue 0 = elements [Nothing]
+arbitraryReducedMaybeValue n = do
+  generated <- arbitraryReduced n
+  if generated == Just A.Null
+    then return Nothing
+    else return generated
+
+-- * Models
+
+instance Arbitrary AcceptedResponse where
+  arbitrary = sized genAcceptedResponse
+
+genAcceptedResponse :: Int -> Gen AcceptedResponse
+genAcceptedResponse n =
+  AcceptedResponse
+    <$> arbitrary -- acceptedResponseAccepted :: Bool
+  
+instance Arbitrary AddMemberInput where
+  arbitrary = sized genAddMemberInput
+
+genAddMemberInput :: Int -> Gen AddMemberInput
+genAddMemberInput n =
+  AddMemberInput
+    <$> arbitrary -- addMemberInputEmail :: Text
+  
+instance Arbitrary AgentToken where
+  arbitrary = sized genAgentToken
+
+genAgentToken :: Int -> Gen AgentToken
+genAgentToken n =
+  AgentToken
+    <$> arbitrary -- agentTokenId :: Text
+    <*> arbitrary -- agentTokenName :: Text
+    <*> arbitrary -- agentTokenKeyPrefix :: Text
+    <*> arbitrary -- agentTokenLastFour :: Text
+    <*> arbitraryReduced n -- agentTokenCreatedAt :: DateTime
+    <*> arbitraryReducedMaybe n -- agentTokenLastUsedAt :: Maybe DateTime
+    <*> arbitraryReducedMaybe n -- agentTokenRevokedAt :: Maybe DateTime
+  
+instance Arbitrary AgentTokenCreated where
+  arbitrary = sized genAgentTokenCreated
+
+genAgentTokenCreated :: Int -> Gen AgentTokenCreated
+genAgentTokenCreated n =
+  AgentTokenCreated
+    <$> arbitrary -- agentTokenCreatedId :: Text
+    <*> arbitrary -- agentTokenCreatedName :: Text
+    <*> arbitrary -- agentTokenCreatedKeyPrefix :: Text
+    <*> arbitrary -- agentTokenCreatedLastFour :: Text
+    <*> arbitraryReduced n -- agentTokenCreatedCreatedAt :: DateTime
+    <*> arbitraryReducedMaybe n -- agentTokenCreatedLastUsedAt :: Maybe DateTime
+    <*> arbitraryReducedMaybe n -- agentTokenCreatedRevokedAt :: Maybe DateTime
+    <*> arbitrary -- agentTokenCreatedToken :: Text
+  
+instance Arbitrary ApiKeySummary where
+  arbitrary = sized genApiKeySummary
+
+genApiKeySummary :: Int -> Gen ApiKeySummary
+genApiKeySummary n =
+  ApiKeySummary
+    <$> arbitraryReducedMaybe n -- apiKeySummaryKeyPrefix :: Maybe Text
+    <*> arbitraryReducedMaybe n -- apiKeySummaryLastFour :: Maybe Text
+    <*> arbitraryReducedMaybe n -- apiKeySummaryUpdatedAt :: Maybe DateTime
+  
+instance Arbitrary AuthResponse where
+  arbitrary = sized genAuthResponse
+
+genAuthResponse :: Int -> Gen AuthResponse
+genAuthResponse n =
+  AuthResponse
+    <$> arbitrary -- authResponseAccessToken :: Text
+    <*> arbitraryReduced n -- authResponseUser :: User
+    <*> arbitraryReduced n -- authResponseOrganizations :: [Organization]
+    <*> arbitraryReducedMaybe n -- authResponseBootstrapApiKey :: Maybe Text
+  
+instance Arbitrary CreateAgentTokenInput where
+  arbitrary = sized genCreateAgentTokenInput
+
+genCreateAgentTokenInput :: Int -> Gen CreateAgentTokenInput
+genCreateAgentTokenInput n =
+  CreateAgentTokenInput
+    <$> arbitrary -- createAgentTokenInputName :: Text
+  
+instance Arbitrary CreateOrganizationInput where
+  arbitrary = sized genCreateOrganizationInput
+
+genCreateOrganizationInput :: Int -> Gen CreateOrganizationInput
+genCreateOrganizationInput n =
+  CreateOrganizationInput
+    <$> arbitrary -- createOrganizationInputName :: Text
+  
+instance Arbitrary CurrentAccount where
+  arbitrary = sized genCurrentAccount
+
+genCurrentAccount :: Int -> Gen CurrentAccount
+genCurrentAccount n =
+  CurrentAccount
+    <$> arbitraryReduced n -- currentAccountUser :: User
+    <*> arbitraryReduced n -- currentAccountOrganizations :: [Organization]
+  
+instance Arbitrary DeletedResponse where
+  arbitrary = sized genDeletedResponse
+
+genDeletedResponse :: Int -> Gen DeletedResponse
+genDeletedResponse n =
+  DeletedResponse
+    <$> arbitrary -- deletedResponseDeleted :: Bool
+  
+instance Arbitrary DeliverySummary where
+  arbitrary = sized genDeliverySummary
+
+genDeliverySummary :: Int -> Gen DeliverySummary
+genDeliverySummary n =
+  DeliverySummary
+    <$> arbitrary -- deliverySummarySent :: Int
+    <*> arbitrary -- deliverySummaryFailed :: Int
+    <*> arbitrary -- deliverySummarySuppressedUsers :: Int
+    <*> arbitrary -- deliverySummaryEligibleDevices :: Int
+  
+instance Arbitrary Device where
+  arbitrary = sized genDevice
+
+genDevice :: Int -> Gen Device
+genDevice n =
+  Device
+    <$> arbitrary -- deviceId :: Text
+    <*> arbitrary -- deviceInstallationId :: Text
+    <*> arbitrary -- deviceEnvironment :: E'Environment
+    <*> arbitraryReducedMaybe n -- deviceAppVersion :: Maybe Text
+    <*> arbitrary -- deviceEnabled :: Bool
+    <*> arbitraryReduced n -- deviceLastSeenAt :: DateTime
+  
+instance Arbitrary DisabledResponse where
+  arbitrary = sized genDisabledResponse
+
+genDisabledResponse :: Int -> Gen DisabledResponse
+genDisabledResponse n =
+  DisabledResponse
+    <$> arbitrary -- disabledResponseDisabled :: Bool
+  
+instance Arbitrary ErrorResponse where
+  arbitrary = sized genErrorResponse
+
+genErrorResponse :: Int -> Gen ErrorResponse
+genErrorResponse n =
+  ErrorResponse
+    <$> arbitrary -- errorResponseStatusCode :: Int
+    <*> arbitrary -- errorResponseMessage :: Text
+    <*> arbitraryReducedMaybe n -- errorResponseError :: Maybe Text
+  
+instance Arbitrary EventDetail where
+  arbitrary = sized genEventDetail
+
+genEventDetail :: Int -> Gen EventDetail
+genEventDetail n =
+  EventDetail
+    <$> arbitrary -- eventDetailId :: Text
+    <*> arbitrary -- eventDetailType :: Text
+    <*> arbitrary -- eventDetailTitle :: Text
+    <*> arbitrary -- eventDetailBody :: Text
+    <*> arbitraryReducedMaybe n -- eventDetailExternalId :: Maybe Text
+    <*> arbitraryReducedMaybe n -- eventDetailActionUrl :: Maybe Text
+    <*> arbitraryReduced n -- eventDetailCreatedAt :: DateTime
+    <*> arbitraryReduced n -- eventDetailService :: ServiceSummary
+    <*> arbitrary -- eventDetailServiceId :: Text
+    <*> arbitraryReducedMaybe n -- eventDetailMetadata :: Maybe (Map.Map String AnyType)
+  
+instance Arbitrary EventFilter where
+  arbitrary = sized genEventFilter
+
+genEventFilter :: Int -> Gen EventFilter
+genEventFilter n =
+  EventFilter
+    <$> arbitrary -- eventFilterOperator :: E'Operator
+    <*> arbitraryReduced n -- eventFilterChildren :: [EventFilter]
+    <*> arbitraryReduced n -- eventFilterChild :: EventFilter
+    <*> arbitrary -- eventFilterField :: E'Field
+    <*> arbitrary -- eventFilterComparison :: E'Comparison
+    <*> arbitraryReduced n -- eventFilterValue :: DateTime
+  
+instance Arbitrary EventPage where
+  arbitrary = sized genEventPage
+
+genEventPage :: Int -> Gen EventPage
+genEventPage n =
+  EventPage
+    <$> arbitraryReduced n -- eventPageEvents :: [EventSummary]
+    <*> arbitraryReducedMaybe n -- eventPageNextCursor :: Maybe Text
+  
+instance Arbitrary EventSummary where
+  arbitrary = sized genEventSummary
+
+genEventSummary :: Int -> Gen EventSummary
+genEventSummary n =
+  EventSummary
+    <$> arbitrary -- eventSummaryId :: Text
+    <*> arbitrary -- eventSummaryType :: Text
+    <*> arbitrary -- eventSummaryTitle :: Text
+    <*> arbitrary -- eventSummaryBody :: Text
+    <*> arbitraryReducedMaybe n -- eventSummaryExternalId :: Maybe Text
+    <*> arbitraryReducedMaybe n -- eventSummaryActionUrl :: Maybe Text
+    <*> arbitraryReduced n -- eventSummaryCreatedAt :: DateTime
+    <*> arbitraryReduced n -- eventSummaryService :: ServiceSummary
+  
+instance Arbitrary FilterGroup where
+  arbitrary = sized genFilterGroup
+
+genFilterGroup :: Int -> Gen FilterGroup
+genFilterGroup n =
+  FilterGroup
+    <$> arbitrary -- filterGroupOperator :: E'Operator2
+    <*> arbitraryReduced n -- filterGroupChildren :: [EventFilter]
+  
+instance Arbitrary FilterNot where
+  arbitrary = sized genFilterNot
+
+genFilterNot :: Int -> Gen FilterNot
+genFilterNot n =
+  FilterNot
+    <$> arbitrary -- filterNotOperator :: E'Operator
+    <*> arbitraryReduced n -- filterNotChild :: EventFilter
+  
+instance Arbitrary HealthResponse where
+  arbitrary = sized genHealthResponse
+
+genHealthResponse :: Int -> Gen HealthResponse
+genHealthResponse n =
+  HealthResponse
+    <$> arbitrary -- healthResponseStatus :: E'Status
+    <*> arbitrary -- healthResponseService :: E'Service
+  
+instance Arbitrary IngestionResult where
+  arbitrary = sized genIngestionResult
+
+genIngestionResult :: Int -> Gen IngestionResult
+genIngestionResult n =
+  IngestionResult
+    <$> arbitraryReduced n -- ingestionResultEvent :: EventDetail
+    <*> arbitrary -- ingestionResultDuplicate :: Bool
+    <*> arbitraryReduced n -- ingestionResultDelivery :: DeliverySummary
+  
+instance Arbitrary InheritedResponse where
+  arbitrary = sized genInheritedResponse
+
+genInheritedResponse :: Int -> Gen InheritedResponse
+genInheritedResponse n =
+  InheritedResponse
+    <$> arbitrary -- inheritedResponseInherited :: Bool
+  
+instance Arbitrary Membership where
+  arbitrary = sized genMembership
+
+genMembership :: Int -> Gen Membership
+genMembership n =
+  Membership
+    <$> arbitrary -- membershipId :: Text
+    <*> arbitrary -- membershipRole :: E'Role
+    <*> arbitraryReduced n -- membershipCreatedAt :: DateTime
+    <*> arbitraryReduced n -- membershipUser :: MembershipUser
+  
+instance Arbitrary MembershipUser where
+  arbitrary = sized genMembershipUser
+
+genMembershipUser :: Int -> Gen MembershipUser
+genMembershipUser n =
+  MembershipUser
+    <$> arbitrary -- membershipUserId :: Text
+    <*> arbitrary -- membershipUserEmail :: Text
+    <*> arbitraryReducedMaybe n -- membershipUserDisplayName :: Maybe Text
+  
+instance Arbitrary Organization where
+  arbitrary = sized genOrganization
+
+genOrganization :: Int -> Gen Organization
+genOrganization n =
+  Organization
+    <$> arbitrary -- organizationId :: Text
+    <*> arbitrary -- organizationName :: Text
+    <*> arbitrary -- organizationRole :: E'Role
+    <*> arbitraryReduced n -- organizationCreatedAt :: DateTime
+    <*> arbitraryReduced n -- organizationUpdatedAt :: DateTime
+    <*> arbitraryReduced n -- organizationJoinedAt :: DateTime
+    <*> arbitraryReducedMaybe n -- organizationApiKey :: Maybe ApiKeySummary
+    <*> arbitraryReducedMaybe n -- organizationCount :: Maybe OrganizationCount
+  
+instance Arbitrary OrganizationApiKeyCreated where
+  arbitrary = sized genOrganizationApiKeyCreated
+
+genOrganizationApiKeyCreated :: Int -> Gen OrganizationApiKeyCreated
+genOrganizationApiKeyCreated n =
+  OrganizationApiKeyCreated
+    <$> arbitrary -- organizationApiKeyCreatedKeyPrefix :: Text
+    <*> arbitrary -- organizationApiKeyCreatedLastFour :: Text
+    <*> arbitraryReduced n -- organizationApiKeyCreatedUpdatedAt :: DateTime
+    <*> arbitrary -- organizationApiKeyCreatedApiKey :: Text
+  
+instance Arbitrary OrganizationCount where
+  arbitrary = sized genOrganizationCount
+
+genOrganizationCount :: Int -> Gen OrganizationCount
+genOrganizationCount n =
+  OrganizationCount
+    <$> arbitraryReducedMaybe n -- organizationCountMemberships :: Maybe Int
+    <*> arbitraryReducedMaybe n -- organizationCountServices :: Maybe Int
+  
+instance Arbitrary OrganizationCreated where
+  arbitrary = sized genOrganizationCreated
+
+genOrganizationCreated :: Int -> Gen OrganizationCreated
+genOrganizationCreated n =
+  OrganizationCreated
+    <$> arbitraryReduced n -- organizationCreatedOrganization :: OrganizationRecord
+    <*> arbitrary -- organizationCreatedApiKey :: Text
+  
+instance Arbitrary OrganizationRecord where
+  arbitrary = sized genOrganizationRecord
+
+genOrganizationRecord :: Int -> Gen OrganizationRecord
+genOrganizationRecord n =
+  OrganizationRecord
+    <$> arbitrary -- organizationRecordId :: Text
+    <*> arbitrary -- organizationRecordName :: Text
+    <*> arbitraryReduced n -- organizationRecordCreatedAt :: DateTime
+    <*> arbitraryReduced n -- organizationRecordUpdatedAt :: DateTime
+  
+instance Arbitrary PasswordLoginInput where
+  arbitrary = sized genPasswordLoginInput
+
+genPasswordLoginInput :: Int -> Gen PasswordLoginInput
+genPasswordLoginInput n =
+  PasswordLoginInput
+    <$> arbitrary -- passwordLoginInputEmail :: Text
+    <*> arbitrary -- passwordLoginInputPassword :: Text
+  
+instance Arbitrary PasswordResetCompleteInput where
+  arbitrary = sized genPasswordResetCompleteInput
+
+genPasswordResetCompleteInput :: Int -> Gen PasswordResetCompleteInput
+genPasswordResetCompleteInput n =
+  PasswordResetCompleteInput
+    <$> arbitrary -- passwordResetCompleteInputToken :: Text
+    <*> arbitrary -- passwordResetCompleteInputPassword :: Text
+  
+instance Arbitrary PasswordResetRequestInput where
+  arbitrary = sized genPasswordResetRequestInput
+
+genPasswordResetRequestInput :: Int -> Gen PasswordResetRequestInput
+genPasswordResetRequestInput n =
+  PasswordResetRequestInput
+    <$> arbitrary -- passwordResetRequestInputEmail :: Text
+  
+instance Arbitrary PreferenceRecord where
+  arbitrary = sized genPreferenceRecord
+
+genPreferenceRecord :: Int -> Gen PreferenceRecord
+genPreferenceRecord n =
+  PreferenceRecord
+    <$> arbitrary -- preferenceRecordServiceId :: Text
+    <*> arbitrary -- preferenceRecordTypeKey :: Text
+    <*> arbitrary -- preferenceRecordEnabled :: Bool
+    <*> arbitraryReduced n -- preferenceRecordUpdatedAt :: DateTime
+  
+instance Arbitrary ProviderLoginInput where
+  arbitrary = sized genProviderLoginInput
+
+genProviderLoginInput :: Int -> Gen ProviderLoginInput
+genProviderLoginInput n =
+  ProviderLoginInput
+    <$> arbitrary -- providerLoginInputIdToken :: Text
+    <*> arbitraryReducedMaybe n -- providerLoginInputDisplayName :: Maybe Text
+  
+instance Arbitrary RegisterDeviceInput where
+  arbitrary = sized genRegisterDeviceInput
+
+genRegisterDeviceInput :: Int -> Gen RegisterDeviceInput
+genRegisterDeviceInput n =
+  RegisterDeviceInput
+    <$> arbitrary -- registerDeviceInputDeviceToken :: Text
+    <*> arbitrary -- registerDeviceInputInstallationId :: Text
+    <*> arbitrary -- registerDeviceInputEnvironment :: E'Environment
+    <*> arbitraryReducedMaybe n -- registerDeviceInputAppVersion :: Maybe Text
+  
+instance Arbitrary RegisterInput where
+  arbitrary = sized genRegisterInput
+
+genRegisterInput :: Int -> Gen RegisterInput
+genRegisterInput n =
+  RegisterInput
+    <$> arbitrary -- registerInputEmail :: Text
+    <*> arbitrary -- registerInputPassword :: Text
+    <*> arbitraryReducedMaybe n -- registerInputDisplayName :: Maybe Text
+  
+instance Arbitrary RegisterWebPushSubscriptionInput where
+  arbitrary = sized genRegisterWebPushSubscriptionInput
+
+genRegisterWebPushSubscriptionInput :: Int -> Gen RegisterWebPushSubscriptionInput
+genRegisterWebPushSubscriptionInput n =
+  RegisterWebPushSubscriptionInput
+    <$> arbitrary -- registerWebPushSubscriptionInputEndpoint :: Text
+    <*> arbitraryReduced n -- registerWebPushSubscriptionInputKeys :: RegisterWebPushSubscriptionInputKeys
+  
+instance Arbitrary RegisterWebPushSubscriptionInputKeys where
+  arbitrary = sized genRegisterWebPushSubscriptionInputKeys
+
+genRegisterWebPushSubscriptionInputKeys :: Int -> Gen RegisterWebPushSubscriptionInputKeys
+genRegisterWebPushSubscriptionInputKeys n =
+  RegisterWebPushSubscriptionInputKeys
+    <$> arbitrary -- registerWebPushSubscriptionInputKeysP256dh :: Text
+    <*> arbitrary -- registerWebPushSubscriptionInputKeysAuth :: Text
+  
+instance Arbitrary RevokedResponse where
+  arbitrary = sized genRevokedResponse
+
+genRevokedResponse :: Int -> Gen RevokedResponse
+genRevokedResponse n =
+  RevokedResponse
+    <$> arbitrary -- revokedResponseRevoked :: Bool
+  
+instance Arbitrary SearchEventsInput where
+  arbitrary = sized genSearchEventsInput
+
+genSearchEventsInput :: Int -> Gen SearchEventsInput
+genSearchEventsInput n =
+  SearchEventsInput
+    <$> arbitraryReduced n -- searchEventsInputFilter :: EventFilter
+    <*> arbitraryReducedMaybe n -- searchEventsInputCursor :: Maybe Text
+    <*> arbitraryReducedMaybe n -- searchEventsInputLimit :: Maybe Int
+  
+instance Arbitrary SendEventInput where
+  arbitrary = sized genSendEventInput
+
+genSendEventInput :: Int -> Gen SendEventInput
+genSendEventInput n =
+  SendEventInput
+    <$> arbitrary -- sendEventInputService :: Text
+    <*> arbitraryReducedMaybe n -- sendEventInputServiceDisplayName :: Maybe Text
+    <*> arbitrary -- sendEventInputType :: Text
+    <*> arbitrary -- sendEventInputTitle :: Text
+    <*> arbitrary -- sendEventInputBody :: Text
+    <*> arbitraryReducedMaybe n -- sendEventInputMetadata :: Maybe (Map.Map String AnyType)
+    <*> arbitraryReducedMaybe n -- sendEventInputExternalId :: Maybe Text
+    <*> arbitraryReducedMaybe n -- sendEventInputActionUrl :: Maybe Text
+  
+instance Arbitrary Service where
+  arbitrary = sized genService
+
+genService :: Int -> Gen Service
+genService n =
+  Service
+    <$> arbitrary -- serviceId :: Text
+    <*> arbitrary -- serviceName :: Text
+    <*> arbitrary -- serviceDisplayName :: Text
+    <*> arbitraryReduced n -- serviceCreatedAt :: DateTime
+    <*> arbitraryReduced n -- serviceCount :: ServiceAllOfCount
+  
+instance Arbitrary ServiceAllOfCount where
+  arbitrary = sized genServiceAllOfCount
+
+genServiceAllOfCount :: Int -> Gen ServiceAllOfCount
+genServiceAllOfCount n =
+  ServiceAllOfCount
+    <$> arbitrary -- serviceAllOfCountEvents :: Int
+  
+instance Arbitrary ServicePreference where
+  arbitrary = sized genServicePreference
+
+genServicePreference :: Int -> Gen ServicePreference
+genServicePreference n =
+  ServicePreference
+    <$> arbitrary -- servicePreferenceId :: Text
+    <*> arbitrary -- servicePreferenceName :: Text
+    <*> arbitrary -- servicePreferenceDisplayName :: Text
+    <*> arbitrary -- servicePreferenceEnabled :: Bool
+    <*> arbitraryReduced n -- servicePreferenceTypeOverrides :: [TypeOverride]
+  
+instance Arbitrary ServiceSummary where
+  arbitrary = sized genServiceSummary
+
+genServiceSummary :: Int -> Gen ServiceSummary
+genServiceSummary n =
+  ServiceSummary
+    <$> arbitrary -- serviceSummaryId :: Text
+    <*> arbitrary -- serviceSummaryName :: Text
+    <*> arbitrary -- serviceSummaryDisplayName :: Text
+  
+instance Arbitrary SetEnabledInput where
+  arbitrary = sized genSetEnabledInput
+
+genSetEnabledInput :: Int -> Gen SetEnabledInput
+genSetEnabledInput n =
+  SetEnabledInput
+    <$> arbitrary -- setEnabledInputEnabled :: Bool
+  
+instance Arbitrary TextFilterCondition where
+  arbitrary = sized genTextFilterCondition
+
+genTextFilterCondition :: Int -> Gen TextFilterCondition
+genTextFilterCondition n =
+  TextFilterCondition
+    <$> arbitrary -- textFilterConditionField :: E'Field2
+    <*> arbitrary -- textFilterConditionComparison :: E'Comparison2
+    <*> arbitrary -- textFilterConditionValue :: Text
+  
+instance Arbitrary TimeFilterCondition where
+  arbitrary = sized genTimeFilterCondition
+
+genTimeFilterCondition :: Int -> Gen TimeFilterCondition
+genTimeFilterCondition n =
+  TimeFilterCondition
+    <$> arbitrary -- timeFilterConditionField :: E'Field
+    <*> arbitrary -- timeFilterConditionComparison :: E'Comparison
+    <*> arbitraryReduced n -- timeFilterConditionValue :: DateTime
+  
+instance Arbitrary TypeOverride where
+  arbitrary = sized genTypeOverride
+
+genTypeOverride :: Int -> Gen TypeOverride
+genTypeOverride n =
+  TypeOverride
+    <$> arbitrary -- typeOverrideType :: Text
+    <*> arbitrary -- typeOverrideEnabled :: Bool
+    <*> arbitraryReduced n -- typeOverrideUpdatedAt :: DateTime
+  
+instance Arbitrary User where
+  arbitrary = sized genUser
+
+genUser :: Int -> Gen User
+genUser n =
+  User
+    <$> arbitrary -- userId :: Text
+    <*> arbitrary -- userEmail :: Text
+    <*> arbitraryReducedMaybe n -- userDisplayName :: Maybe Text
+    <*> arbitrary -- userHasPassword :: Bool
+    <*> arbitrary -- userHasGoogle :: Bool
+    <*> arbitrary -- userHasApple :: Bool
+  
+instance Arbitrary WebPushConfiguration where
+  arbitrary = sized genWebPushConfiguration
+
+genWebPushConfiguration :: Int -> Gen WebPushConfiguration
+genWebPushConfiguration n =
+  WebPushConfiguration
+    <$> arbitrary -- webPushConfigurationEnabled :: Bool
+    <*> arbitraryReducedMaybe n -- webPushConfigurationPublicKey :: Maybe Text
+  
+instance Arbitrary WebPushSubscription where
+  arbitrary = sized genWebPushSubscription
+
+genWebPushSubscription :: Int -> Gen WebPushSubscription
+genWebPushSubscription n =
+  WebPushSubscription
+    <$> arbitrary -- webPushSubscriptionId :: Text
+    <*> arbitrary -- webPushSubscriptionEnabled :: Bool
+    <*> arbitraryReduced n -- webPushSubscriptionLastSeenAt :: DateTime
+  
+
+
+
+instance Arbitrary E'Comparison where
+  arbitrary = arbitraryBoundedEnum
+
+instance Arbitrary E'Comparison2 where
+  arbitrary = arbitraryBoundedEnum
+
+instance Arbitrary E'Environment where
+  arbitrary = arbitraryBoundedEnum
+
+instance Arbitrary E'Field where
+  arbitrary = arbitraryBoundedEnum
+
+instance Arbitrary E'Field2 where
+  arbitrary = arbitraryBoundedEnum
+
+instance Arbitrary E'Operator where
+  arbitrary = arbitraryBoundedEnum
+
+instance Arbitrary E'Operator2 where
+  arbitrary = arbitraryBoundedEnum
+
+instance Arbitrary E'Role where
+  arbitrary = arbitraryBoundedEnum
+
+instance Arbitrary E'Service where
+  arbitrary = arbitraryBoundedEnum
+
+instance Arbitrary E'Status where
+  arbitrary = arbitraryBoundedEnum
+
diff --git a/tests/PropMime.hs b/tests/PropMime.hs
new file mode 100644
--- /dev/null
+++ b/tests/PropMime.hs
@@ -0,0 +1,51 @@
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE ConstraintKinds #-}
+{-# OPTIONS_GHC -fno-warn-unused-imports #-}
+
+module PropMime where
+
+import Data.Aeson
+import Data.Aeson.Types (parseEither)
+import Data.Monoid ((<>))
+import Data.Typeable (Proxy(..), typeOf, Typeable)
+import qualified Data.ByteString.Lazy.Char8 as BL8
+import Test.Hspec
+import Test.QuickCheck
+import Test.QuickCheck.Property
+import Test.Hspec.QuickCheck (prop)
+
+import AgentPushKit.MimeTypes
+
+import ApproxEq
+
+-- * Type Aliases
+
+type ArbitraryMime mime a = ArbitraryRoundtrip (MimeUnrender mime) (MimeRender mime) a
+
+type ArbitraryRoundtrip from to a = (from a, to a, Arbitrary' a)
+
+type Arbitrary' a = (Arbitrary a, Show a, Typeable a)
+
+-- * Mime
+
+propMime
+  :: forall a b mime.
+     (ArbitraryMime mime a, Testable b)
+  => String -> (a -> a -> b) -> mime -> Proxy a -> Spec
+propMime eqDescr eq m _ =
+  prop
+    (show (typeOf (undefined :: a)) <> " " <> show (typeOf (undefined :: mime)) <> " roundtrip " <> eqDescr) $
+  \(x :: a) ->
+     let rendered = mimeRender' m x
+         actual = mimeUnrender' m rendered
+         expected = Right x
+         failMsg =
+           "ACTUAL: " <> show actual <> "\nRENDERED: " <> BL8.unpack rendered
+     in counterexample failMsg $
+        either reject property (eq <$> actual <*> expected)
+  where
+    reject = property . const rejected
+
+propMimeEq :: (ArbitraryMime mime a, Eq a) => mime -> Proxy a -> Spec
+propMimeEq = propMime "(EQ)" (==)
diff --git a/tests/Test.hs b/tests/Test.hs
new file mode 100644
--- /dev/null
+++ b/tests/Test.hs
@@ -0,0 +1,76 @@
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE PartialTypeSignatures #-}
+
+module Main where
+
+import Data.Typeable (Proxy(..))
+import Test.Hspec
+import Test.Hspec.QuickCheck
+
+import PropMime
+import Instances ()
+
+import AgentPushKit.Model
+import AgentPushKit.MimeTypes
+
+main :: IO ()
+main =
+  hspec $ modifyMaxSize (const 10) $ do
+    describe "JSON instances" $ do
+      pure ()
+      propMimeEq MimeJSON (Proxy :: Proxy AcceptedResponse)
+      propMimeEq MimeJSON (Proxy :: Proxy AddMemberInput)
+      propMimeEq MimeJSON (Proxy :: Proxy AgentToken)
+      propMimeEq MimeJSON (Proxy :: Proxy AgentTokenCreated)
+      propMimeEq MimeJSON (Proxy :: Proxy ApiKeySummary)
+      propMimeEq MimeJSON (Proxy :: Proxy AuthResponse)
+      propMimeEq MimeJSON (Proxy :: Proxy CreateAgentTokenInput)
+      propMimeEq MimeJSON (Proxy :: Proxy CreateOrganizationInput)
+      propMimeEq MimeJSON (Proxy :: Proxy CurrentAccount)
+      propMimeEq MimeJSON (Proxy :: Proxy DeletedResponse)
+      propMimeEq MimeJSON (Proxy :: Proxy DeliverySummary)
+      propMimeEq MimeJSON (Proxy :: Proxy Device)
+      propMimeEq MimeJSON (Proxy :: Proxy DisabledResponse)
+      propMimeEq MimeJSON (Proxy :: Proxy ErrorResponse)
+      propMimeEq MimeJSON (Proxy :: Proxy EventDetail)
+      propMimeEq MimeJSON (Proxy :: Proxy EventFilter)
+      propMimeEq MimeJSON (Proxy :: Proxy EventPage)
+      propMimeEq MimeJSON (Proxy :: Proxy EventSummary)
+      propMimeEq MimeJSON (Proxy :: Proxy FilterGroup)
+      propMimeEq MimeJSON (Proxy :: Proxy FilterNot)
+      propMimeEq MimeJSON (Proxy :: Proxy HealthResponse)
+      propMimeEq MimeJSON (Proxy :: Proxy IngestionResult)
+      propMimeEq MimeJSON (Proxy :: Proxy InheritedResponse)
+      propMimeEq MimeJSON (Proxy :: Proxy Membership)
+      propMimeEq MimeJSON (Proxy :: Proxy MembershipUser)
+      propMimeEq MimeJSON (Proxy :: Proxy Organization)
+      propMimeEq MimeJSON (Proxy :: Proxy OrganizationApiKeyCreated)
+      propMimeEq MimeJSON (Proxy :: Proxy OrganizationCount)
+      propMimeEq MimeJSON (Proxy :: Proxy OrganizationCreated)
+      propMimeEq MimeJSON (Proxy :: Proxy OrganizationRecord)
+      propMimeEq MimeJSON (Proxy :: Proxy PasswordLoginInput)
+      propMimeEq MimeJSON (Proxy :: Proxy PasswordResetCompleteInput)
+      propMimeEq MimeJSON (Proxy :: Proxy PasswordResetRequestInput)
+      propMimeEq MimeJSON (Proxy :: Proxy PreferenceRecord)
+      propMimeEq MimeJSON (Proxy :: Proxy ProviderLoginInput)
+      propMimeEq MimeJSON (Proxy :: Proxy RegisterDeviceInput)
+      propMimeEq MimeJSON (Proxy :: Proxy RegisterInput)
+      propMimeEq MimeJSON (Proxy :: Proxy RegisterWebPushSubscriptionInput)
+      propMimeEq MimeJSON (Proxy :: Proxy RegisterWebPushSubscriptionInputKeys)
+      propMimeEq MimeJSON (Proxy :: Proxy RevokedResponse)
+      propMimeEq MimeJSON (Proxy :: Proxy SearchEventsInput)
+      propMimeEq MimeJSON (Proxy :: Proxy SendEventInput)
+      propMimeEq MimeJSON (Proxy :: Proxy Service)
+      propMimeEq MimeJSON (Proxy :: Proxy ServiceAllOfCount)
+      propMimeEq MimeJSON (Proxy :: Proxy ServicePreference)
+      propMimeEq MimeJSON (Proxy :: Proxy ServiceSummary)
+      propMimeEq MimeJSON (Proxy :: Proxy SetEnabledInput)
+      propMimeEq MimeJSON (Proxy :: Proxy TextFilterCondition)
+      propMimeEq MimeJSON (Proxy :: Proxy TimeFilterCondition)
+      propMimeEq MimeJSON (Proxy :: Proxy TypeOverride)
+      propMimeEq MimeJSON (Proxy :: Proxy User)
+      propMimeEq MimeJSON (Proxy :: Proxy WebPushConfiguration)
+      propMimeEq MimeJSON (Proxy :: Proxy WebPushSubscription)
+      
