diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
diff --git a/bugsnag-types.cabal b/bugsnag-types.cabal
new file mode 100644
--- /dev/null
+++ b/bugsnag-types.cabal
@@ -0,0 +1,117 @@
+cabal-version:   1.18
+name:            bugsnag-types
+version:         1.1.0.0
+license:         MIT
+maintainer:      pbrisbin@gmail.com
+author:          Patrick Brisbin
+homepage:        https://codeberg.org/pbrisbin/bugsnag-haskell#readme
+synopsis:        Types for the Bugsnag error reporter for Haskell
+description:     Please see README.md
+category:        Web
+build-type:      Simple
+extra-doc-files:
+    README.md
+    CHANGELOG.md
+
+library
+    exposed-modules:
+        Data.Bugsnag.Types.Application
+        Data.Bugsnag.Types.BinaryArch
+        Data.Bugsnag.Types.Breadcrumb
+        Data.Bugsnag.Types.BreadcrumbType
+        Data.Bugsnag.Types.DependentNotifier
+        Data.Bugsnag.Types.Device
+        Data.Bugsnag.Types.ErrorType
+        Data.Bugsnag.Types.Event
+        Data.Bugsnag.Types.Exception
+        Data.Bugsnag.Types.FeatureFlag
+        Data.Bugsnag.Types.Notifier
+        Data.Bugsnag.Types.Payload
+        Data.Bugsnag.Types.Prelude
+        Data.Bugsnag.Types.Request
+        Data.Bugsnag.Types.RuntimeVersion
+        Data.Bugsnag.Types.Session
+        Data.Bugsnag.Types.SessionEvent
+        Data.Bugsnag.Types.Severity
+        Data.Bugsnag.Types.SeverityReason
+        Data.Bugsnag.Types.SeverityReasonAttributes
+        Data.Bugsnag.Types.SeverityReasonType
+        Data.Bugsnag.Types.Stackframe
+        Data.Bugsnag.Types.Thread
+        Data.Bugsnag.Types.User
+
+    hs-source-dirs:     src
+    other-modules:      Paths_bugsnag_types
+    default-language:   GHC2021
+    default-extensions:
+        DataKinds DeriveAnyClass DerivingStrategies DerivingVia
+        DuplicateRecordFields GADTs LambdaCase NoFieldSelectors
+        NoImplicitPrelude NoMonomorphismRestriction NoPostfixOperators
+        OverloadedRecordDot OverloadedStrings QuasiQuotes TypeFamilies
+
+    ghc-options:
+        -Weverything -Wno-all-missed-specialisations
+        -Wno-missed-specialisations -Wno-missing-exported-signatures
+        -Wno-missing-import-lists -Wno-missing-local-signatures
+        -Wno-monomorphism-restriction -Wno-safe -Wno-unsafe
+
+    build-depends:
+        aeson >=2.0.3.0,
+        base >=4.16.4.0 && <5,
+        text >=1.2.5.0
+
+    if impl(ghc >=9.8)
+        ghc-options:
+            -Wno-missing-role-annotations -Wno-missing-poly-kind-signatures
+
+    if impl(ghc >=9.2)
+        ghc-options: -Wno-missing-kind-signatures
+
+    if impl(ghc >=8.10)
+        ghc-options:
+            -Wno-missing-safe-haskell-mode -Wno-prepositive-qualified-module
+
+    if impl(ghc >=8.8)
+        ghc-options: -fwrite-ide-info
+
+test-suite spec
+    type:               exitcode-stdio-1.0
+    main-is:            Spec.hs
+    hs-source-dirs:     test
+    other-modules:
+        Data.Bugsnag.Types.PayloadSpec
+        Paths_bugsnag_types
+
+    default-language:   GHC2021
+    default-extensions:
+        DataKinds DeriveAnyClass DerivingStrategies DerivingVia
+        DuplicateRecordFields GADTs LambdaCase NoFieldSelectors
+        NoImplicitPrelude NoMonomorphismRestriction NoPostfixOperators
+        OverloadedRecordDot OverloadedStrings QuasiQuotes TypeFamilies
+
+    ghc-options:
+        -Weverything -Wno-all-missed-specialisations
+        -Wno-missed-specialisations -Wno-missing-exported-signatures
+        -Wno-missing-import-lists -Wno-missing-local-signatures
+        -Wno-monomorphism-restriction -Wno-safe -Wno-unsafe -threaded
+        -rtsopts -with-rtsopts=-N
+
+    build-depends:
+        aeson >=2.0.3.0,
+        base >=4.16.4.0 && <5,
+        bugsnag-types,
+        hspec >=2.9.7
+
+    if impl(ghc >=9.8)
+        ghc-options:
+            -Wno-missing-role-annotations -Wno-missing-poly-kind-signatures
+
+    if impl(ghc >=9.2)
+        ghc-options: -Wno-missing-kind-signatures
+
+    if impl(ghc >=8.10)
+        ghc-options:
+            -Wno-missing-safe-haskell-mode -Wno-prepositive-qualified-module
+
+    if impl(ghc >=8.8)
+        ghc-options: -fwrite-ide-info
diff --git a/src/Data/Bugsnag/Types/Application.hs b/src/Data/Bugsnag/Types/Application.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Bugsnag/Types/Application.hs
@@ -0,0 +1,77 @@
+module Data.Bugsnag.Types.Application
+  ( Application (..)
+  , exampleApplication
+  ) where
+
+import Data.Bugsnag.Types.Prelude
+
+
+import Data.Bugsnag.Types.BinaryArch
+
+data Application = Application
+  { id :: Maybe Text
+  -- ^ A unique ID for the application.
+  , version :: Maybe Text
+  -- ^ The version number of the application which generated the error.
+  , versionCode :: Maybe Int
+  -- ^ The [version
+  -- code](https://developer.android.com/studio/publish/versioning.html) of the
+  -- application (Android only)
+  , bundleVersion :: Maybe Text
+  -- ^ The [bundle version/build number](https://developer.apple.com/library/content/technotes/tn2420/_index.html)
+  -- of the application (iOS/macOS/tvOS only)
+  , codeBundleId :: Maybe Text
+  -- ^ A unique identifier to identify a code bundle release when using tools like
+  -- CodePush (mobile only).
+  , buildUUID :: Maybe Text
+  -- ^ A build ID that is required to identify a specific build when the version
+  -- and version code are the same.
+  , releaseStage :: Maybe Text
+  -- ^ The release stage that this error occurred in, for example "development",
+  -- "staging" or "production".
+  , type_ :: Maybe Text
+  -- ^ A specialized type of the application, such as the worker queue or web
+  -- framework used, like "rails", "mailman", or "celery".
+  , dsymUUIDs :: Maybe [Text]
+  -- ^ The UUIDs of the [debug symbols file](http://lldb.llvm.org/symbols.html)
+  -- corresponding to this application, if any.
+  , duration :: Maybe Int
+  -- ^ How long the app has been running for in milliseconds.
+  , durationInForeground :: Maybe Int
+  -- ^ How long the app has been in the foreground of the device in milliseconds.
+  , inForeground :: Maybe Bool
+  -- ^ Whether or not the app was in the foreground when the error occurred.
+  , isLaunching :: Maybe Bool
+  -- ^ Whether or not the app was still launching when the error occurred.
+  , binaryArch :: Maybe BinaryArch
+  -- ^ The architecture of the running binary.
+  , runningOnRosetta :: Maybe Bool
+  -- ^ Whether the application is running on the Rosetta emulator for Mac.
+  }
+  deriving stock (Eq, Show, Generic)
+
+instance FromJSON Application where
+  parseJSON = genericParseJSON aesonOptions
+
+instance ToJSON Application where
+  toJSON = genericToJSON aesonOptions
+  toEncoding = genericToEncoding aesonOptions
+
+exampleApplication :: Application
+exampleApplication = Application
+  { id = Just "com.bugsnag.android.example.debug"
+  , version = Just "1.1.3"
+  , versionCode = Just 12
+  , bundleVersion = Just "1.0.2"
+  , codeBundleId = Just "1.0-1234"
+  , buildUUID = Just "BE5BA3D0-971C-4418-9ECF-E2D1ABCB66BE"
+  , releaseStage = Just "staging"
+  , type_ = Just "rails"
+  , dsymUUIDs = Just ["e6173678256785afd940392abee"]
+  , duration = Just 1275
+  , durationInForeground = Just 983
+  , inForeground = Just True
+  , isLaunching = Just True
+  , binaryArch = Just exampleBinaryArch
+  , runningOnRosetta = Just True
+  }
diff --git a/src/Data/Bugsnag/Types/BinaryArch.hs b/src/Data/Bugsnag/Types/BinaryArch.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Bugsnag/Types/BinaryArch.hs
@@ -0,0 +1,36 @@
+module Data.Bugsnag.Types.BinaryArch
+  ( BinaryArch (..)
+  , exampleBinaryArch
+  ) where
+
+import Data.Bugsnag.Types.Prelude
+
+
+data BinaryArch
+  = X86
+  -- ^ x86/i386 (32-bit).
+  | X86_64
+  -- ^ x86 (64-bit).
+  | Arm32
+  -- ^ armeabi/armeabi-v7a (32-bit).
+  | Arm64
+  -- ^ arm64-v8a (64-bit).
+  | Arm64e
+  | Armv6
+  | Armv7
+  | Armv7f
+  | Armv7k
+  | Armv7s
+  | Armv8
+  | Amd64
+  deriving stock (Bounded, Enum, Eq, Show, Generic)
+
+instance FromJSON BinaryArch where
+  parseJSON = genericParseJSON aesonOptions
+
+instance ToJSON BinaryArch where
+  toJSON = genericToJSON aesonOptions
+  toEncoding = genericToEncoding aesonOptions
+
+exampleBinaryArch :: BinaryArch
+exampleBinaryArch = toEnum 0
diff --git a/src/Data/Bugsnag/Types/Breadcrumb.hs b/src/Data/Bugsnag/Types/Breadcrumb.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Bugsnag/Types/Breadcrumb.hs
@@ -0,0 +1,44 @@
+module Data.Bugsnag.Types.Breadcrumb
+  ( Breadcrumb (..)
+  , exampleBreadcrumb
+  ) where
+
+import Data.Bugsnag.Types.Prelude
+
+
+import Data.Bugsnag.Types.BreadcrumbType
+
+data Breadcrumb = Breadcrumb
+  { timestamp :: Text
+  -- ^ The time at which the event occurred, in [ISO 8601
+  -- format](https://tools.ietf.org/html/rfc3339#section-5.8).
+  , name :: Text
+  -- ^ A short summary describing the event, such as the user action taken or a new application state.
+  , type_ :: BreadcrumbType
+  -- ^ A category which describes the breadcrumb, from the list of allowed values.
+  , metaData :: Maybe (KeyMap Text)
+  -- ^ Additional information about the event, as key/value pairs.
+  -- 
+  -- ```
+  -- {
+  --     "to": "PauseView",
+  --     "from": "PodBayDoorView"
+  -- }
+  -- ```
+  }
+  deriving stock (Eq, Show, Generic)
+
+instance FromJSON Breadcrumb where
+  parseJSON = genericParseJSON aesonOptions
+
+instance ToJSON Breadcrumb where
+  toJSON = genericToJSON aesonOptions
+  toEncoding = genericToEncoding aesonOptions
+
+exampleBreadcrumb :: Breadcrumb
+exampleBreadcrumb = Breadcrumb
+  { timestamp = "2016-07-19T12:17:27-0700"
+  , name = "Open menu"
+  , type_ = exampleBreadcrumbType
+  , metaData = Just mempty
+  }
diff --git a/src/Data/Bugsnag/Types/BreadcrumbType.hs b/src/Data/Bugsnag/Types/BreadcrumbType.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Bugsnag/Types/BreadcrumbType.hs
@@ -0,0 +1,36 @@
+module Data.Bugsnag.Types.BreadcrumbType
+  ( BreadcrumbType (..)
+  , exampleBreadcrumbType
+  ) where
+
+import Data.Bugsnag.Types.Prelude
+
+
+data BreadcrumbType
+  = Navigation
+  -- ^ Changing screens or content being displayed, with a defined destination and optionally a previous location.
+  | Request
+  -- ^ Sending and receiving requests and responses.
+  | Process
+  -- ^ Performing an intensive task or query.
+  | Log
+  -- ^ Messages and severity sent to a logging platform.
+  | User
+  -- ^ Actions performed by the user, like text input, button presses, or confirming/cancelling an alert dialog.
+  | State
+  -- ^ Changing the overall state of an app, such as closing, pausing, or being moved to the background, as well as device state changes like memory or battery warnings and network connectivity changes.
+  | Error
+  -- ^ An error which was reported to Bugsnag encountered in the same session.
+  | Manual
+  -- ^ User-defined, manually added breadcrumbs.
+  deriving stock (Bounded, Enum, Eq, Show, Generic)
+
+instance FromJSON BreadcrumbType where
+  parseJSON = genericParseJSON aesonOptions
+
+instance ToJSON BreadcrumbType where
+  toJSON = genericToJSON aesonOptions
+  toEncoding = genericToEncoding aesonOptions
+
+exampleBreadcrumbType :: BreadcrumbType
+exampleBreadcrumbType = toEnum 0
diff --git a/src/Data/Bugsnag/Types/DependentNotifier.hs b/src/Data/Bugsnag/Types/DependentNotifier.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Bugsnag/Types/DependentNotifier.hs
@@ -0,0 +1,31 @@
+module Data.Bugsnag.Types.DependentNotifier
+  ( DependentNotifier (..)
+  , exampleDependentNotifier
+  ) where
+
+import Data.Bugsnag.Types.Prelude
+
+
+data DependentNotifier = DependentNotifier
+  { name :: Text
+  -- ^ The notifier name.
+  , version :: Text
+  -- ^ The notifier's current version.
+  , url :: Text
+  -- ^ The URL associated with the notifier.
+  }
+  deriving stock (Eq, Show, Generic)
+
+instance FromJSON DependentNotifier where
+  parseJSON = genericParseJSON aesonOptions
+
+instance ToJSON DependentNotifier where
+  toJSON = genericToJSON aesonOptions
+  toEncoding = genericToEncoding aesonOptions
+
+exampleDependentNotifier :: DependentNotifier
+exampleDependentNotifier = DependentNotifier
+  { name = "Bugsnag Android"
+  , version = "2.1.10"
+  , url = "https://github.com/bugsnag/bugsnag-android"
+  }
diff --git a/src/Data/Bugsnag/Types/Device.hs b/src/Data/Bugsnag/Types/Device.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Bugsnag/Types/Device.hs
@@ -0,0 +1,79 @@
+module Data.Bugsnag.Types.Device
+  ( Device (..)
+  , exampleDevice
+  ) where
+
+import Data.Bugsnag.Types.Prelude
+
+
+import Data.Bugsnag.Types.RuntimeVersion
+
+data Device = Device
+  { hostname :: Maybe Text
+  -- ^ The hostname of the server running your code, if applicable.
+  , id :: Maybe Text
+  -- ^ A unique identifier for the device.
+  , manufacturer :: Maybe Text
+  -- ^ The manufacturer of the device.
+  , model :: Maybe Text
+  -- ^ The model of the device.
+  , modelNumber :: Maybe Text
+  -- ^ The model number of the device.
+  , osName :: Maybe Text
+  -- ^ The device's operating system name.
+  , osVersion :: Maybe Text
+  -- ^ The device's operating system version.
+  , freeMemory :: Maybe Int
+  -- ^ The number of bytes unused in the device's RAM.
+  , totalMemory :: Maybe Int
+  -- ^ The number of total bytes in the device's RAM.
+  , freeDisk :: Maybe Int
+  -- ^ The number of unused bytes on the drive running the application.
+  , browserName :: Maybe Text
+  -- ^ If a web application, the web browser used by the device.
+  , browserVersion :: Maybe Text
+  -- ^ If a web application, the version of the browser used by the device.
+  , jailbroken :: Maybe Bool
+  -- ^ Whether or not the device has been modified to give users root access.
+  , orientation :: Maybe Text
+  -- ^ The orientation of the device at the time of the error.
+  , time :: Maybe Text
+  -- ^ The time at which the error occurred, in [ISO 8601
+  -- format](https://tools.ietf.org/html/rfc3339#section-5.8).
+  , cpuAbi :: Maybe [Text]
+  -- ^ The [ABIs](https://developer.android.com/ndk/guides/abis) supported by the device (Android only).
+  , runtimeVersions :: Maybe RuntimeVersion
+  -- ^ The versions of the relevant runtimes, languages and/or frameworks for the platform.
+  , macCatalystiOSVersion :: Maybe Text
+  -- ^ The device's Mac Catalyst iOS version.
+  }
+  deriving stock (Eq, Show, Generic)
+
+instance FromJSON Device where
+  parseJSON = genericParseJSON aesonOptions
+
+instance ToJSON Device where
+  toJSON = genericToJSON aesonOptions
+  toEncoding = genericToEncoding aesonOptions
+
+exampleDevice :: Device
+exampleDevice = Device
+  { hostname = Just "web1.internal"
+  , id = Just "fd124e87760c4281aef"
+  , manufacturer = Just "LGE"
+  , model = Just $ "Nexus 6P"
+  , modelNumber = Just "600"
+  , osName = Just "android"
+  , osVersion = Just "8.0.1"
+  , freeMemory = Just 183879616
+  , totalMemory = Just 201326592
+  , freeDisk = Just 13478064128
+  , browserName = Just "Chrome"
+  , browserVersion = Just "61.0.3163.100"
+  , jailbroken = Just False
+  , orientation = Just "portrait"
+  , time = Just "2018-08-07T10:16:34.564Z"
+  , cpuAbi = Just ["x86_64"]
+  , runtimeVersions = Just exampleRuntimeVersion
+  , macCatalystiOSVersion = Just "14.0"
+  }
diff --git a/src/Data/Bugsnag/Types/ErrorType.hs b/src/Data/Bugsnag/Types/ErrorType.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Bugsnag/Types/ErrorType.hs
@@ -0,0 +1,50 @@
+module Data.Bugsnag.Types.ErrorType
+  ( ErrorType (..)
+  , exampleErrorType
+  ) where
+
+import Data.Bugsnag.Types.Prelude
+
+
+data ErrorType
+  = Android
+  -- ^ For Android
+  | Browserjs
+  -- ^ For browser-based JavaScript
+  | C
+  -- ^ For C based platforms
+  | Cocoa
+  -- ^ For Cocoa (iOS/tvOS/macOS)
+  | Csharp
+  -- ^ For C# based platforms
+  | Electronnodejs
+  -- ^ For Electron main thread
+  | Electronrendererjs
+  -- ^ For Electron renderer thread
+  | Expojs
+  -- ^ For Expo JavaScript
+  | Go
+  -- ^ For Go based platforms
+  | Java
+  -- ^ For Java based platforms
+  | Nodejs
+  -- ^ For Node.js JavaScript
+  | Php
+  -- ^ For PHP based platforms
+  | Python
+  -- ^ For Python based platforms
+  | Reactnativejs
+  -- ^ For React Native JavaScript
+  | Ruby
+  -- ^ For Ruby based platforms
+  deriving stock (Bounded, Enum, Eq, Show, Generic)
+
+instance FromJSON ErrorType where
+  parseJSON = genericParseJSON aesonOptions
+
+instance ToJSON ErrorType where
+  toJSON = genericToJSON aesonOptions
+  toEncoding = genericToEncoding aesonOptions
+
+exampleErrorType :: ErrorType
+exampleErrorType = toEnum 0
diff --git a/src/Data/Bugsnag/Types/Event.hs b/src/Data/Bugsnag/Types/Event.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Bugsnag/Types/Event.hs
@@ -0,0 +1,174 @@
+module Data.Bugsnag.Types.Event
+  ( Event (..)
+  , exampleEvent
+  ) where
+
+import Data.Bugsnag.Types.Prelude
+
+
+import Data.Bugsnag.Types.Exception
+import Data.Bugsnag.Types.Breadcrumb
+import Data.Bugsnag.Types.Request
+import Data.Bugsnag.Types.Thread
+import Data.Bugsnag.Types.Severity
+import Data.Bugsnag.Types.SeverityReason
+import Data.Bugsnag.Types.User
+import Data.Bugsnag.Types.Application
+import Data.Bugsnag.Types.Device
+import Data.Bugsnag.Types.Session
+import Data.Bugsnag.Types.FeatureFlag
+
+data Event = Event
+  { exceptions :: [Exception]
+  -- ^ An array of exceptions that occurred during this event. There must be at
+  -- least one entry. Most of the time there will only be one exception, but some
+  -- languages support "nested" or "caused by" exceptions. In this case,
+  -- exceptions should be unwrapped and added to the array one at a time. The
+  -- array should be in order from the outermost error to the innermost. For
+  -- example, the first element in the array should be the error caused by the
+  -- second element, and so on.
+  , breadcrumbs :: Maybe [Breadcrumb]
+  -- ^ An array of user- and system-initiated events which led up to an error,
+  -- providing additional context. This list is sequential and ordered newest to
+  -- oldest.
+  , request :: Maybe Request
+  -- ^ Details about the web request from the client that experienced the error,
+  -- if relevant. To display custom request data alongside these standard fields
+  -- on the Bugsnag website, the custom data should be included in the `metaData`
+  -- object in a `request` object.
+  , threads :: Maybe [Thread]
+  -- ^ An array of background threads. This is optional but recommended for apps
+  -- that rely heavily on threading. Threads should be in an order that makes
+  -- sense for your application.
+  , context :: Maybe Text
+  -- ^ A string representing what was happening in the application at the time of
+  -- the error. This string could be used for grouping purposes, depending on the
+  -- event. Usually this would represent the controller and action in a server
+  -- based project. It could represent the screen that the user was interacting
+  -- with in a client side project.
+  -- For example:
+  -- 
+  -- * On Ruby on Rails the context could be `controller#action`.
+  -- 
+  -- * In Android, the context could be the top most Activity.
+  -- 
+  -- * In iOS, the context could be the name of the top most
+  --      UIViewController.
+  , groupingHash :: Maybe Text
+  -- ^ Bugsnag's [default
+  -- error grouping](https://docs.bugsnag.com/product/error-grouping) can be
+  -- overridden by specifying a custom grouping hash.
+  , unhandled :: Maybe Bool
+  -- ^ Whether the error was unhandled. If true, the error was detected by the
+  -- notifier because it was not handled by the application. If false, the errors
+  -- was handled and reported using Bugsnag.notify.
+  , severity :: Maybe Severity
+  -- ^ The severity of the error
+  , severityReason :: Maybe SeverityReason
+  -- ^ Information about why the severity was picked.
+  , projectPackages :: Maybe [Text]
+  -- ^ Sets which package names Bugsnag should consider as a part of the running
+  -- application. We mark stacktrace lines as in-project if they originate from
+  -- any of these packages and this allows us to improve the visual display of the
+  -- stacktrace on the dashboard.
+  , user :: Maybe User
+  -- ^ Information about the user affected by the error. These fields are optional
+  -- but highly recommended. To display custom user data alongside these standard
+  -- fields on the Bugsnag website, the custom data should be included in the
+  -- `metaData` object in a `user` object.
+  , app :: Maybe Application
+  -- ^ Information about the app where the error occurred. These fields are
+  -- optional but highly recommended. To display custom app data alongside these
+  -- standard fields on the Bugsnag website, the custom data should be included
+  -- in the `metaData` object in an `app` object.
+  , device :: Maybe Device
+  -- ^ Information about the computer/device running the app. These fields are
+  -- optional but highly recommended. To display custom device data alongside
+  -- these standard fields on the Bugsnag website, the custom data should be
+  -- included in the `metaData` object in a `device` object.
+  , session :: Maybe Session
+  -- ^ Details of any session information associated with the event.
+  -- 
+  -- This can be used alongside the [Bugsnag Session Tracking API](https://bugsnagsessiontrackingapi.docs.apiary.io) to associate the event with a session so that a release's crash rate can be determined.
+  , featureFlags :: Maybe [FeatureFlag]
+  -- ^ Details of the feature flags (experiments) and associated variants that were active when the error occurred.
+  , metaData :: Maybe (KeyMap (KeyMap Text))
+  -- ^ An object containing any further data you wish to attach to this
+  -- error event. This should contain one or more objects, with each
+  -- object being displayed in its own tab on the event details on Bugsnag.
+  -- 
+  -- ```
+  -- {
+  --     // Custom user data to be displayed in the User tab along with standard
+  --     // user fields on the Bugsnag website.
+  --     "user": {
+  --        ...
+  --     },
+  -- 
+  --     // Custom app data to be displayed in the App tab along with standard
+  --     // app fields on the Bugsnag website.
+  --     "app": {
+  --        ...
+  --     },
+  -- 
+  --     // Custom device data to be displayed in the Device tab along with
+  --     //standard device fields on the Bugsnag website.
+  --     "device": {
+  --        ...
+  --     },
+  -- 
+  --     Custom request data to be displayed in the Request tab along with
+  --     standard request fields on the Bugsnag website.
+  --     "request": {
+  --        ...
+  --     },
+  -- 
+  --     // This will be displayed as an extra tab on the Bugsnag website.
+  --     "Some data": {
+  -- 
+  --         // A key value pair that will be displayed in the first tab.
+  --         "key": "value",
+  -- 
+  --         // Key value pairs can be contained in nested objects which helps
+  --         // to organise the information presented in the tab.
+  --         "setOfKeys": {
+  --             "key": "value",
+  --             "key2": "value"
+  --         }
+  --     },
+  -- 
+  --     // This would be the second extra tab on the Bugsnag website.
+  --     "Some more data": {
+  --         ...
+  --     }
+  -- }
+  -- ```
+  }
+  deriving stock (Eq, Show, Generic)
+
+instance FromJSON Event where
+  parseJSON = genericParseJSON aesonOptions
+
+instance ToJSON Event where
+  toJSON = genericToJSON aesonOptions
+  toEncoding = genericToEncoding aesonOptions
+
+exampleEvent :: Event
+exampleEvent = Event
+  { exceptions = [exampleException]
+  , breadcrumbs = Just [exampleBreadcrumb]
+  , request = Just exampleRequest
+  , threads = Just [exampleThread]
+  , context = Just "auth/session#create"
+  , groupingHash = Just "buggy_file.rb"
+  , unhandled = Just True
+  , severity = Just exampleSeverity
+  , severityReason = Just exampleSeverityReason
+  , projectPackages = Just ["com.example.package1"]
+  , user = Just exampleUser
+  , app = Just exampleApplication
+  , device = Just exampleDevice
+  , session = Just exampleSession
+  , featureFlags = Just [exampleFeatureFlag]
+  , metaData = Just mempty
+  }
diff --git a/src/Data/Bugsnag/Types/Exception.hs b/src/Data/Bugsnag/Types/Exception.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Bugsnag/Types/Exception.hs
@@ -0,0 +1,45 @@
+module Data.Bugsnag.Types.Exception
+  ( Exception (..)
+  , exampleException
+  ) where
+
+import Data.Bugsnag.Types.Prelude
+
+
+import Data.Bugsnag.Types.Stackframe
+import Data.Bugsnag.Types.ErrorType
+
+data Exception = Exception
+  { errorClass :: Text
+  -- ^ The class of error which occurred. This field is used to group the errors
+  -- together so should not contain any contextual information that would
+  -- prevent correct grouping. This would ordinarily be the Exception name when
+  -- dealing with an exception.
+  , message :: Maybe Text
+  -- ^ The error message associated with the error. Usually this will contain some
+  -- information about this specific instance of the error and is not used to
+  -- group the errors.
+  , stacktrace :: [Stackframe]
+  -- ^ An array of stackframe objects. Each object represents one line in the
+  -- exception's stacktrace. Bugsnag uses this information to help with error
+  -- grouping, as well as displaying it to the user.
+  , type_ :: Maybe ErrorType
+  -- ^ This should be set for the following platforms so that the stacktrace can be
+  -- parsed correctly.
+  }
+  deriving stock (Eq, Show, Generic)
+
+instance FromJSON Exception where
+  parseJSON = genericParseJSON aesonOptions
+
+instance ToJSON Exception where
+  toJSON = genericToJSON aesonOptions
+  toEncoding = genericToEncoding aesonOptions
+
+exampleException :: Exception
+exampleException = Exception
+  { errorClass = "NoMethodError"
+  , message = Just $ "Unable to connect to database"
+  , stacktrace = [exampleStackframe]
+  , type_ = Just exampleErrorType
+  }
diff --git a/src/Data/Bugsnag/Types/FeatureFlag.hs b/src/Data/Bugsnag/Types/FeatureFlag.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Bugsnag/Types/FeatureFlag.hs
@@ -0,0 +1,28 @@
+module Data.Bugsnag.Types.FeatureFlag
+  ( FeatureFlag (..)
+  , exampleFeatureFlag
+  ) where
+
+import Data.Bugsnag.Types.Prelude
+
+
+data FeatureFlag = FeatureFlag
+  { featureFlag :: Text
+  -- ^ The name of the feature flag.
+  , variant :: Maybe Text
+  -- ^ The name of the variant.
+  }
+  deriving stock (Eq, Show, Generic)
+
+instance FromJSON FeatureFlag where
+  parseJSON = genericParseJSON aesonOptions
+
+instance ToJSON FeatureFlag where
+  toJSON = genericToJSON aesonOptions
+  toEncoding = genericToEncoding aesonOptions
+
+exampleFeatureFlag :: FeatureFlag
+exampleFeatureFlag = FeatureFlag
+  { featureFlag = "share_ios_photo_sharing_button"
+  , variant = Just "blue_button"
+  }
diff --git a/src/Data/Bugsnag/Types/Notifier.hs b/src/Data/Bugsnag/Types/Notifier.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Bugsnag/Types/Notifier.hs
@@ -0,0 +1,37 @@
+module Data.Bugsnag.Types.Notifier
+  ( Notifier (..)
+  , exampleNotifier
+  ) where
+
+import Data.Bugsnag.Types.Prelude
+
+
+import Data.Bugsnag.Types.DependentNotifier
+
+data Notifier = Notifier
+  { name :: Text
+  -- ^ The notifier name.
+  , version :: Text
+  -- ^ The notifier's current version.
+  , url :: Text
+  -- ^ The URL associated with the notifier.
+  , dependencies :: Maybe [DependentNotifier]
+  -- ^ For platforms where multiple notifiers are used to capture an event, an optional
+  -- array containing the details of the additional notifiers can be specified.
+  }
+  deriving stock (Eq, Show, Generic)
+
+instance FromJSON Notifier where
+  parseJSON = genericParseJSON aesonOptions
+
+instance ToJSON Notifier where
+  toJSON = genericToJSON aesonOptions
+  toEncoding = genericToEncoding aesonOptions
+
+exampleNotifier :: Notifier
+exampleNotifier = Notifier
+  { name = "Bugsnag Ruby"
+  , version = "1.0.11"
+  , url = "https://github.com/bugsnag/bugsnag-ruby"
+  , dependencies = Just [exampleDependentNotifier]
+  }
diff --git a/src/Data/Bugsnag/Types/Payload.hs b/src/Data/Bugsnag/Types/Payload.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Bugsnag/Types/Payload.hs
@@ -0,0 +1,45 @@
+module Data.Bugsnag.Types.Payload
+  ( Payload (..)
+  , examplePayload
+  ) where
+
+import Data.Bugsnag.Types.Prelude
+
+
+import Data.Bugsnag.Types.Notifier
+import Data.Bugsnag.Types.Event
+
+data Payload = Payload
+  { apiKey :: Maybe Text
+  -- ^ The API Key associated with the project. Informs Bugsnag which project has
+  -- generated this error.
+  -- 
+  -- This is provided for legacy notifiers. It is preferable to use the `Bugsnag-Api-Key` header instead.
+  , payloadVersion :: Text
+  -- ^ The version number of the payload. This is currently `5`.
+  -- 
+  -- The `Bugsnag-Payload-Version` header should be included as well, for compatibility reasons.
+  , notifier :: Notifier
+  -- ^ Describes the notifier itself. These properties are used within Bugsnag to
+  -- track error rates from a notifier.
+  , events :: [Event]
+  -- ^ An array of error events that Bugsnag should be notified of. A notifier
+  -- can choose to group notices into an array to minimize network traffic, or
+  -- can notify Bugsnag each time an event occurs. Should contain at least 1 event.
+  }
+  deriving stock (Eq, Show, Generic)
+
+instance FromJSON Payload where
+  parseJSON = genericParseJSON aesonOptions
+
+instance ToJSON Payload where
+  toJSON = genericToJSON aesonOptions
+  toEncoding = genericToEncoding aesonOptions
+
+examplePayload :: Payload
+examplePayload = Payload
+  { apiKey = Just "YOUR-NOTIFIER-API-KEY"
+  , payloadVersion = "5"
+  , notifier = exampleNotifier
+  , events = [exampleEvent]
+  }
diff --git a/src/Data/Bugsnag/Types/Prelude.hs b/src/Data/Bugsnag/Types/Prelude.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Bugsnag/Types/Prelude.hs
@@ -0,0 +1,33 @@
+module Data.Bugsnag.Types.Prelude
+  ( module X
+  , aesonOptions
+  ) where
+
+import Prelude as X
+
+import Control.Monad as X (void)
+import Data.Aeson (Options (..), defaultOptions)
+import Data.Aeson as X
+  ( FromJSON (..)
+  , ToJSON (..)
+  , genericParseJSON
+  , genericToEncoding
+  , genericToJSON
+  )
+import Data.Aeson.KeyMap as X (KeyMap)
+import Data.Char (toLower)
+import Data.Foldable as X (for_, traverse_)
+import Data.Maybe as X (catMaybes, fromMaybe, mapMaybe)
+import Data.Text as X (Text, pack, unpack)
+import Data.Traversable as X (for)
+import GHC.Generics as X (Generic)
+
+aesonOptions :: Options
+aesonOptions =
+  defaultOptions
+    { fieldLabelModifier = \case
+        "type_" -> "type"
+        x -> x
+    , constructorTagModifier = map toLower
+    , omitNothingFields = True
+    }
diff --git a/src/Data/Bugsnag/Types/Request.hs b/src/Data/Bugsnag/Types/Request.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Bugsnag/Types/Request.hs
@@ -0,0 +1,45 @@
+module Data.Bugsnag.Types.Request
+  ( Request (..)
+  , exampleRequest
+  ) where
+
+import Data.Bugsnag.Types.Prelude
+
+
+data Request = Request
+  { clientIp :: Maybe Text
+  -- ^ The IP address of the client that experienced the error.
+  , headers :: Maybe (KeyMap Text)
+  -- ^ The headers sent with the request.
+  -- 
+  -- ```
+  -- {
+  --     "Accept": "*/*",
+  --     "Accept-Encoding": "gzip, deflate, sdch, br",
+  --     "Accept-Language": "en-US,en;q=0.8"
+  -- }
+  -- ```
+  , httpMethod :: Maybe Text
+  -- ^ The HTTP method used.
+  , url :: Maybe Text
+  -- ^ The URL of the request.
+  , referer :: Maybe Text
+  -- ^ The [HTTP referer](https://en.wikipedia.org/wiki/HTTP_referer)
+  }
+  deriving stock (Eq, Show, Generic)
+
+instance FromJSON Request where
+  parseJSON = genericParseJSON aesonOptions
+
+instance ToJSON Request where
+  toJSON = genericToJSON aesonOptions
+  toEncoding = genericToEncoding aesonOptions
+
+exampleRequest :: Request
+exampleRequest = Request
+  { clientIp = Just "192.168.44.0"
+  , headers = Just mempty
+  , httpMethod = Just "PUT"
+  , url = Just "http://example.com/users/19/settings"
+  , referer = Just "http://example.com?q=awesome"
+  }
diff --git a/src/Data/Bugsnag/Types/RuntimeVersion.hs b/src/Data/Bugsnag/Types/RuntimeVersion.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Bugsnag/Types/RuntimeVersion.hs
@@ -0,0 +1,178 @@
+module Data.Bugsnag.Types.RuntimeVersion
+  ( RuntimeVersion (..)
+  , exampleRuntimeVersion
+  ) where
+
+import Data.Bugsnag.Types.Prelude
+
+
+data RuntimeVersion = RuntimeVersion
+  { androidApiLevel :: Maybe Text
+  -- ^ The Android API level (Android only).
+  , bottle :: Maybe Text
+  -- ^ Bottle framework version (Python only).
+  , celery :: Maybe Text
+  -- ^ Celery task queue version (Python only).
+  , clangVersion :: Maybe Text
+  -- ^ Clang compiler version (iOS/tvOS/macOS only).
+  , cocos2dx :: Maybe Text
+  -- ^ Cocos2d-x framework version (Cocos2d-x only).
+  , delayedJob :: Maybe Text
+  -- ^ Delayed Job framework version (Ruby only).
+  , django :: Maybe Text
+  -- ^ Django framework version (Python only).
+  , dotnet :: Maybe Text
+  -- ^ Description of the framework (.NET only).
+  , dotnetApiCompatibility :: Maybe Text
+  -- ^ .NET API compatibility level (Unity only).
+  , dotnetClr :: Maybe Text
+  -- ^ Version of .NET Common Language Runtime (.NET only).
+  , dotnetScriptingRuntime :: Maybe Text
+  -- ^ .NET scripting runtime version (Unity only).
+  , electron :: Maybe Text
+  -- ^ Electron platform version (Electron only).
+  , eventMachine :: Maybe Text
+  -- ^ EventMachine library version (Ruby only).
+  , expoApp :: Maybe Text
+  -- ^ Expo app version (Expo only).
+  , expoSdk :: Maybe Text
+  -- ^ Expo SDK version (Expo only).
+  , flask :: Maybe Text
+  -- ^ Flask framework version (Python only).
+  , gin :: Maybe Text
+  -- ^ Gin framework version (Go only).
+  , go :: Maybe Text
+  -- ^ Go language version (Go only).
+  , javaType :: Maybe Text
+  -- ^ Java platform implementation type (Java only).
+  , javaVersion :: Maybe Text
+  -- ^ Java runtime version (Java only).
+  , jruby :: Maybe Text
+  -- ^ Version of JRuby (Ruby only).
+  , laravel :: Maybe Text
+  -- ^ Laravel framework version (PHP only).
+  , lumen :: Maybe Text
+  -- ^ Lumen framework version (PHP only).
+  , magento :: Maybe Text
+  -- ^ Magento platform version (PHP only).
+  , mailman :: Maybe Text
+  -- ^ Mailman framework version (Ruby only).
+  , martini :: Maybe Text
+  -- ^ Martini framework version (Go only).
+  , negroni :: Maybe Text
+  -- ^ Negroni framework version (Go only).
+  , node :: Maybe Text
+  -- ^ Node.js version (Javascript only).
+  , osBuild :: Maybe Text
+  -- ^ Build number of the OS (iOS/tvOS/macOS only).
+  , php :: Maybe Text
+  -- ^ Version of PHP (PHP only).
+  , python :: Maybe Text
+  -- ^ Version of Python (Python only).
+  , que :: Maybe Text
+  -- ^ Que job queue version (Ruby only).
+  , rack :: Maybe Text
+  -- ^ Rack webserver version (Ruby only).
+  , rails :: Maybe Text
+  -- ^ Ruby on Rails version (Ruby only).
+  , rake :: Maybe Text
+  -- ^ Rake tool version (Ruby only).
+  , reactNative :: Maybe Text
+  -- ^ Version of React Native (React Native/Expo only).
+  , reactNativeJsEngine :: Maybe Text
+  -- ^ Javascript engine type (React Native/Expo only).
+  , resque :: Maybe Text
+  -- ^ Resque library version (Ruby only).
+  , revel :: Maybe Text
+  -- ^ Revel framework version (Go only).
+  , ruby :: Maybe Text
+  -- ^ Version of Ruby (Ruby only).
+  , shoryoken :: Maybe Text
+  -- ^ Shoryoken framework version (Ruby only).
+  , sidekiq :: Maybe Text
+  -- ^ Sidekiq scheduler version (Ruby only).
+  , silex :: Maybe Text
+  -- ^ Silex framework version (PHP only).
+  , sinatra :: Maybe Text
+  -- ^ Sinatra DSL version (Ruby only).
+  , springBoot :: Maybe Text
+  -- ^ Spring Boot framework version (Java only).
+  , springFramework :: Maybe Text
+  -- ^ Spring framework version (Java only).
+  , swift :: Maybe Text
+  -- ^ Swift language version (iOS/tvOS/macOS only).
+  , symfony :: Maybe Text
+  -- ^ Symfony framework version (PHP only).
+  , tornado :: Maybe Text
+  -- ^ Tornado framework version (Python only).
+  , unity :: Maybe Text
+  -- ^ Version of Unity.
+  , unityScriptingBackend :: Maybe Text
+  -- ^ The Unity scripting backend - Mono or IL2CPP (Unity only).
+  , wordpress :: Maybe Text
+  -- ^ Wordpress version (PHP only).
+  }
+  deriving stock (Eq, Show, Generic)
+
+instance FromJSON RuntimeVersion where
+  parseJSON = genericParseJSON aesonOptions
+
+instance ToJSON RuntimeVersion where
+  toJSON = genericToJSON aesonOptions
+  toEncoding = genericToEncoding aesonOptions
+
+exampleRuntimeVersion :: RuntimeVersion
+exampleRuntimeVersion = RuntimeVersion
+  { androidApiLevel = Just "28"
+  , bottle = Just "0.12.8"
+  , celery = Just "4.2.0"
+  , clangVersion = Just "7.0.1"
+  , cocos2dx = Just "3.17.2"
+  , delayedJob = Just "4.1.8"
+  , django = Just "2.1.7"
+  , dotnet = Just $ ".NET Framework 4.7.3416.0"
+  , dotnetApiCompatibility = Just $ ".NET 2.0 Subset"
+  , dotnetClr = Just "4.0.30319.17379"
+  , dotnetScriptingRuntime = Just $ ".NET 3.5 equivalent"
+  , electron = Just "11.4.3"
+  , eventMachine = Just "1.2.7"
+  , expoApp = Just "2.10.0.105125"
+  , expoSdk = Just "32.0.0"
+  , flask = Just "1.0.2"
+  , gin = Just "1.3.0"
+  , go = Just "1.11.2"
+  , javaType = Just $ "Java(TM) SE Runtime Environment"
+  , javaVersion = Just "1.8.0_131-b11"
+  , jruby = Just "9.2.5.0"
+  , laravel = Just "5.7.22"
+  , lumen = Just "5.7"
+  , magento = Just "2.3.0"
+  , mailman = Just "0.8.0"
+  , martini = Just "1.0"
+  , negroni = Just "1.0.0"
+  , node = Just "10.14.1"
+  , osBuild = Just "16D57"
+  , php = Just "7.2.12"
+  , python = Just "3.7.1"
+  , que = Just "0.14.3"
+  , rack = Just "2.0.6"
+  , rails = Just "5.2.2"
+  , rake = Just "12.3.2"
+  , reactNative = Just "0.57.5"
+  , reactNativeJsEngine = Just "hermes"
+  , resque = Just "2.0.0"
+  , revel = Just "0.21.0"
+  , ruby = Just "2.5.3"
+  , shoryoken = Just "5.0.1"
+  , sidekiq = Just "5.1.3"
+  , silex = Just "2.1.0"
+  , sinatra = Just "2.0.3"
+  , springBoot = Just "1.5.13.RELEASE"
+  , springFramework = Just "4.2.13.RELEASE"
+  , swift = Just "4.2"
+  , symfony = Just "4.2.11"
+  , tornado = Just "5.1.1"
+  , unity = Just "2018.2.17"
+  , unityScriptingBackend = Just "Mono"
+  , wordpress = Just "5.1"
+  }
diff --git a/src/Data/Bugsnag/Types/Session.hs b/src/Data/Bugsnag/Types/Session.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Bugsnag/Types/Session.hs
@@ -0,0 +1,33 @@
+module Data.Bugsnag.Types.Session
+  ( Session (..)
+  , exampleSession
+  ) where
+
+import Data.Bugsnag.Types.Prelude
+
+
+import Data.Bugsnag.Types.SessionEvent
+
+data Session = Session
+  { id :: Text
+  -- ^ The unique identifier of the session.
+  , startedAt :: Text
+  -- ^ The time (in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format) at which the session started.
+  , events :: SessionEvent
+  -- ^ Details of the number of handled and unhandled events that have occurred so far in this session.
+  }
+  deriving stock (Eq, Show, Generic)
+
+instance FromJSON Session where
+  parseJSON = genericParseJSON aesonOptions
+
+instance ToJSON Session where
+  toJSON = genericToJSON aesonOptions
+  toEncoding = genericToEncoding aesonOptions
+
+exampleSession :: Session
+exampleSession = Session
+  { id = "9f65c975-8155-456f-91e5-c4c4b3db0555"
+  , startedAt = "2017-01-01T14:30:00.000Z"
+  , events = exampleSessionEvent
+  }
diff --git a/src/Data/Bugsnag/Types/SessionEvent.hs b/src/Data/Bugsnag/Types/SessionEvent.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Bugsnag/Types/SessionEvent.hs
@@ -0,0 +1,28 @@
+module Data.Bugsnag.Types.SessionEvent
+  ( SessionEvent (..)
+  , exampleSessionEvent
+  ) where
+
+import Data.Bugsnag.Types.Prelude
+
+
+data SessionEvent = SessionEvent
+  { handled :: Int
+  -- ^  The number of handled events that have occurred in this session (including this event).
+  , unhandled :: Int
+  -- ^  The number of unhandled events that have occurred in this session (including this event)
+  }
+  deriving stock (Eq, Show, Generic)
+
+instance FromJSON SessionEvent where
+  parseJSON = genericParseJSON aesonOptions
+
+instance ToJSON SessionEvent where
+  toJSON = genericToJSON aesonOptions
+  toEncoding = genericToEncoding aesonOptions
+
+exampleSessionEvent :: SessionEvent
+exampleSessionEvent = SessionEvent
+  { handled = 1
+  , unhandled = 1
+  }
diff --git a/src/Data/Bugsnag/Types/Severity.hs b/src/Data/Bugsnag/Types/Severity.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Bugsnag/Types/Severity.hs
@@ -0,0 +1,26 @@
+module Data.Bugsnag.Types.Severity
+  ( Severity (..)
+  , exampleSeverity
+  ) where
+
+import Data.Bugsnag.Types.Prelude
+
+
+data Severity
+  = Error
+  -- ^ The default for unhandled errors.
+  | Warning
+  -- ^ The default when Bugsnag.notify is called.
+  | Info
+  -- ^ Can be used in manual Bugsnag.notify calls.
+  deriving stock (Bounded, Enum, Eq, Show, Generic)
+
+instance FromJSON Severity where
+  parseJSON = genericParseJSON aesonOptions
+
+instance ToJSON Severity where
+  toJSON = genericToJSON aesonOptions
+  toEncoding = genericToEncoding aesonOptions
+
+exampleSeverity :: Severity
+exampleSeverity = toEnum 0
diff --git a/src/Data/Bugsnag/Types/SeverityReason.hs b/src/Data/Bugsnag/Types/SeverityReason.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Bugsnag/Types/SeverityReason.hs
@@ -0,0 +1,34 @@
+module Data.Bugsnag.Types.SeverityReason
+  ( SeverityReason (..)
+  , exampleSeverityReason
+  ) where
+
+import Data.Bugsnag.Types.Prelude
+
+
+import Data.Bugsnag.Types.SeverityReasonType
+import Data.Bugsnag.Types.SeverityReasonAttributes
+
+data SeverityReason = SeverityReason
+  { type_ :: Maybe SeverityReasonType
+  -- ^ A type key that represents the reason for the assigned severity.
+  , attributes :: Maybe SeverityReasonAttributes
+  -- ^ Optional attributes to provide extra information about the severity reason.
+  , unhandledOverridden :: Maybe Bool
+  -- ^ Whether the event's `unhandled` flag was overridden from the notifier's default value.
+  }
+  deriving stock (Eq, Show, Generic)
+
+instance FromJSON SeverityReason where
+  parseJSON = genericParseJSON aesonOptions
+
+instance ToJSON SeverityReason where
+  toJSON = genericToJSON aesonOptions
+  toEncoding = genericToEncoding aesonOptions
+
+exampleSeverityReason :: SeverityReason
+exampleSeverityReason = SeverityReason
+  { type_ = Just exampleSeverityReasonType
+  , attributes = Just exampleSeverityReasonAttributes
+  , unhandledOverridden = Just False
+  }
diff --git a/src/Data/Bugsnag/Types/SeverityReasonAttributes.hs b/src/Data/Bugsnag/Types/SeverityReasonAttributes.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Bugsnag/Types/SeverityReasonAttributes.hs
@@ -0,0 +1,49 @@
+module Data.Bugsnag.Types.SeverityReasonAttributes
+  ( SeverityReasonAttributes (..)
+  , exampleSeverityReasonAttributes
+  ) where
+
+import Data.Bugsnag.Types.Prelude
+
+
+data SeverityReasonAttributes = SeverityReasonAttributes
+  { errorType :: Maybe Text
+  -- ^ Included for `unhandledError` severity reason. See [PHP Error
+  -- Constants](http://php.net/manual/en/errorfunc.constants.php).
+  , level :: Maybe Text
+  -- ^ Included for `log` severity reason.
+  , signalType :: Maybe Text
+  -- ^ Included for `signal` severity reason. See [Signal
+  -- Codes](https://en.wikipedia.org/wiki/C_signal_handling).
+  , violationType :: Maybe Text
+  -- ^ Included for `strictMode` severity reason. See [Strict
+  -- Mode](https://developer.android.com/reference/android/os/StrictMode.html).
+  , errorClass :: Maybe Text
+  -- ^ Included for `errorClass` severity reason. Specifies the error class
+  -- that is automatically sent.
+  , framework :: Maybe Text
+  -- ^ Included for middleware severity reasons, specifies the middleware
+  -- that had an error.
+  , exceptionClass :: Maybe Text
+  -- ^ Included for `exceptionClass` severity reason. Specifies the error class
+  -- that is automatically sent.
+  }
+  deriving stock (Eq, Show, Generic)
+
+instance FromJSON SeverityReasonAttributes where
+  parseJSON = genericParseJSON aesonOptions
+
+instance ToJSON SeverityReasonAttributes where
+  toJSON = genericToJSON aesonOptions
+  toEncoding = genericToEncoding aesonOptions
+
+exampleSeverityReasonAttributes :: SeverityReasonAttributes
+exampleSeverityReasonAttributes = SeverityReasonAttributes
+  { errorType = Just "E_ERROR"
+  , level = Just "Error"
+  , signalType = Just "SIGSEGV"
+  , violationType = Just "NetworkOnMainThread"
+  , errorClass = Just "ActiveRecord::RecordNotFound"
+  , framework = Just "Rack"
+  , exceptionClass = Just "TypeMismatchException"
+  }
diff --git a/src/Data/Bugsnag/Types/SeverityReasonType.hs b/src/Data/Bugsnag/Types/SeverityReasonType.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Bugsnag/Types/SeverityReasonType.hs
@@ -0,0 +1,64 @@
+module Data.Bugsnag.Types.SeverityReasonType
+  ( SeverityReasonType (..)
+  , exampleSeverityReasonType
+  ) where
+
+import Data.Bugsnag.Types.Prelude
+
+
+data SeverityReasonType
+  = UnhandledException
+  -- ^ Whenever an uncaught exception is discovered (generic).
+  | UnhandledError
+  -- ^ When an error is discovered (PHP).
+  | Log
+  -- ^ Whenever a log message is sent (generic).
+  | Signal
+  -- ^ Whenever a "fatal" signal is discovered (iOS).
+  | StrictMode
+  -- ^ Whenever a strictMode issue is discovered (Android).
+  | UnhandledPromiseRejection
+  -- ^ Whenever an unhandled promise rejection is discovered (JS/Node JS/React Native).
+  | CallbackErrorIntercept
+  -- ^ callbackErrorIntercept (Node JS).
+  | ErrorClass
+  -- ^ Whenever an exception with a particular class is automatically sent (Ruby).
+  | ExceptionClass
+  -- ^ Whenever an exception with a particular class is automatically sent (Java).
+  | UnhandledPanic
+  -- ^ When a panic is unhandled and crashes the app (Go).
+  | UnhandledErrorMiddleware
+  -- ^ Unhandled errors in ${Negroni} middleware have a default severity:error.
+  | UnhandledExceptionMiddleware
+  -- ^ Unhandled exceptions in ${Rack} middleware have a default severity:error.
+  | UserCallbackSetSeverity
+  -- ^ Whenever a callback changes a report's severity (generic).
+  | UserSpecifiedSeverity
+  -- ^ Whenever a severity is set through a manual notify call (generic).
+  | HandledException
+  -- ^ Whenever a handled exception is sent through (generic).
+  | HandledError
+  -- ^ Whenever a handled error is sent through (PHP).
+  | HandledPanic
+  -- ^ Whenever a panic is handled through AutoNotify or Recover (Go).
+  | UserContextSetSeverity
+  -- ^ When a user creates a context which changes the severity (Python).
+  | AnrError
+  -- ^ Whenever an ANR is detected (Android).
+  | AppHang
+  -- ^ Whenever an app hang is detected (Cocoa).
+  | OutOfMemory
+  -- ^ When an app is terminated because it used too much memory (Cocoa).
+  | ThermalKill
+  -- ^ When an app is terminated because the device is overheating (Cocoa).
+  deriving stock (Bounded, Enum, Eq, Show, Generic)
+
+instance FromJSON SeverityReasonType where
+  parseJSON = genericParseJSON aesonOptions
+
+instance ToJSON SeverityReasonType where
+  toJSON = genericToJSON aesonOptions
+  toEncoding = genericToEncoding aesonOptions
+
+exampleSeverityReasonType :: SeverityReasonType
+exampleSeverityReasonType = toEnum 0
diff --git a/src/Data/Bugsnag/Types/Stackframe.hs b/src/Data/Bugsnag/Types/Stackframe.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Bugsnag/Types/Stackframe.hs
@@ -0,0 +1,98 @@
+module Data.Bugsnag.Types.Stackframe
+  ( Stackframe (..)
+  , exampleStackframe
+  ) where
+
+import Data.Bugsnag.Types.Prelude
+
+
+data Stackframe = Stackframe
+  { file :: Text
+  -- ^ The file that this stack frame was executing. It is recommended that you
+  -- strip any unnecessary or common information from the beginning of the path.
+  , lineNumber :: Int
+  -- ^ The line of the file that this frame of the stack was in.
+  , columnNumber :: Maybe Int
+  -- ^ The column of the file that this frame of the stack was in.
+  , method :: Text
+  -- ^ The method that this particular stack frame is within.
+  , inProject :: Maybe Bool
+  -- ^ If this stacktrace line is in the user's project code, set this to true. It
+  -- is useful for developers to be able to see which lines of a stacktrace are
+  -- within their own application, and which are within third party libraries.
+  -- This boolean field allows Bugsnag to display this information in the
+  -- stacktrace as well as use the information to help group errors better.
+  , code :: Maybe (KeyMap Text)
+  -- ^ The code in this file surrounding this line. This is an object containing
+  -- key value pairs where each key is a line number and each value is the code
+  -- from that line. You can include up to three lines on either side of the line
+  -- where the error occurred. These will be displayed on the bugsnag dashboard
+  -- when you expand that line.
+  -- 
+  -- ```
+  -- {
+  --     "1231": "  def a",
+  --     "1232": "",
+  --     "1233": "    if problem?",
+  --     "1234": "      raise 'something went wrong'",
+  --     "1235": "    end"
+  --     "1236": "",
+  --     "1237": "  end"
+  -- }
+  -- ```
+  , frameAddress :: Maybe Text
+  -- ^ The run time memory address of the instruction being executed (for the first
+  -- stack frame) or to which control will return after the function call or
+  -- subroutine completes.
+  , loadAddress :: Maybe Text
+  -- ^ The address in memory where the binary has been loaded at run time.
+  , isLR :: Maybe Bool
+  -- ^ True if `frameAddress` corresponds to value of the Link Register. This is sometimes
+  -- the case for the second frame in a stack - e.g. for signals and mach exceptions.
+  , isPC :: Maybe Bool
+  -- ^ True if `frameAddress` corresponds to the Program Counter.
+  , symbolAddress :: Maybe Text
+  -- ^ The run time memory address of the symbol that most closely matches `frameAddress`.
+  , machoFile :: Maybe Text
+  -- ^ The full path of the Mach-O binary (iOS/macOS/tvOS only).
+  , machoLoadAddress :: Maybe Text
+  -- ^ The address in memory where the Mach-O binary has been loaded at run time.
+  -- This may differ from `machoVMAddress` due to Address Space Layout Randomization.
+  -- The difference between `machoLoadAddress` and `machoVMAddress` is known as the
+  -- "slide" (iOS/macOS/tvOS only).
+  , machoUUID :: Maybe Text
+  -- ^ A UUID which uniquely identifies this Mach-O binary (iOS/macOS/tvOS only).
+  , machoVMAddress :: Maybe Text
+  -- ^ The memory address assigned to the Mach-O binary by the linker at build time
+  -- (iOS/macOS/tvOS only).
+  , codeIdentifier :: Maybe Text
+  -- ^ The ID of the executable/library that the frame relates to.
+  }
+  deriving stock (Eq, Show, Generic)
+
+instance FromJSON Stackframe where
+  parseJSON = genericParseJSON aesonOptions
+
+instance ToJSON Stackframe where
+  toJSON = genericToJSON aesonOptions
+  toEncoding = genericToEncoding aesonOptions
+
+exampleStackframe :: Stackframe
+exampleStackframe = Stackframe
+  { file = "controllers/auth/session_controller.rb"
+  , lineNumber = 1234
+  , columnNumber = Just 123
+  , method = "create"
+  , inProject = Just True
+  , code = Just mempty
+  , frameAddress = Just "0x000000010d131040"
+  , loadAddress = Just "0x000000010d12e000"
+  , isLR = Just False
+  , isPC = Just True
+  , symbolAddress = Just "0x000000010d130fe6"
+  , machoFile = Just "/System/Library/Frameworks/Foundation.framework/Foundation"
+  , machoLoadAddress = Just "0x000000010d12e000"
+  , machoUUID = Just "B3196052-BAF1-3EA5-AD28-F9E6ECCF0B03"
+  , machoVMAddress = Just "0x0000000100000000"
+  , codeIdentifier = Just "b6b529d5e58421a0fba0fa2c5c2c5f3e"
+  }
diff --git a/src/Data/Bugsnag/Types/Thread.hs b/src/Data/Bugsnag/Types/Thread.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Bugsnag/Types/Thread.hs
@@ -0,0 +1,45 @@
+module Data.Bugsnag.Types.Thread
+  ( Thread (..)
+  , exampleThread
+  ) where
+
+import Data.Bugsnag.Types.Prelude
+
+
+import Data.Bugsnag.Types.Stackframe
+import Data.Bugsnag.Types.ErrorType
+
+data Thread = Thread
+  { id :: Maybe Text
+  -- ^ The id of the thread in your application.
+  , name :: Maybe Text
+  -- ^ A human readable name for the thread.
+  , errorReportingThread :: Maybe Bool
+  -- ^ If this is the thread that the error was reported from (either an unhandled error or a call to bugsnag.notify), set this to true.
+  , stacktrace :: Maybe [Stackframe]
+  -- ^ An array of stacktrace objects. Each object represents one line in the
+  -- stacktrace of the thread at the point that the error occurred.
+  , state :: Maybe Text
+  -- ^ The state of the thread at the time of the error.
+  , type_ :: Maybe ErrorType
+  -- ^ This should be set to indicate the type of runtime the thread was running on so that the stacktrace can be
+  -- parsed correctly.
+  }
+  deriving stock (Eq, Show, Generic)
+
+instance FromJSON Thread where
+  parseJSON = genericParseJSON aesonOptions
+
+instance ToJSON Thread where
+  toJSON = genericToJSON aesonOptions
+  toEncoding = genericToEncoding aesonOptions
+
+exampleThread :: Thread
+exampleThread = Thread
+  { id = Just "thread_id"
+  , name = Just "thread_name"
+  , errorReportingThread = Just True
+  , stacktrace = Just [exampleStackframe]
+  , state = Just "WAITING"
+  , type_ = Just exampleErrorType
+  }
diff --git a/src/Data/Bugsnag/Types/User.hs b/src/Data/Bugsnag/Types/User.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Bugsnag/Types/User.hs
@@ -0,0 +1,32 @@
+module Data.Bugsnag.Types.User
+  ( User (..)
+  , exampleUser
+  ) where
+
+import Data.Bugsnag.Types.Prelude
+
+
+data User = User
+  { id :: Maybe Text
+  -- ^ A unique identifier for a user affected by this event. This could be any
+  -- distinct identifier that makes sense for your application/platform.
+  , name :: Maybe Text
+  -- ^ The user's name, or a string you use to identify them.
+  , email :: Maybe Text
+  -- ^ The user's email address.
+  }
+  deriving stock (Eq, Show, Generic)
+
+instance FromJSON User where
+  parseJSON = genericParseJSON aesonOptions
+
+instance ToJSON User where
+  toJSON = genericToJSON aesonOptions
+  toEncoding = genericToEncoding aesonOptions
+
+exampleUser :: User
+exampleUser = User
+  { id = Just "19"
+  , name = Just $ "Robert Hawkins"
+  , email = Just "bob@example.com"
+  }
diff --git a/test/Data/Bugsnag/Types/PayloadSpec.hs b/test/Data/Bugsnag/Types/PayloadSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/Data/Bugsnag/Types/PayloadSpec.hs
@@ -0,0 +1,186 @@
+module Data.Bugsnag.Types.PayloadSpec
+  ( spec
+  )
+where
+
+import Data.Bugsnag.Types.Prelude
+
+import Data.Aeson
+import Data.Bugsnag.Types.Payload
+import Test.Hspec
+
+spec :: Spec
+spec = do
+  describe "ToJSON" $ do
+    it "renders" $ do
+      encode examplePayload
+        `shouldBe` mconcat
+          [ "{\"apiKey\":\"YOUR-NOTIFIER-API-KEY\""
+          , ",\"payloadVersion\":\"5\""
+          , ",\"notifier\":{\"name\":\"Bugsnag Ruby\""
+          , ",\"version\":\"1.0.11\""
+          , ",\"url\":\"https://github.com/bugsnag/bugsnag-ruby\""
+          , ",\"dependencies\":[{\"name\":\"Bugsnag Android\""
+          , ",\"version\":\"2.1.10\""
+          , ",\"url\":\"https://github.com/bugsnag/bugsnag-android\"}]}"
+          , ",\"events\":[{\"exceptions\":[{\"errorClass\":\"NoMethodError\""
+          , ",\"message\":\"Unable to connect to database\""
+          , ",\"stacktrace\":[{\"file\":\"controllers/auth/session_controller.rb\""
+          , ",\"lineNumber\":1234"
+          , ",\"columnNumber\":123"
+          , ",\"method\":\"create\""
+          , ",\"inProject\":true"
+          , ",\"code\":{}"
+          , ",\"frameAddress\":\"0x000000010d131040\""
+          , ",\"loadAddress\":\"0x000000010d12e000\""
+          , ",\"isLR\":false"
+          , ",\"isPC\":true"
+          , ",\"symbolAddress\":\"0x000000010d130fe6\""
+          , ",\"machoFile\":\"/System/Library/Frameworks/Foundation.framework/Foundation\""
+          , ",\"machoLoadAddress\":\"0x000000010d12e000\""
+          , ",\"machoUUID\":\"B3196052-BAF1-3EA5-AD28-F9E6ECCF0B03\""
+          , ",\"machoVMAddress\":\"0x0000000100000000\""
+          , ",\"codeIdentifier\":\"b6b529d5e58421a0fba0fa2c5c2c5f3e\"}]"
+          , ",\"type\":\"android\"}]"
+          , ",\"breadcrumbs\":[{\"timestamp\":\"2016-07-19T12:17:27-0700\""
+          , ",\"name\":\"Open menu\""
+          , ",\"type\":\"navigation\""
+          , ",\"metaData\":{}}]"
+          , ",\"request\":{\"clientIp\":\"192.168.44.0\""
+          , ",\"headers\":{}"
+          , ",\"httpMethod\":\"PUT\""
+          , ",\"url\":\"http://example.com/users/19/settings\""
+          , ",\"referer\":\"http://example.com?q=awesome\"}"
+          , ",\"threads\":[{\"id\":\"thread_id\""
+          , ",\"name\":\"thread_name\""
+          , ",\"errorReportingThread\":true"
+          , ",\"stacktrace\":[{\"file\":\"controllers/auth/session_controller.rb\""
+          , ",\"lineNumber\":1234"
+          , ",\"columnNumber\":123"
+          , ",\"method\":\"create\""
+          , ",\"inProject\":true"
+          , ",\"code\":{}"
+          , ",\"frameAddress\":\"0x000000010d131040\""
+          , ",\"loadAddress\":\"0x000000010d12e000\""
+          , ",\"isLR\":false"
+          , ",\"isPC\":true"
+          , ",\"symbolAddress\":\"0x000000010d130fe6\""
+          , ",\"machoFile\":\"/System/Library/Frameworks/Foundation.framework/Foundation\""
+          , ",\"machoLoadAddress\":\"0x000000010d12e000\""
+          , ",\"machoUUID\":\"B3196052-BAF1-3EA5-AD28-F9E6ECCF0B03\""
+          , ",\"machoVMAddress\":\"0x0000000100000000\""
+          , ",\"codeIdentifier\":\"b6b529d5e58421a0fba0fa2c5c2c5f3e\"}]"
+          , ",\"state\":\"WAITING\""
+          , ",\"type\":\"android\"}]"
+          , ",\"context\":\"auth/session#create\""
+          , ",\"groupingHash\":\"buggy_file.rb\""
+          , ",\"unhandled\":true"
+          , ",\"severity\":\"error\""
+          , ",\"severityReason\":{\"type\":\"unhandledexception\""
+          , ",\"attributes\":{\"errorType\":\"E_ERROR\""
+          , ",\"level\":\"Error\""
+          , ",\"signalType\":\"SIGSEGV\""
+          , ",\"violationType\":\"NetworkOnMainThread\""
+          , ",\"errorClass\":\"ActiveRecord::RecordNotFound\""
+          , ",\"framework\":\"Rack\""
+          , ",\"exceptionClass\":\"TypeMismatchException\"}"
+          , ",\"unhandledOverridden\":false}"
+          , ",\"projectPackages\":[\"com.example.package1\"]"
+          , ",\"user\":{\"id\":\"19\""
+          , ",\"name\":\"Robert Hawkins\""
+          , ",\"email\":\"bob@example.com\"}"
+          , ",\"app\":{\"id\":\"com.bugsnag.android.example.debug\""
+          , ",\"version\":\"1.1.3\""
+          , ",\"versionCode\":12"
+          , ",\"bundleVersion\":\"1.0.2\""
+          , ",\"codeBundleId\":\"1.0-1234\""
+          , ",\"buildUUID\":\"BE5BA3D0-971C-4418-9ECF-E2D1ABCB66BE\""
+          , ",\"releaseStage\":\"staging\""
+          , ",\"type\":\"rails\""
+          , ",\"dsymUUIDs\":[\"e6173678256785afd940392abee\"]"
+          , ",\"duration\":1275"
+          , ",\"durationInForeground\":983"
+          , ",\"inForeground\":true"
+          , ",\"isLaunching\":true"
+          , ",\"binaryArch\":\"x86\""
+          , ",\"runningOnRosetta\":true}"
+          , ",\"device\":{\"hostname\":\"web1.internal\""
+          , ",\"id\":\"fd124e87760c4281aef\""
+          , ",\"manufacturer\":\"LGE\""
+          , ",\"model\":\"Nexus 6P\""
+          , ",\"modelNumber\":\"600\""
+          , ",\"osName\":\"android\""
+          , ",\"osVersion\":\"8.0.1\""
+          , ",\"freeMemory\":183879616"
+          , ",\"totalMemory\":201326592"
+          , ",\"freeDisk\":13478064128"
+          , ",\"browserName\":\"Chrome\""
+          , ",\"browserVersion\":\"61.0.3163.100\""
+          , ",\"jailbroken\":false"
+          , ",\"orientation\":\"portrait\""
+          , ",\"time\":\"2018-08-07T10:16:34.564Z\""
+          , ",\"cpuAbi\":[\"x86_64\"]"
+          , ",\"runtimeVersions\":{\"androidApiLevel\":\"28\""
+          , ",\"bottle\":\"0.12.8\""
+          , ",\"celery\":\"4.2.0\""
+          , ",\"clangVersion\":\"7.0.1\""
+          , ",\"cocos2dx\":\"3.17.2\""
+          , ",\"delayedJob\":\"4.1.8\""
+          , ",\"django\":\"2.1.7\""
+          , ",\"dotnet\":\".NET Framework 4.7.3416.0\""
+          , ",\"dotnetApiCompatibility\":\".NET 2.0 Subset\""
+          , ",\"dotnetClr\":\"4.0.30319.17379\""
+          , ",\"dotnetScriptingRuntime\":\".NET 3.5 equivalent\""
+          , ",\"electron\":\"11.4.3\""
+          , ",\"eventMachine\":\"1.2.7\""
+          , ",\"expoApp\":\"2.10.0.105125\""
+          , ",\"expoSdk\":\"32.0.0\""
+          , ",\"flask\":\"1.0.2\""
+          , ",\"gin\":\"1.3.0\""
+          , ",\"go\":\"1.11.2\""
+          , ",\"javaType\":\"Java(TM) SE Runtime Environment\""
+          , ",\"javaVersion\":\"1.8.0_131-b11\""
+          , ",\"jruby\":\"9.2.5.0\""
+          , ",\"laravel\":\"5.7.22\""
+          , ",\"lumen\":\"5.7\""
+          , ",\"magento\":\"2.3.0\""
+          , ",\"mailman\":\"0.8.0\""
+          , ",\"martini\":\"1.0\""
+          , ",\"negroni\":\"1.0.0\""
+          , ",\"node\":\"10.14.1\""
+          , ",\"osBuild\":\"16D57\""
+          , ",\"php\":\"7.2.12\""
+          , ",\"python\":\"3.7.1\""
+          , ",\"que\":\"0.14.3\""
+          , ",\"rack\":\"2.0.6\""
+          , ",\"rails\":\"5.2.2\""
+          , ",\"rake\":\"12.3.2\""
+          , ",\"reactNative\":\"0.57.5\""
+          , ",\"reactNativeJsEngine\":\"hermes\""
+          , ",\"resque\":\"2.0.0\""
+          , ",\"revel\":\"0.21.0\""
+          , ",\"ruby\":\"2.5.3\""
+          , ",\"shoryoken\":\"5.0.1\""
+          , ",\"sidekiq\":\"5.1.3\""
+          , ",\"silex\":\"2.1.0\""
+          , ",\"sinatra\":\"2.0.3\""
+          , ",\"springBoot\":\"1.5.13.RELEASE\""
+          , ",\"springFramework\":\"4.2.13.RELEASE\""
+          , ",\"swift\":\"4.2\""
+          , ",\"symfony\":\"4.2.11\""
+          , ",\"tornado\":\"5.1.1\""
+          , ",\"unity\":\"2018.2.17\""
+          , ",\"unityScriptingBackend\":\"Mono\""
+          , ",\"wordpress\":\"5.1\"}"
+          , ",\"macCatalystiOSVersion\":\"14.0\"}"
+          , ",\"session\":{\"id\":\"9f65c975-8155-456f-91e5-c4c4b3db0555\""
+          , ",\"startedAt\":\"2017-01-01T14:30:00.000Z\""
+          , ",\"events\":{\"handled\":1"
+          , ",\"unhandled\":1}}"
+          , ",\"featureFlags\":[{\"featureFlag\":\"share_ios_photo_sharing_button\""
+          , ",\"variant\":\"blue_button\"}]"
+          , ",\"metaData\":{}}]}"
+          ]
+
+    it "round-trips" $ do
+      eitherDecode (encode examplePayload) `shouldBe` Right examplePayload
diff --git a/test/Spec.hs b/test/Spec.hs
new file mode 100644
--- /dev/null
+++ b/test/Spec.hs
@@ -0,0 +1,2 @@
+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
+{-# OPTIONS_GHC -Wno-missing-export-lists #-}
