diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -8,6 +8,18 @@
 
 -
 
+## 1.17.0
+
+- [S3NP41-v](https://github.com/discord-haskell/discord-haskell/pull/206) (and [2](https://github.com/discord-haskell/discord-haskell/pull/207)) Audit log and moderation types and gateway events as well as a new intent or two
+
+- [L0neGamer](https://github.com/discord-haskell/discord-haskell/pull/205) Derive instances instead of defining them ourselves
+
+- [julmb](https://github.com/discord-haskell/discord-haskell/pull/204) Add ToJSONKey and FromJSONKey instances to ID types
+
+- [aquarial](https://github.com/discord-haskell/discord-haskell/pull/203) Add more fields to FullApplication
+
+- [L0neGamer](https://github.com/discord-haskell/discord-haskell/pull/202) GHC 9.8 officially supported
+
 ## 1.16.1
 
 - [julmb](https://github.com/discord-haskell/discord-haskell/pull/200) Default instance for InteractionResponseMessage
diff --git a/discord-haskell.cabal b/discord-haskell.cabal
--- a/discord-haskell.cabal
+++ b/discord-haskell.cabal
@@ -1,6 +1,6 @@
 cabal-version:       2.0
 name:                discord-haskell
-version:             1.16.1
+version:             1.17.0
 description:         Functions and data types to write discord bots.
                      Official discord docs <https://discord.com/developers/docs/reference>.
                      .
@@ -20,6 +20,7 @@
                    , GHC == 9.2
                    , GHC == 9.4
                    , GHC == 9.6
+                   , GHC == 9.8
 extra-doc-files:     README.md
                    , changelog.md
 
@@ -143,6 +144,7 @@
     , Discord.Internal.Rest.ApplicationInfo
     , Discord.Internal.Rest.Interactions
     , Discord.Internal.Rest.ScheduledEvents
+    , Discord.Internal.Rest.AutoModeration
     , Discord.Internal.Types
     , Discord.Internal.Types.Prelude
     , Discord.Internal.Types.Channel
@@ -159,10 +161,12 @@
     , Discord.Internal.Types.Emoji
     , Discord.Internal.Types.RolePermissions
     , Discord.Internal.Types.ScheduledEvents
+    , Discord.Internal.Types.AutoModeration
+    , Discord.Internal.Types.AuditLog
   build-depends:
   -- https://gitlab.haskell.org/ghc/ghc/-/wikis/commentary/libraries/version-history
-  -- below also sets the GHC version effectively. set to == 8.10.*, == 9.0.*., == 9.2.*, == 9.4.*, == 9.6.*
-    base == 4.14.* || == 4.15.* || == 4.16.* || == 4.17.* || == 4.18.*,
+  -- below also sets the GHC version effectively. set to == 8.10.*, == 9.0.*., == 9.2.*, == 9.4.*, == 9.6.*, == 9.8.*
+    base == 4.14.* || == 4.15.* || == 4.16.* || == 4.17.* || == 4.18.* || == 4.19.*,
     aeson >= 2.0 && < 2.3,
     async >=2.2 && <2.3,
     bytestring >=0.10 && <0.13,
@@ -170,6 +174,7 @@
     containers >=0.6 && <0.7,
     data-default >=0.7 && <0.8,
     emojis >=0.1.3 && <0.2,
+    hashable >= 1.4.0.0 && <1.5,
     http-client >=0.6 && <0.8,
     iso8601-time >=0.1 && <0.2,
     MonadRandom >=0.5 && <0.7,
@@ -177,7 +182,7 @@
     safe-exceptions >=0.1 && <0.2,
     text >=1.2 && <3,
     time >=1.9 && <1.13,
-    websockets >=0.12 && <0.13,
+    websockets >=0.12 && <0.14,
     network >=3.0.0.0 && <3.2.0.0,
     wuss >=1.1 && <3,
     mtl >=2.2 && <2.4,
diff --git a/src/Discord/Internal/Rest/AutoModeration.hs b/src/Discord/Internal/Rest/AutoModeration.hs
new file mode 100644
--- /dev/null
+++ b/src/Discord/Internal/Rest/AutoModeration.hs
@@ -0,0 +1,97 @@
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+module Discord.Internal.Rest.AutoModeration 
+  ( AutoModerationRequest(..)
+  , MakeAutoModerationRule(..)
+  ) where
+
+import Data.Aeson
+import Discord.Internal.Types
+import Discord.Internal.Rest.Prelude
+import           Network.HTTP.Req ((/:), (/~))
+import qualified Network.HTTP.Req as R
+
+instance Request (AutoModerationRequest a) where
+  majorRoute  = autoModerationMajorRoute
+  jsonRequest = autoModerationJsonRequest
+
+data AutoModerationRequest a where
+  -- | Returns all audo moderation rules in a guild
+  ListAutoModerationRules  :: GuildId -> AutoModerationRequest [AutoModerationRule]
+  -- | Returns an auto moderation rule from its id
+  GetAutoModerationRule    :: GuildId -> AutoModerationRuleId -> AutoModerationRequest AutoModerationRule
+  -- | Creates an auto moderation rule in a guild
+  CreateAutoModerationRule :: GuildId -> MakeAutoModerationRule -> AutoModerationRequest ()
+  -- | Modifies (Replaces) an auto moderation rule in a guild
+  ModifyAutoModerationRule :: GuildId -> AutoModerationRuleId -> MakeAutoModerationRule -> AutoModerationRequest AutoModerationRule
+  -- | Deletes an auto moderation rule from its id
+  DeleteAutoModerationRule :: GuildId -> AutoModerationRuleId -> AutoModerationRequest ()
+
+
+data MakeAutoModerationRule = MakeAutoModerationRule
+  { makeAutoModerationRuleName            :: String
+  , makeAutoModerationRuleEventType       :: AutoModerationRuleEventType
+  , makeAutoModerationRuleTriggerType     :: AutoModerationRuleTriggerType
+  , makeAutoModerationRuleTriggerMetadata :: Maybe AutoModerationRuleTriggerMetadata
+  , makeAutoModerationRuleActions         :: [AutoModerationRuleAction]
+  , makeAutoModerationRuleEnabled         :: Bool
+  , makeAutoModerationRuleExemptRoles     :: [RoleId]
+  , makeAutoModerationRuleExemptChannels  :: [ChannelId]
+  } deriving ( Show, Read )
+
+instance FromJSON MakeAutoModerationRule where
+  parseJSON = withObject "MakeAutoModerationRule" $ \o ->
+    MakeAutoModerationRule <$> o .:  "name"
+                           <*> o .:  "event_type"
+                           <*> o .:  "trigger_type"
+                           <*> o .:? "trigger_metadata"
+                           <*> o .:  "actions"
+                           <*> o .:  "enabled"
+                           <*> o .:  "exempt_roles"
+                           <*> o .:  "exempt_channels"
+
+instance ToJSON MakeAutoModerationRule where
+  toJSON MakeAutoModerationRule{..} = objectFromMaybes
+    [ "name"              .== makeAutoModerationRuleName
+    , "event_type"        .== makeAutoModerationRuleEventType
+    , "trigger_type"      .== makeAutoModerationRuleTriggerType
+    , "trigger_metadata"  .=? makeAutoModerationRuleTriggerMetadata
+    , "actions"           .== makeAutoModerationRuleActions
+    , "enabled"           .== makeAutoModerationRuleEnabled
+    , "exempt_roles"      .== makeAutoModerationRuleExemptRoles
+    , "exempt_channels"   .== makeAutoModerationRuleExemptChannels
+    ]
+
+autoModerationMajorRoute :: AutoModerationRequest a -> String
+autoModerationMajorRoute c = case c of
+  (ListAutoModerationRules g) ->          "guild " <> show g
+  (GetAutoModerationRule g _) ->          "guild " <> show g
+  (CreateAutoModerationRule g _) ->       "guild " <> show g
+  (ModifyAutoModerationRule g _ _) ->     "guild " <> show g
+  (DeleteAutoModerationRule g _) ->       "guild " <> show g
+
+autoModerationJsonRequest :: AutoModerationRequest r -> JsonRequest
+autoModerationJsonRequest c = case c of
+  (ListAutoModerationRules guild) ->
+      Get (guilds /~ guild /: "auto-moderation" /: "rules") mempty
+  
+  (GetAutoModerationRule guild amid) ->
+      Get (guilds /~ guild /: "auto-moderation" /: "rules" /~ amid) mempty
+
+  (CreateAutoModerationRule guild autoModRule) ->
+      let body = pure (R.ReqBodyJson autoModRule)
+      in Post (guilds /~ guild /: "auto-moderation" /: "rules") body mempty
+
+  (ModifyAutoModerationRule guild amid patch) ->
+      let body = pure (R.ReqBodyJson patch)
+      in Patch (guilds /~ guild /: "auto-moderation" /: "rules" /~ amid) body mempty
+
+  (DeleteAutoModerationRule guild amid) ->
+      Delete (guilds /~ guild /: "auto-moderation" /: "rules" /~ amid) mempty
+  
+  where
+    guilds :: R.Url 'R.Https
+    guilds = baseUrl /: "guilds"
diff --git a/src/Discord/Internal/Rest/Guild.hs b/src/Discord/Internal/Rest/Guild.hs
--- a/src/Discord/Internal/Rest/Guild.hs
+++ b/src/Discord/Internal/Rest/Guild.hs
@@ -28,6 +28,8 @@
 import Discord.Internal.Types
 import Data.Default (Default(..))
 
+import Discord.Internal.Types.AuditLog ( AuditLogEvent(MkAuditLogEvent) )
+
 instance Request (GuildRequest a) where
   majorRoute = guildMajorRoute
   jsonRequest = guildJsonRequest
@@ -108,6 +110,10 @@
   --   that would be removed in a prune operation. Requires the 'KICK_MEMBERS'
   --   permission.
   GetGuildPruneCount       :: GuildId -> Integer -> GuildRequest Object
+  -- | Returns an AuditLog object, includes options about time, action type,
+  --   user that took the action and amount of entries to fetch.
+  --   Requires 'VIEW_AUDIT_LOG' permission
+  GetGuildAuditLog         :: GuildId -> GetAuditLogOpts -> GuildRequest AuditLog
   -- | Begin a prune operation. Requires the 'KICK_MEMBERS' permission. Returns an
   --   object with one 'pruned' key indicating the number of members that were removed
   --   in the prune operation. Fires multiple Guild Member Remove 'Events'.
@@ -320,6 +326,7 @@
     ListActiveThreads <$> o .: "threads"
                       <*> o .: "members"
 
+
 guildMembersTimingToQuery :: GuildMembersTiming -> R.Option 'R.Https
 guildMembersTimingToQuery (GuildMembersTiming mLimit mAfter) =
   let limit = case mLimit of
@@ -357,6 +364,7 @@
   (ModifyGuildRole g _ _) ->         "guild_role " <> show g
   (DeleteGuildRole g _) ->           "guild_role " <> show g
   (GetGuildPruneCount g _) ->       "guild_prune " <> show g
+  (GetGuildAuditLog g _) ->               "guild " <> show g
   (BeginGuildPrune g _) ->          "guild_prune " <> show g
   (GetGuildVoiceRegions g) ->       "guild_voice " <> show g
   (GetGuildInvites g) ->            "guild_invit " <> show g
@@ -453,6 +461,27 @@
 
   (GetGuildPruneCount guild days) ->
       Get (guilds /~ guild /: "prune") ("days" R.=: days)
+
+  (GetGuildAuditLog guild auditOpts) ->
+      let user_id = case getAuditLogUserId auditOpts of
+            Nothing  -> mempty
+            Just uid -> "user_id" R.=: uid
+          action_type = case getAuditLogActionType auditOpts of
+            Nothing                  -> mempty
+            Just (MkAuditLogEvent n) -> "action_type" R.=: n
+
+          timing = case getAuditLogTiming auditOpts of
+            Nothing                    -> mempty
+            Just LatestLogEntries      -> mempty
+            Just (BeforeLogEntry snow) -> "before" R.=: snow
+            Just (AfterLogEntry snow)  -> "after"  R.=: snow
+
+          limit = case getAuditLogLimit auditOpts of
+            Nothing -> mempty
+            Just n  -> "limit" R.=: max 1 (min 100 n)
+      
+          body = user_id <> action_type <> timing <> limit
+      in Get (guilds /~ guild /: "audit-logs") body
 
   (BeginGuildPrune guild days) ->
       Post (guilds /~ guild /: "prune") (pure R.NoReqBody) ("days" R.=: days)
diff --git a/src/Discord/Internal/Types.hs b/src/Discord/Internal/Types.hs
--- a/src/Discord/Internal/Types.hs
+++ b/src/Discord/Internal/Types.hs
@@ -12,6 +12,8 @@
     module Discord.Internal.Types.Components,
     module Discord.Internal.Types.Emoji,
     module Discord.Internal.Types.RolePermissions,
+    module Discord.Internal.Types.AutoModeration,
+    module Discord.Internal.Types.AuditLog,
     module Data.Aeson,
     module Data.Time.Clock,
     userFacingEvent,
@@ -32,12 +34,18 @@
 import Discord.Internal.Types.Prelude
 import Discord.Internal.Types.User
 import Discord.Internal.Types.RolePermissions
+import Discord.Internal.Types.AutoModeration
+import Discord.Internal.Types.AuditLog hiding ( MkAuditLogEvent )
 
 -- | Converts an internal event to its user facing counterpart
 userFacingEvent :: EventInternalParse -> Event
 userFacingEvent event = case event of
   InternalReady a b c d e f g -> Ready a b c d e f g
   InternalResumed a -> Resumed a
+  InternalAutoModerationRuleCreate a -> AutoModerationRuleCreate a
+  InternalAutoModerationRuleUpdate a -> AutoModerationRuleUpdate a
+  InternalAutoModerationRuleDelete a -> AutoModerationRuleDelete a
+  InternalAutoModerationActionExecution a -> AutoModerationActionExecution a
   InternalChannelCreate a -> ChannelCreate a
   InternalChannelUpdate a -> ChannelUpdate a
   InternalChannelDelete a -> ChannelDelete a
@@ -65,6 +73,7 @@
   InternalMessageCreate a -> MessageCreate a
   InternalMessageUpdate a b -> MessageUpdate a b
   InternalMessageDelete a b -> MessageDelete a b
+  InternalGuildAuditLogEntryCreate a -> GuildAuditLogEntryCreate a
   InternalMessageDeleteBulk a b -> MessageDeleteBulk a b
   InternalMessageReactionAdd a -> MessageReactionAdd a
   InternalMessageReactionRemove a -> MessageReactionRemove a
diff --git a/src/Discord/Internal/Types/ApplicationInfo.hs b/src/Discord/Internal/Types/ApplicationInfo.hs
--- a/src/Discord/Internal/Types/ApplicationInfo.hs
+++ b/src/Discord/Internal/Types/ApplicationInfo.hs
@@ -5,19 +5,130 @@
 module Discord.Internal.Types.ApplicationInfo where
 
 import Data.Aeson
+import qualified Data.Aeson.Key as Key
+import qualified Data.Aeson.KeyMap as KM
 import qualified Data.Text as T
 import Discord.Internal.Types.Prelude
 
 -- | Structure containing partial information about an Application
+--    <https://discord.com/developers/docs/resources/application#application-object>
 data FullApplication = FullApplication
   { fullApplicationID :: ApplicationId
   , fullApplicationName :: T.Text
-  , fullApplicationFlags :: Int
-  } deriving (Show, Eq, Read)
+  , fullApplicationIcon :: Maybe T.Text -- ^ Icon hash
+  , fullApplicationDescription :: T.Text
+  , fullApplicationRPCOrigins :: Maybe [T.Text] -- ^ List of RPC origin URLs, if RPC is enabled
+  , fullApplicationBotPublic :: Bool -- ^ When false, only the app owner can add the app to guilds
+  , fullApplicationRequiresCodeGrant :: Bool -- ^ When true, the app's bot will only join upon completion of the full OAuth2 code grant flow
+  , fullApplicationBotUserId :: Maybe UserId -- ^ UserId of the bot user associated with the app
+  -- , fullApplicationBot :: User -- partial user, test what it has?
+  , fullApplicationTermsOfServiceUrl :: Maybe T.Text
+  , fullApplicationPrivacyPolicyUrl :: Maybe T.Text
+  , fullApplicationOwnerId :: Maybe UserId -- ^ UserId for the bot user associated with the app
+  -- , fullApplicationOwner :: User -- ^ partial user, test what it has?
+  , fullApplicationVerifyKey :: T.Text -- ^ Hex encoded key for verification in interactions and the GameSDK's GetTicket
+  , fullApplicationTeam :: Maybe DiscordTeam -- ^ Included if the app belongs to a team
+  , fullApplicationGuildId :: Maybe GuildId -- ^ Guild ID associated with the App. 
+  -- fullapplicationGuild :: PartialGuild -- ^ Don't include this because it's partial
+  , fullApplicationGameSKUId :: Maybe GameSKUId
+  , fullapplicationSlug  :: Maybe T.Text -- ^ If this app is a game sold on Discord, this field will be the URL slug that links to the store page
+  , fullApplicationCoverImage :: Maybe T.Text -- ^ App's default rich presence invite cover image hash
+  , fullApplicationFlags :: Maybe Integer -- ^ App's public flags
+  , fullApplicationApproximateGuildCount :: Maybe Integer -- ^ Approximate count of guilds the app has been added to
+  , fullApplicationRedirectURIs :: Maybe [T.Text] -- ^ Array of redirect URIs for the app
+  , fullApplicationInteractionEndpointURL :: Maybe T.Text -- ^ Interactions endpoint URL for the app
+  , fullApplicationRoleConnectionVerificationURL :: Maybe T.Text -- ^ Role connection verification URL for the app
+  , fullApplicationTags :: Maybe [T.Text] -- ^ List of tags describing the content and functionality of the app. Max of 5 tags.
+  , fullApplicationInstallParams :: Maybe DiscordInstallParams
+  , fullApplicationCustomInstallUrl :: Maybe T.Text -- ^ Default custom authorization URL for the app, if enabled
+  } deriving (Show, Read, Eq, Ord)
 
+
 instance FromJSON FullApplication where
   parseJSON = withObject "FullApplication" $ \o ->
     FullApplication <$> o .: "id"
                     <*> o .: "name"
-                    <*> o .: "flags"
+                    <*> o .:? "icon"
+                    <*> o .: "description"
+                    <*> o .:? "rpc_origins"
+                    <*> o .: "bot_public"
+                    <*> o .: "bot_require_code_grant"
+                    <*> (extractId <$> (o .:? "bot"))
+                    <*> o .:? "terms_of_service_url"
+                    <*> o .:? "privacy_policy_url"
+                    <*> (extractId <$> (o .:? "owner"))
+                    <*> o .: "verify_key"
+                    <*> o .:? "team"
+                    <*> o .:? "guild_id"
+                    -- <*> o .:? "guild"
+                    <*> o .:? "primary_sku_id"
+                    <*> o .:? "slug"
+                    <*> o .:? "cover_image"
+                    <*> o .:? "flags"
+                    <*> o .:? "approximate_guild_count"
+                    <*> o .:? "redirect_uris"
+                    <*> o .:? "interactions_endpoint_url"
+                    <*> o .:? "role_connections_verification_url"
+                    <*> o .:? "tags"
+                    <*> o .:? "install_params"
+                    <*> o .:? "custom_install_url"
+    where
+    extractId :: FromJSON a => Maybe Object -> Maybe a
+    extractId maybeBot = do
+      bot <- maybeBot
+      v <- KM.lookup (Key.fromText "id") bot
+      case fromJSON v of
+          Success a -> Just a
+          _         -> Nothing
 
+data DiscordTeam = DiscordTeam
+  { discordTeamIcon :: Maybe T.Text
+  , discordTeamId :: DiscordTeamId
+  , discordTeamMembers :: [DiscordTeamMember]
+  , discordTeamName :: T.Text
+  , discordTeamOwnerUserId :: UserId
+  } deriving (Show, Read, Eq, Ord)
+
+instance FromJSON DiscordTeam where
+  parseJSON = withObject "DiscordTeam" $ \o ->
+    DiscordTeam <$> o .:? "icon" -- ^ Hash of the image of the team's icon
+                <*> o .:  "id"
+                <*> o .:  "members"
+                <*> o .:  "name"
+                <*> o .:  "owner_user_id" -- ^ User ID of the current team owner
+
+data DiscordTeamMember = DiscordTeamMember
+  { discordTeamMemberState :: DiscordTeamMemberState
+  , discordTeamMemberParentTeam :: DiscordTeamId
+  , discordTeamMemberUserId :: UserId
+  , discordTeamMemberOwnerRole :: T.Text
+  } deriving (Show, Read, Eq, Ord)
+
+instance FromJSON DiscordTeamMember where
+  parseJSON = withObject "DiscordTeamMember" $ \o ->
+    DiscordTeamMember <$> (parseState <$> (o .: "membership_state"))
+                      <*> o .: "team_id"
+                      <*> (o .: "user" >>= (.: "id"))
+                      <*> o .: "role"
+    where
+      parseState :: Integer -> DiscordTeamMemberState
+      parseState 1 = DiscordTeamMemberStateInvited
+      parseState 2 = DiscordTeamMemberStateAccepted
+      parseState _ = DiscordTeamMemberStateUnknown
+
+data DiscordTeamMemberState = DiscordTeamMemberStateInvited
+                            | DiscordTeamMemberStateAccepted
+                            | DiscordTeamMemberStateUnknown
+  deriving (Show, Read, Eq, Ord)
+
+
+
+data DiscordInstallParams = DiscordInstallParams
+    { discordInstallParamsScopes :: [T.Text]
+    , discordInstallParamsPermissions :: T.Text
+    } deriving (Show, Read, Eq, Ord)
+
+instance FromJSON DiscordInstallParams where
+  parseJSON = withObject "DiscordInstallParams" $ \o ->
+    DiscordInstallParams <$> o .: "scopes"
+                         <*> o .: "permissions"
diff --git a/src/Discord/Internal/Types/AuditLog.hs b/src/Discord/Internal/Types/AuditLog.hs
new file mode 100644
--- /dev/null
+++ b/src/Discord/Internal/Types/AuditLog.hs
@@ -0,0 +1,149 @@
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+module Discord.Internal.Types.AuditLog 
+  ( AuditLog (..)
+  , AuditLogEntry (..)
+  , AuditLogChange (..)
+  , AuditLogEntryOptions
+  , AuditLogTiming (..)
+  , GetAuditLogOpts (..)
+  , AuditLogEvent (..)
+  , toAuditLogEvent
+  ) where
+
+
+import Data.Aeson
+
+import Discord.Internal.Types.Guild (Integration)
+import Discord.Internal.Types.Prelude
+import Discord.Internal.Types.User
+import Discord.Internal.Types.ScheduledEvents
+import Discord.Internal.Types.Channel
+import Discord.Internal.Types.ApplicationCommands
+import Discord.Internal.Types.AutoModeration
+import Data.Default (Default(..))
+
+
+
+-- | Audit log object, along with the entries it also contains referenced users, integrations [...] and so on
+data AuditLog = AuditLog
+  { auditLogEntries             :: [AuditLogEntry]
+  , auditLogUsers               :: [User]
+  , auditLogIntegrations        :: [Integration]
+  , auditLogWebhooks            :: [Webhook]
+  , auditlogScheduledEvents     :: [ScheduledEvent]
+  , auditLogThreads             :: [Channel]
+  , auditLogApplicationCommands :: [ApplicationCommand]
+  , auditLogAutoModerationRules :: [AutoModerationRule]
+  } deriving ( Eq, Show, Read )
+
+
+instance FromJSON AuditLog where
+  parseJSON = withObject "AuditLog" $ \o ->
+    AuditLog <$> o .: "audit_log_entries"
+             <*> o .: "users"
+             <*> o .: "integrations"
+             <*> o .: "webhooks"
+             <*> o .: "guild_scheduled_events"
+             <*> o .: "threads"
+             <*> o .: "application_commands"
+             <*> o .: "auto_moderation_rules"
+
+-- | An audit log entry object, so to speak the actual event that took place
+data AuditLogEntry = AuditLogEntry
+  { auditLogEntryId         :: AuditLogEntryId
+  , auditLogEntryActionType :: AuditLogEvent
+  , auditLogEntryUserId     :: Maybe UserId
+  , auditLogEntryTargetId   :: Maybe Snowflake
+  , auditLogEntryChanges    :: Maybe [AuditLogChange]
+  , auditLogEntryOptions    :: Maybe AuditLogEntryOptions
+  , auditLogEntryReasons    :: Maybe String
+  } deriving ( Eq, Show, Read )
+
+instance FromJSON AuditLogEntry where
+  parseJSON = withObject "AuditLogEntry" $ \o ->
+    AuditLogEntry <$> o .:  "id"
+                  <*> o .:  "action_type"
+                  <*> o .:? "user_id"
+                  <*> o .:? "target_id"
+                  <*> o .:? "changes"
+                  <*> o .:? "options"
+                  <*> o .:? "reasons"
+
+newtype AuditLogEvent = MkAuditLogEvent Int
+  deriving ( Eq, Show, Read )
+
+instance FromJSON AuditLogEvent where
+  parseJSON = fmap MkAuditLogEvent . parseJSON
+
+-- | A change object, new value and old value fields are of Aesons `Value` type,
+--   because it can be pretty much any value from discord api
+data AuditLogChange = AuditLogChange
+  { auditLogChangeKey      :: String
+  , auditLogChangeNewValue :: Maybe Value
+  , auditLogChangeOldValue :: Maybe Value
+  } deriving ( Eq, Show, Read )
+
+instance FromJSON AuditLogChange where
+  parseJSON = withObject "AuditLogChange" $ \o ->
+    AuditLogChange <$> o .:  "key"
+                   <*> o .:? "new_value"
+                   <*> o .:? "old_value"
+
+-- | Optional data for the Audit Log Entry object
+data AuditLogEntryOptions = AuditLogEntryOptions
+  { auditLogEntryOptionApplicationId                  :: Maybe ApplicationId
+  , auditLogEntryOptionAutoModerationRuleName         :: Maybe String
+  , auditLogEntryOptionAutoModerationRuleTriggerType  :: Maybe String
+  , auditLogEntryOptionChannelId                      :: Maybe ChannelId
+  , auditLogEntryOptionCount                          :: Maybe String
+  , auditLogEntryOptionDeleteMemberDays               :: Maybe String
+  , auditLogEntryOptionId                             :: Maybe Snowflake
+  , auditLogEntryOptionMembersRemoved                 :: Maybe String
+  , auditLogEntryOptionMessageId                      :: Maybe MessageId
+  , auditLogEntryOptionRoleName                       :: Maybe String
+  , auditLogEntryOptionType                           :: Maybe String
+  , auditLogEntryOptionIntegrationType                :: Maybe String
+  } deriving ( Eq, Show, Read )
+
+instance FromJSON AuditLogEntryOptions where
+  parseJSON = withObject "AuditLogEntryOption" $ \o ->
+    AuditLogEntryOptions <$> o .:? "application_id"
+                         <*> o .:? "auto_moderation_rule_name"
+                         <*> o .:? "auto_moderation_rule_trigger_type"
+                         <*> o .:? "channel_id"
+                         <*> o .:? "count"
+                         <*> o .:? "delete_member_days"
+                         <*> o .:? "id"
+                         <*> o .:? "members_removed"
+                         <*> o .:? "message_id"
+                         <*> o .:? "role_name"
+                         <*> o .:? "type"
+                         <*> o .:? "integration_type"
+
+-- | Options for `GetAuditLog` request
+data GetAuditLogOpts = GetAuditLogOpts
+  { getAuditLogUserId     :: Maybe UserId
+  , getAuditLogActionType :: Maybe AuditLogEvent
+  , getAuditLogTiming     :: Maybe AuditLogTiming
+  , getAuditLogLimit      :: Maybe Int
+  } deriving ( Eq, Show, Read)
+
+instance Default GetAuditLogOpts where
+  def = GetAuditLogOpts { getAuditLogUserId     = Nothing
+                        , getAuditLogActionType = Nothing
+                        , getAuditLogTiming     = Nothing
+                        , getAuditLogLimit      = Nothing
+                        }
+
+data AuditLogTiming = BeforeLogEntry AuditLogEntryId
+                    | AfterLogEntry AuditLogEntryId
+                    | LatestLogEntries
+  deriving ( Show, Read, Eq, Ord)
+
+-- | See <https://discord.com/developers/docs/resources/audit-log#audit-log-entry-object-audit-log-events> for more information on Events
+toAuditLogEvent :: Int -> Maybe AuditLogEvent
+toAuditLogEvent i = if i `elem` (1 : 121 : [10..15] <> [20..42] <> [50..52] <> [60..62] <> [72..75] <> [80..85] <> [90..92] <> [100..102] <> [110..112] <> [140..145] <> [150, 151])
+  then Just (MkAuditLogEvent i) else Nothing
diff --git a/src/Discord/Internal/Types/AutoModeration.hs b/src/Discord/Internal/Types/AutoModeration.hs
new file mode 100644
--- /dev/null
+++ b/src/Discord/Internal/Types/AutoModeration.hs
@@ -0,0 +1,192 @@
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+module Discord.Internal.Types.AutoModeration where
+
+import Data.Aeson
+import Discord.Internal.Types.Prelude
+import Data.Scientific ( toBoundedInteger )
+
+
+data AutoModerationRule = AutoModerationRule
+  { autoModerationRuleId              :: AutoModerationRuleId
+  , autoModerationRuleGuildId         :: GuildId
+  , autoModerationRuleName            :: String
+  , autoModerationRuleCreatorId       :: UserId
+  , autoModerationRuleEventType       :: AutoModerationRuleEventType
+  , autoModerationRuleTriggerType     :: AutoModerationRuleTriggerType
+  , autoModerationRuleTriggerMetadata :: AutoModerationRuleTriggerMetadata
+  , autoModerationRuleActions         :: [AutoModerationRuleAction]
+  , autoModerationRuleEnabled         :: Bool
+  , autoModerationRuleExemptRoles     :: [RoleId]
+  , autoModerationRuleExemptChannels  :: [ChannelId]
+  } deriving ( Eq, Show, Read )
+
+instance FromJSON AutoModerationRule where
+  parseJSON = withObject "AutoModerationRule" $ \o ->
+    AutoModerationRule <$> o .: "id"
+                       <*> o .: "guild_id"
+                       <*> o .: "name"
+                       <*> o .: "creator_id"
+                       <*> o .: "event_type"
+                       <*> o .: "trigger_type"
+                       <*> o .: "trigger_metadata"
+                       <*> o .: "actions"
+                       <*> o .: "enabled"
+                       <*> o .: "exempt_roles"
+                       <*> o .: "exempt_channels"
+
+instance ToJSON AutoModerationRule where
+  toJSON AutoModerationRule{..} = object
+    [ ("id", toJSON autoModerationRuleGuildId)
+    , ("guild_id", toJSON autoModerationRuleGuildId)
+    , ("name", toJSON autoModerationRuleName)
+    , ("creator_id", toJSON autoModerationRuleCreatorId)
+    , ("event_type", toJSON autoModerationRuleEventType)
+    , ("trigger_type", toJSON autoModerationRuleTriggerType)
+    , ("trigger_metadata", toJSON autoModerationRuleTriggerMetadata)
+    , ("actions", toJSON autoModerationRuleActions)
+    , ("enabled", toJSON autoModerationRuleEnabled)
+    , ("exempt_roles", toJSON autoModerationRuleExemptRoles)
+    , ("exempt_channels", toJSON autoModerationRuleExemptChannels)
+    ]
+
+-- Discord makes it pretty clear they left room for updates, so far this is the only event type
+-- See <https://discord.com/developers/docs/resources/auto-moderation#auto-moderation-rule-object-event-types>
+data AutoModerationRuleEventType
+  = MessageSent
+  deriving ( Eq, Show, Read )
+
+instance FromJSON AutoModerationRuleEventType where
+  parseJSON = withScientific "AutoModerationRuleEventType" $ \v -> case toBoundedInteger v :: Maybe Int of
+    Just 1 -> return MessageSent
+    _      -> fail $ "Could not parse event type: " <> show v
+
+instance ToJSON AutoModerationRuleEventType where
+  toJSON MessageSent = Number 1
+
+
+data AutoModerationRuleTriggerType
+  = Keyword
+  | Spam
+  | KeywordPreset
+  | MentionSpam
+  deriving ( Eq, Show, Read )
+
+instance FromJSON AutoModerationRuleTriggerType where
+  parseJSON = withScientific "AutoModerationTriggerType" $ \v -> case toBoundedInteger v :: Maybe Int of
+    Just 1 -> return Keyword
+    Just 3 -> return Spam
+    Just 4 -> return KeywordPreset
+    Just 5 -> return MentionSpam
+    _      -> fail $ "Could not parse trigger type: " <> show v
+
+instance ToJSON AutoModerationRuleTriggerType where
+  toJSON Keyword        = Number 1
+  toJSON Spam           = Number 3
+  toJSON KeywordPreset  = Number 4
+  toJSON MentionSpam    = Number 5
+
+data AutoModerationRuleTriggerMetadata = AutoModerationRuleTriggerMetadata
+  { autoModerationRuleTriggerMetadataKeywordFilter  :: [String]
+  , autoModerationRuleTriggerMetadataRegexPatterns  :: [String]
+  , autoModerationRuleTriggerMetadataPresets        :: Maybe [AutoModerationRuleTriggerMetadataPreset]
+  , autoModerationRuleTriggerMetadataAllowList      :: [String]
+  , autoModerationRuleTriggerMetadataMentionLimit   :: Maybe Int
+  , autoModerationRuleTriggerMetadataRaidProtection :: Maybe Bool
+  } deriving ( Eq, Show, Read )
+
+instance FromJSON AutoModerationRuleTriggerMetadata where
+  parseJSON = withObject "AutoModerationRuleTriggerMetadata" $ \o ->
+    AutoModerationRuleTriggerMetadata
+      <$> o .:  "keyword_filter"
+      <*> o .:  "regex_patterns"
+      <*> o .:? "presets"
+      <*> o .:  "allow_list"
+      <*> o .:? "mention_total_limit"
+      <*> o .:? "mention_raid_protection_enabled"
+
+instance ToJSON AutoModerationRuleTriggerMetadata where
+  toJSON AutoModerationRuleTriggerMetadata {..} = objectFromMaybes
+    [ "keyword_filter"  .== autoModerationRuleTriggerMetadataKeywordFilter
+    , "regex_patterns"  .== autoModerationRuleTriggerMetadataRegexPatterns
+    , "presets"         .=? autoModerationRuleTriggerMetadataPresets
+    , "allow_list"      .== autoModerationRuleTriggerMetadataAllowList
+    , "mention_total_limit" .=? autoModerationRuleTriggerMetadataMentionLimit
+    , "mention_raid_protection_enabled" .=? autoModerationRuleTriggerMetadataRaidProtection
+    ]
+
+data AutoModerationRuleTriggerMetadataPreset 
+  = Profanity
+  | SexualContent
+  | Slurs
+  deriving ( Eq, Show, Read )
+
+instance FromJSON AutoModerationRuleTriggerMetadataPreset where
+  parseJSON = withScientific "AutoModerationRuleTriggerMetadataPreset" $ \v -> case toBoundedInteger v :: Maybe Int of
+    Just 1 -> return Profanity
+    Just 3 -> return SexualContent
+    Just 4 -> return Slurs
+    _      -> fail $ "Could not parse preset type: " <> show v
+
+instance ToJSON AutoModerationRuleTriggerMetadataPreset where
+  toJSON Profanity      = Number 1
+  toJSON SexualContent  = Number 2
+  toJSON Slurs          = Number 3
+
+data AutoModerationRuleAction = AutoModerationRuleAction
+  { autoModerationRuleActionType      :: AutoModerationRuleActionType
+  , autoModerationRuleActionMetadata  :: Maybe AutoModerationRuleActionMetadata
+  } deriving ( Eq, Show, Read )
+
+instance FromJSON AutoModerationRuleAction where
+  parseJSON = withObject "AutoModerationRuleAction" $ \o ->
+    AutoModerationRuleAction
+      <$> o .: "type"
+      <*> o .: "metadata"
+
+instance ToJSON AutoModerationRuleAction where
+  toJSON AutoModerationRuleAction{..} = object 
+    [ ("type", toJSON autoModerationRuleActionType)
+    , ("metadata", toJSON autoModerationRuleActionMetadata)
+    ]
+
+data AutoModerationRuleActionType
+  = BlockMessage
+  | SendAlertMessage
+  | Timeout
+  deriving ( Eq, Show, Read )
+
+instance FromJSON AutoModerationRuleActionType where
+  parseJSON = withScientific "AutoModerationRuleActionType" $ \v -> case toBoundedInteger v :: Maybe Int of
+    Just 1 -> return BlockMessage
+    Just 3 -> return SendAlertMessage
+    Just 4 -> return Timeout
+    _      -> fail $ "Could not parse action type: " <> show v
+
+instance ToJSON AutoModerationRuleActionType where
+  toJSON BlockMessage     = Number 1
+  toJSON SendAlertMessage = Number 2
+  toJSON Timeout          = Number 3
+
+data AutoModerationRuleActionMetadata = AutoModerationRuleActionMetadata
+  { autoModerationRuleActionMetadataChannelId       :: Maybe ChannelId
+  , autoModerationRuleActionMetadataTimeoutDuration :: Maybe Integer
+  , autoModerationRuleActionMetadataCustomMessage   :: Maybe String
+  } deriving ( Eq, Show, Read )
+
+instance FromJSON AutoModerationRuleActionMetadata where
+  parseJSON = withObject "AutoModerationRuleActionMetadata" $ \o ->
+    AutoModerationRuleActionMetadata
+      <$> o .:? "channel_id"
+      <*> o .:? "duration_seconds"
+      <*> o .:? "custom_message"
+
+instance ToJSON AutoModerationRuleActionMetadata where
+  toJSON AutoModerationRuleActionMetadata{..} = objectFromMaybes
+    [ "channel_id"        .=? autoModerationRuleActionMetadataChannelId
+    , "duration_seconds"  .=? autoModerationRuleActionMetadataTimeoutDuration
+    , "custom_message"    .=? autoModerationRuleActionMetadataCustomMessage
+    ]
diff --git a/src/Discord/Internal/Types/Events.hs b/src/Discord/Internal/Types/Events.hs
--- a/src/Discord/Internal/Types/Events.hs
+++ b/src/Discord/Internal/Types/Events.hs
@@ -1,5 +1,6 @@
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE RecordWildCards #-}
 
 -- | Data structures pertaining to gateway dispatch 'Event's
 module Discord.Internal.Types.Events where
@@ -19,6 +20,8 @@
 import Discord.Internal.Types.Prelude
 import Discord.Internal.Types.Channel
 import Discord.Internal.Types.Guild
+import Discord.Internal.Types.AuditLog (AuditLogEntry)
+import Discord.Internal.Types.AutoModeration (AutoModerationRule, AutoModerationRuleAction, AutoModerationRuleTriggerType)
 import Discord.Internal.Types.User (User, GuildMember)
 import Discord.Internal.Types.Interactions (Interaction)
 import Discord.Internal.Types.Emoji (Emoji)
@@ -31,6 +34,14 @@
     Ready                      Int User [GuildUnavailable] T.Text HostName (Maybe Shard) PartialApplication
   -- | Response to a @Resume@ gateway command
   | Resumed                    [T.Text]
+  -- | New auto moderation rule was created, requires the AutoModerationConfiguration intent
+  | AutoModerationRuleCreate   AutoModerationRule
+  -- | Auto moderation rule was changed, requires the AutoModerationConfiguration intent
+  | AutoModerationRuleUpdate   AutoModerationRule
+  -- | Auto moderation rule was deleted, requires the AutoModerationConfiguration intent
+  | AutoModerationRuleDelete   AutoModerationRule
+  -- | Action from an auto moderation rule was executed, requires the AutoModerationExecution intent
+  | AutoModerationActionExecution  AutoModerationActionExecuteInfo
   -- | new guild channel created
   | ChannelCreate              Channel
   -- | channel was updated
@@ -57,6 +68,8 @@
   | GuildUpdate                Guild
   -- | guild became unavailable, or user left/was removed from a guild
   | GuildDelete                GuildUnavailable
+  -- | new entry to the audit log was added
+  | GuildAuditLogEntryCreate   AuditLogEntry
   -- | user was banned from a guild
   | GuildBanAdd                GuildId User
   -- | user was unbanned from a guild
@@ -115,6 +128,10 @@
 data EventInternalParse =
     InternalReady                      Int User [GuildUnavailable] T.Text HostName (Maybe Shard) PartialApplication
   | InternalResumed                    [T.Text]
+  | InternalAutoModerationRuleCreate   AutoModerationRule
+  | InternalAutoModerationRuleUpdate   AutoModerationRule
+  | InternalAutoModerationRuleDelete   AutoModerationRule
+  | InternalAutoModerationActionExecution AutoModerationActionExecuteInfo
   | InternalChannelCreate              Channel
   | InternalChannelUpdate              Channel
   | InternalChannelDelete              Channel
@@ -128,6 +145,7 @@
   | InternalGuildCreate                Guild GuildCreateData
   | InternalGuildUpdate                Guild
   | InternalGuildDelete                GuildUnavailable
+  | InternalGuildAuditLogEntryCreate   AuditLogEntry
   | InternalGuildBanAdd                GuildId User
   | InternalGuildBanRemove             GuildId User
   | InternalGuildEmojiUpdate           GuildId [Emoji]
@@ -246,8 +264,51 @@
        let utc = posixSecondsToUTCTime posix
        pure (TypingInfo uid cid utc)
 
+-- | Structure containing auto moderation action execution information
+data AutoModerationActionExecuteInfo = AutoModerationActionExecuteInfo
+  { autoModerationActionExecuteInfoGuildId        :: GuildId
+  , autoModerationActionExecuteInfoAction         :: AutoModerationRuleAction
+  , autoModerationActionExecuteInfoRuleId         :: AutoModerationRuleId
+  , autoModerationActionExecuteInfoTriggerType    :: AutoModerationRuleTriggerType
+  , autoModerationActionExecuteInfoUserId         :: UserId
+  , autoModerationActionExecuteInfoChannelId      :: Maybe ChannelId
+  , autoModerationActionExecuteInfoMessageId      :: Maybe MessageId
+  , autoModerationActionExecuteInfoAlertMessageId :: Maybe MessageId
+  , autoModerationActionExecuteInfoContent        :: String
+  , autoModerationActionExecuteInfoMatchedKeyword :: Maybe String
+  , autoModerationActionExecuteInfoMatchedContent :: Maybe String
+  } deriving ( Eq, Show, Read )
 
+instance FromJSON AutoModerationActionExecuteInfo where
+  parseJSON = withObject "AutoModerationActionExecuteInfo" $ \o ->
+    AutoModerationActionExecuteInfo
+      <$> o .:  "guild_id"
+      <*> o .:  "action"
+      <*> o .:  "rule_id"
+      <*> o .:  "rule_trigger_type"
+      <*> o .:  "user_id"
+      <*> o .:? "channel_id"
+      <*> o .:? "message_id"
+      <*> o .:? "alert_system_message_id"
+      <*> o .:  "content"
+      <*> o .:? "matched_keyword"
+      <*> o .:? "matched_content"
 
+instance ToJSON AutoModerationActionExecuteInfo where
+  toJSON AutoModerationActionExecuteInfo{..} = objectFromMaybes
+    [ "guild_id"                  .== autoModerationActionExecuteInfoGuildId
+    , "action"                    .== autoModerationActionExecuteInfoAction
+    , "rule_id"                   .== autoModerationActionExecuteInfoRuleId
+    , "rule_trigger_type"         .== autoModerationActionExecuteInfoTriggerType
+    , "user_id"                   .== autoModerationActionExecuteInfoUserId
+    , "channel_id"                .=? autoModerationActionExecuteInfoChannelId
+    , "message_id"                .=? autoModerationActionExecuteInfoMessageId
+    , "alert_system_message_id"   .=? autoModerationActionExecuteInfoAlertMessageId
+    , "content"                   .== autoModerationActionExecuteInfoContent
+    , "matched_keyword"           .=? autoModerationActionExecuteInfoMatchedKeyword
+    , "matched_content"           .=? autoModerationActionExecuteInfoMatchedContent
+    ]
+
 -- | Convert ToJSON value to FromJSON value
 reparse :: (ToJSON a, FromJSON b) => a -> Parser b
 reparse val = case parseEither parseJSON $ toJSON val of
@@ -276,6 +337,10 @@
                                          <*> o .: "shard"
                                          <*> o .: "application"
     "RESUMED"                   -> InternalResumed <$> o .: "_trace"
+    "AUTO_MODERATION_RULE_CREATE" -> InternalAutoModerationRuleCreate <$> reparse o
+    "AUTO_MODERATION_RULE_UPDATE" -> InternalAutoModerationRuleUpdate <$> reparse o
+    "AUTO_MODERATION_RULE_DELETE" -> InternalAutoModerationRuleDelete <$> reparse o
+    "AUTO_MODERATION_ACTION_EXECUTION" -> InternalAutoModerationActionExecution <$> reparse o
     "CHANNEL_CREATE"            -> InternalChannelCreate             <$> reparse o
     "CHANNEL_UPDATE"            -> InternalChannelUpdate             <$> reparse o
     "CHANNEL_DELETE"            -> InternalChannelDelete             <$> reparse o
@@ -292,6 +357,7 @@
     "GUILD_CREATE"              -> parseGuildCreate o
     "GUILD_UPDATE"              -> InternalGuildUpdate               <$> reparse o
     "GUILD_DELETE"              -> InternalGuildDelete               <$> reparse o
+    "GUILD_AUDIT_LOG_ENTRY_CREATE" -> InternalGuildAuditLogEntryCreate <$> reparse o
     "GUILD_BAN_ADD"             -> InternalGuildBanAdd    <$> o .: "guild_id" <*> o .: "user"
     "GUILD_BAN_REMOVE"          -> InternalGuildBanRemove <$> o .: "guild_id" <*> o .: "user"
     "GUILD_EMOJI_UPDATE"        -> InternalGuildEmojiUpdate <$> o .: "guild_id" <*> o .: "emojis"
diff --git a/src/Discord/Internal/Types/Gateway.hs b/src/Discord/Internal/Types/Gateway.hs
--- a/src/Discord/Internal/Types/Gateway.hs
+++ b/src/Discord/Internal/Types/Gateway.hs
@@ -62,25 +62,29 @@
   , gatewayIntentDirectMessageReactions :: Bool
   , gatewayIntentDirectMessageTyping :: Bool
   , gatewayIntentMessageContent :: Bool
+  , gatewayIntentAutoModerationConfiguration :: Bool
+  , gatewayIntentAutoModerationExecution :: Bool
   } deriving (Show, Read, Eq, Ord)
 
 instance Default GatewayIntent where
-  def = GatewayIntent { gatewayIntentGuilds                 = True
-                      , gatewayIntentMembers                = False -- false
-                      , gatewayIntentBans                   = True
-                      , gatewayIntentEmojis                 = True
-                      , gatewayIntentIntegrations           = True
-                      , gatewayIntentWebhooks               = True
-                      , gatewayIntentInvites                = True
-                      , gatewayIntentVoiceStates            = True
-                      , gatewayIntentPresences              = False  -- false
-                      , gatewayIntentMessageChanges         = True
-                      , gatewayIntentMessageReactions       = True
-                      , gatewayIntentMessageTyping          = True
-                      , gatewayIntentDirectMessageChanges   = True
-                      , gatewayIntentDirectMessageReactions = True
-                      , gatewayIntentDirectMessageTyping    = True
-                      , gatewayIntentMessageContent         = True
+  def = GatewayIntent { gatewayIntentGuilds                      = True
+                      , gatewayIntentMembers                     = False -- false
+                      , gatewayIntentBans                        = True
+                      , gatewayIntentEmojis                      = True
+                      , gatewayIntentIntegrations                = True
+                      , gatewayIntentWebhooks                    = True
+                      , gatewayIntentInvites                     = True
+                      , gatewayIntentVoiceStates                 = True
+                      , gatewayIntentPresences                   = False  -- false
+                      , gatewayIntentMessageChanges              = True
+                      , gatewayIntentMessageReactions            = True
+                      , gatewayIntentMessageTyping               = True
+                      , gatewayIntentDirectMessageChanges        = True
+                      , gatewayIntentDirectMessageReactions      = True
+                      , gatewayIntentDirectMessageTyping         = True
+                      , gatewayIntentMessageContent              = True
+                      , gatewayIntentAutoModerationConfiguration = True
+                      , gatewayIntentAutoModerationExecution     = True
                       }
 
 compileGatewayIntent :: GatewayIntent -> Int
@@ -102,6 +106,8 @@
                        , (2 ^ 13, gatewayIntentDirectMessageReactions)
                        , (2 ^ 14, gatewayIntentDirectMessageTyping)
                        , (2 ^ 15, gatewayIntentMessageContent)
+                       , (2 ^ 20, gatewayIntentAutoModerationConfiguration)
+                       , (2 ^ 21, gatewayIntentAutoModerationExecution)
                        ]
        ]
 
diff --git a/src/Discord/Internal/Types/Prelude.hs b/src/Discord/Internal/Types/Prelude.hs
--- a/src/Discord/Internal/Types/Prelude.hs
+++ b/src/Discord/Internal/Types/Prelude.hs
@@ -4,6 +4,7 @@
 {-# LANGUAGE FlexibleInstances  #-}
 {-# LANGUAGE RankNTypes  #-}
 {-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DerivingStrategies #-}
 
 -- | Provides base types and utility functions needed for modules in Discord.Internal.Types
 module Discord.Internal.Types.Prelude
@@ -24,6 +25,8 @@
   , EmojiId
   , StickerId
   , UserId
+  , DiscordTeamId
+  , GameSKUId
   , RoleId
   , IntegrationId
   , WebhookId
@@ -33,6 +36,8 @@
   , InteractionId
   , ScheduledEventId
   , ScheduledEventEntityId
+  , AuditLogEntryId
+  , AutoModerationRuleId
 
   , DiscordToken (..)
   , InteractionToken
@@ -55,17 +60,17 @@
 
  where
 
-import Data.Bifunctor (first)
 import Data.Bits (Bits(shiftR))
 import Data.Data (Data (dataTypeOf), dataTypeConstrs, fromConstr)
 import Data.Word (Word64)
 import Data.Maybe (catMaybes)
 import Text.Read (readMaybe)
+import Data.Hashable (Hashable)
 
 import Data.Aeson.Types
 import Data.Time.Clock
 import Data.Time.Clock.POSIX
-import Web.Internal.HttpApiData
+import Web.HttpApiData
 
 import qualified Data.ByteString as B
 import qualified Data.Text as T
@@ -85,16 +90,10 @@
 
 -- | A unique integer identifier. Can be used to calculate the creation date of an entity.
 newtype Snowflake = Snowflake { unSnowflake :: Word64 }
-  deriving (Ord, Eq)
-
-instance Show Snowflake where
-  show (Snowflake a) = show a
-
-instance Read Snowflake where
-  readsPrec p = fmap (first Snowflake) . readsPrec p
+  deriving newtype (Ord, Eq, Hashable, Show, Read, ToJSONKey, FromJSONKey, ToHttpApiData)
 
 instance ToJSON Snowflake where
-  toJSON (Snowflake snowflake) = String . T.pack $ show snowflake
+  toJSON = String . T.pack . show
 
 instance FromJSON Snowflake where
   parseJSON =
@@ -102,21 +101,12 @@
       "Snowflake"
       ( \snowflake ->
           case readMaybe (T.unpack snowflake) of
-            Nothing -> fail "null snowflake"
+            Nothing -> fail $ "invalid snowflake: " <> show snowflake
             (Just i) -> pure i
       )
 
-instance ToHttpApiData Snowflake where
-  toUrlPiece = T.pack . show
-
 newtype RolePermissions = RolePermissions { getRolePermissions :: Integer } 
-  deriving (Eq, Ord, Bits)
-
-instance Read RolePermissions where
-  readsPrec p = fmap (first RolePermissions) . readsPrec p
-
-instance ToJSON RolePermissions where
-  toJSON = toJSON . getRolePermissions
+  deriving newtype (Eq, Ord, Bits, Read, Show, ToJSON)
 
 -- In v8 and above, all permissions are serialized as strings.
 -- See https://discord.com/developers/docs/topics/permissions#permissions.
@@ -124,28 +114,10 @@
   parseJSON = withText "RolePermissions" $
       \text -> case readMaybe (T.unpack text) of
               Just perms -> pure $ RolePermissions perms
-              Nothing    -> fail "invalid role permissions integer string"
-
-instance Show RolePermissions where
-  show = show . getRolePermissions
+              Nothing    -> fail $ "invalid role permissions: " <> show text
 
 newtype DiscordId a = DiscordId { unId :: Snowflake }
-  deriving (Ord, Eq)
-
-instance Show (DiscordId a) where
-  show = show . unId
-
-instance Read (DiscordId a) where
-  readsPrec p = fmap (first DiscordId) . readsPrec p
-
-instance ToJSON (DiscordId a) where
-  toJSON = toJSON . unId
-
-instance FromJSON (DiscordId a) where
-  parseJSON = fmap DiscordId . parseJSON
-
-instance ToHttpApiData (DiscordId a) where
-  toUrlPiece = T.pack . show
+  deriving newtype (Ord, Eq, Hashable, Show, Read, ToJSON, ToJSONKey, FromJSON, FromJSONKey, ToHttpApiData)
 
 data ChannelIdType
 type ChannelId = DiscordId ChannelIdType
@@ -174,6 +146,12 @@
 data RoleIdType
 type RoleId = DiscordId RoleIdType
 
+data DiscordTeamIdType
+type DiscordTeamId = DiscordId DiscordTeamIdType
+
+data GameSKUIdType
+type GameSKUId = DiscordId GameSKUIdType
+
 data IntegrationIdType
 type IntegrationId = DiscordId IntegrationIdType
 
@@ -198,23 +176,14 @@
 data ScheduledEventEntityIdType
 type ScheduledEventEntityId = DiscordId ScheduledEventEntityIdType
 
-newtype DiscordToken a = DiscordToken { unToken :: T.Text }
-  deriving (Ord, Eq)
-
-instance Show (DiscordToken a) where
-  show = show . unToken
-
-instance Read (DiscordToken a) where
-  readsPrec p = fmap (first DiscordToken) . readsPrec p
-
-instance ToJSON (DiscordToken a) where
-  toJSON = toJSON . unToken
+data AuditLogEntryIdType
+type AuditLogEntryId = DiscordId AuditLogEntryIdType
 
-instance FromJSON (DiscordToken a) where
-  parseJSON = fmap DiscordToken . parseJSON
+data AutoModerationRuleIdType
+type AutoModerationRuleId = DiscordId AutoModerationRuleIdType
 
-instance ToHttpApiData (DiscordToken a) where
-  toUrlPiece = unToken
+newtype DiscordToken a = DiscordToken { unToken :: T.Text }
+  deriving newtype (Ord, Eq, Show, Read, ToJSON, FromJSON, ToHttpApiData)
 
 type InteractionToken = DiscordToken InteractionIdType
 
diff --git a/src/Discord/Requests.hs b/src/Discord/Requests.hs
--- a/src/Discord/Requests.hs
+++ b/src/Discord/Requests.hs
@@ -10,6 +10,7 @@
   , module Discord.Internal.Rest.ApplicationCommands
   , module Discord.Internal.Rest.Interactions
   , module Discord.Internal.Rest.ScheduledEvents
+  , module Discord.Internal.Rest.AutoModeration
   ) where
 
 import Discord.Internal.Rest.ApplicationInfo
@@ -23,3 +24,4 @@
 import Discord.Internal.Rest.ApplicationCommands
 import Discord.Internal.Rest.Interactions
 import Discord.Internal.Rest.ScheduledEvents
+import Discord.Internal.Rest.AutoModeration
