diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,30 @@
+# 2.0.1.0 (2025-01-09)
+* [#136](https://github.com/MercuryTechnologies/slack-web/pull/136)
+  Bumps the version ranges for dependencies to be compatible with LTS 22.43.
+
+# 2.0.0.4 (2024-09-15)
+* [#135](https://github.com/MercuryTechnologies/slack-web/pull/135)
+  Improves attachement support by providing clients wih the raw JSON value
+  in case of a parse failure.
+
+# 2.0.0.3 (2024-08-30)
+* [#133](https://github.com/MercuryTechnologies/slack-web/pull/133)
+  Adds attachment support for message event subscriptions.
+
+# 2.0.0.2 (2024-08-29)
+* [#132](https://github.com/MercuryTechnologies/slack-web/pull/132)
+  Add support for bot_message event subtype.
+
+# 2.0.0.0 (2023-10-26)
+
+* [#123](https://github.com/MercuryTechnologies/slack-web/pull/123)
+  Add support for section fields.
+
+# 1.6.2.0 (2023-10-24)
+
+* [#127](https://github.com/MercuryTechnologies/slack-web/pull/127)
+  Add helper for the divider block type.
+
 # 1.6.1.0 (2022-12-16)
 
 * [#124](https://github.com/MercuryTechnologies/slack-web/pull/124)
diff --git a/main/cli.hs b/main/cli.hs
--- a/main/cli.hs
+++ b/main/cli.hs
@@ -64,11 +64,12 @@
 
     addCmd "conversations.history" $ do
       conversationId <-
-        Slack.ConversationId . Text.pack
+        Slack.ConversationId
+          . Text.pack
           <$> addParamString "CONVERSATION_ID" (paramHelpStr "ID of the conversation to fetch")
       getsAll <- addSimpleBoolFlag "A" ["all"] (flagHelpStr "Get all available messages in the channel")
-      addCmdImpl $
-        if getsAll
+      addCmdImpl
+        $ if getsAll
           then do
             (`runReaderT` apiConfig) $ do
               fetchPage <- Slack.conversationsHistoryAll $ (SlackConversation.mkHistoryReq conversationId) {SlackConversation.historyReqCount = 2}
@@ -101,7 +102,8 @@
 
     addCmd "conversations.replies" $ do
       conversationId <-
-        Slack.ConversationId . Text.pack
+        Slack.ConversationId
+          . Text.pack
           <$> addParamString "CONVERSATION_ID" (paramHelpStr "ID of the conversation to fetch")
       threadTimeStampStr <- addParamString "TIMESTAMP" (paramHelpStr "Timestamp of the thread to fetch")
       let ethreadTimeStamp = Slack.timestampFromText $ Text.pack threadTimeStampStr
diff --git a/slack-web.cabal b/slack-web.cabal
--- a/slack-web.cabal
+++ b/slack-web.cabal
@@ -1,6 +1,6 @@
 cabal-version: 2.2
 name: slack-web
-version: 1.6.1.0
+version: 2.0.1.0
 
 build-type: Simple
 
@@ -32,7 +32,7 @@
 
 category: Web
 
-tested-with: GHC == 8.10.7 || ==9.2.4 || == 9.4.2
+tested-with: GHC == 8.10.7 || ==9.2.4 || == 9.4.2 || == 9.6.6
 
 extra-source-files:
   CHANGELOG.md
@@ -133,12 +133,12 @@
       Web.Slack.AesonUtils
   build-depends:
       aeson >= 2.0 && < 2.2
-    , base >= 4.11 && < 4.18
+    , base >= 4.11 && < 4.19
     , base16-bytestring
     , bytestring
     , classy-prelude
     , containers
-    , cryptonite
+    , crypton
     , data-default-class
     , deepseq
     , either
@@ -152,9 +152,9 @@
     , mtl
     , refined
     , scientific
-    , servant >= 0.16 && < 0.20
-    , servant-client >= 0.16 && < 0.20
-    , servant-client-core >= 0.16 && < 0.20
+    , servant >= 0.16 && < 0.21
+    , servant-client >= 0.16 && < 0.21
+    , servant-client-core >= 0.16 && < 0.21
     , string-conversions
     , string-variants >= 0.1.0.1
     , text (>= 1.2 && < 1.3) || (>= 2.0 && < 2.1)
@@ -186,6 +186,7 @@
       Web.Slack.Experimental.RequestVerificationSpec
       Web.Slack.Experimental.Events.TypesSpec
       Web.Slack.Experimental.BlocksSpec
+      Web.Slack.Experimental.Blocks.TypesSpec
       TestImport
       TestImport.Aeson
   build-tool-depends:
@@ -205,6 +206,7 @@
     , mtl
     , pretty-simple ^>= 4.1
     , quickcheck-instances
+    , refined
     , slack-web
     , string-conversions
     , string-variants
diff --git a/src/Web/Slack.hs b/src/Web/Slack.hs
--- a/src/Web/Slack.hs
+++ b/src/Web/Slack.hs
@@ -12,34 +12,33 @@
 -- *Since 0.4.0.0*: The API functions is now more intuitive for newbies
 -- than before. If you need compatiblity with the previous version, use
 -- 'Web.Slack.Classy' instead.
-module Web.Slack
-  ( SlackConfig (..),
-    mkSlackConfig,
+module Web.Slack (
+  SlackConfig (..),
+  mkSlackConfig,
 
-    -- * Endpoints
-    apiTest,
-    authTest,
-    chatPostMessage,
-    chatUpdate,
-    conversationsList,
-    conversationsListAll,
-    conversationsHistory,
-    conversationsHistoryAll,
-    conversationsReplies,
-    repliesFetchAll,
-    getUserDesc,
-    usersList,
-    usersListAll,
-    userLookupByEmail,
-    UsersConversations.usersConversations,
-    UsersConversations.usersConversationsAll,
+  -- * Endpoints
+  apiTest,
+  authTest,
+  chatPostMessage,
+  chatUpdate,
+  conversationsList,
+  conversationsListAll,
+  conversationsHistory,
+  conversationsHistoryAll,
+  conversationsReplies,
+  repliesFetchAll,
+  getUserDesc,
+  usersList,
+  usersListAll,
+  userLookupByEmail,
+  UsersConversations.usersConversations,
+  UsersConversations.usersConversationsAll,
 
-    -- * Requests and responses
-    authenticateReq,
-    Response,
-    LoadPage,
-  )
-where
+  -- * Requests and responses
+  authenticateReq,
+  Response,
+  LoadPage,
+) where
 
 -- FIXME: Web.Slack.Prelude
 
diff --git a/src/Web/Slack/AesonUtils.hs b/src/Web/Slack/AesonUtils.hs
--- a/src/Web/Slack/AesonUtils.hs
+++ b/src/Web/Slack/AesonUtils.hs
@@ -76,13 +76,13 @@
 objectOptional = J.object . catMaybes
 
 -- | Encode a value for 'objectOptional'
-(.=!) :: ToJSON v => Key -> v -> Maybe Pair
+(.=!) :: (ToJSON v) => Key -> v -> Maybe Pair
 key .=! val = Just (key .= val)
 
 infixr 8 .=!
 
 -- | Encode a Maybe value for 'objectOptional'
-(.=?) :: ToJSON v => Key -> Maybe v -> Maybe Pair
+(.=?) :: (ToJSON v) => Key -> Maybe v -> Maybe Pair
 key .=? mVal = fmap (key .=) mVal
 
 infixr 8 .=?
diff --git a/src/Web/Slack/Api.hs b/src/Web/Slack/Api.hs
--- a/src/Web/Slack/Api.hs
+++ b/src/Web/Slack/Api.hs
@@ -9,12 +9,11 @@
 -- |
 -- Module: Web.Slack.Api
 -- Description:
-module Web.Slack.Api
-  ( TestReq (..),
-    mkTestReq,
-    TestRsp (..),
-  )
-where
+module Web.Slack.Api (
+  TestReq (..),
+  mkTestReq,
+  TestRsp (..),
+) where
 
 -- FIXME: Web.Slack.Prelude
 
diff --git a/src/Web/Slack/Chat.hs b/src/Web/Slack/Chat.hs
--- a/src/Web/Slack/Chat.hs
+++ b/src/Web/Slack/Chat.hs
@@ -2,16 +2,15 @@
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE TemplateHaskell #-}
 
-module Web.Slack.Chat
-  ( PostMsg (..),
-    PostMsgReq (..),
-    mkPostMsgReq,
-    PostMsgRsp (..),
-    UpdateReq (..),
-    mkUpdateReq,
-    UpdateRsp (..),
-  )
-where
+module Web.Slack.Chat (
+  PostMsg (..),
+  PostMsgReq (..),
+  mkPostMsgReq,
+  PostMsgRsp (..),
+  UpdateReq (..),
+  mkUpdateReq,
+  UpdateRsp (..),
+) where
 
 import Web.FormUrlEncoded
 import Web.Slack.Conversation (ConversationId)
diff --git a/src/Web/Slack/Classy.hs b/src/Web/Slack/Classy.hs
--- a/src/Web/Slack/Classy.hs
+++ b/src/Web/Slack/Classy.hs
@@ -5,27 +5,26 @@
 -- |
 -- Module: Web.Slack.Classy
 -- Description: For compatibility with Web.Slack prior to v0.4.0.0.
-module Web.Slack.Classy
-  ( SlackConfig (..),
-    mkSlackConfig,
-    apiTest,
-    authTest,
-    chatPostMessage,
-    conversationsList,
-    conversationsHistory,
-    conversationsHistoryAll,
-    conversationsReplies,
-    repliesFetchAll,
-    getUserDesc,
-    usersList,
-    userLookupByEmail,
-    authenticateReq,
-    Response,
-    LoadPage,
-    HasManager (..),
-    HasToken (..),
-  )
-where
+module Web.Slack.Classy (
+  SlackConfig (..),
+  mkSlackConfig,
+  apiTest,
+  authTest,
+  chatPostMessage,
+  conversationsList,
+  conversationsHistory,
+  conversationsHistoryAll,
+  conversationsReplies,
+  repliesFetchAll,
+  getUserDesc,
+  usersList,
+  userLookupByEmail,
+  authenticateReq,
+  Response,
+  LoadPage,
+  HasManager (..),
+  HasToken (..),
+) where
 
 import Data.Map qualified as Map
 import Network.HTTP.Client (Manager)
diff --git a/src/Web/Slack/Common.hs b/src/Web/Slack/Common.hs
--- a/src/Web/Slack/Common.hs
+++ b/src/Web/Slack/Common.hs
@@ -15,21 +15,20 @@
 -- |
 -- Module: Web.Slack.Common
 -- Description:
-module Web.Slack.Common
-  ( Color (..),
-    UserId (..),
-    ConversationId (..),
-    TeamId (..),
-    Cursor (..),
-    SlackTimestamp (..),
-    mkSlackTimestamp,
-    timestampFromText,
-    Message (..),
-    MessageType (..),
-    SlackClientError (..),
-    SlackMessageText (..),
-  )
-where
+module Web.Slack.Common (
+  Color (..),
+  UserId (..),
+  ConversationId (..),
+  TeamId (..),
+  Cursor (..),
+  SlackTimestamp (..),
+  mkSlackTimestamp,
+  timestampFromText,
+  Message (..),
+  MessageType (..),
+  SlackClientError (..),
+  SlackMessageText (..),
+) where
 
 -- FIXME: Web.Slack.Prelude
 
diff --git a/src/Web/Slack/Conversation.hs b/src/Web/Slack/Conversation.hs
--- a/src/Web/Slack/Conversation.hs
+++ b/src/Web/Slack/Conversation.hs
@@ -15,27 +15,26 @@
 -- |
 -- Module: Web.Slack.Channel
 -- Description: Types and functions related to <https://api.slack.com/docs/conversations-api Conversation API>
-module Web.Slack.Conversation
-  ( Conversation (..),
-    ConversationId (..),
-    ConversationType (..),
-    ChannelConversation (..),
-    GroupConversation (..),
-    ImConversation (..),
-    TeamId (..),
-    Purpose (..),
-    Topic (..),
-    ListReq (..),
-    mkListReq,
-    ListRsp (..),
-    HistoryReq (..),
-    mkHistoryReq,
-    HistoryRsp (..),
-    RepliesReq (..),
-    mkRepliesReq,
-    ResponseMetadata (..),
-  )
-where
+module Web.Slack.Conversation (
+  Conversation (..),
+  ConversationId (..),
+  ConversationType (..),
+  ChannelConversation (..),
+  GroupConversation (..),
+  ImConversation (..),
+  TeamId (..),
+  Purpose (..),
+  Topic (..),
+  ListReq (..),
+  mkListReq,
+  ListRsp (..),
+  HistoryReq (..),
+  mkHistoryReq,
+  HistoryRsp (..),
+  RepliesReq (..),
+  mkRepliesReq,
+  ResponseMetadata (..),
+) where
 
 import Data.Aeson
 import Data.Aeson.Encoding
@@ -209,7 +208,7 @@
       -- This uses the outer Parser monad since deciding which parser to use
       -- is monadic, then the Maybe to decide which parser is picked, then
       -- finally the inner parser to actually run it
-      parseWhen :: FromJSON a => Key -> (a -> b) -> Object -> Parser (Maybe (Parser b))
+      parseWhen :: (FromJSON a) => Key -> (a -> b) -> Object -> Parser (Maybe (Parser b))
       parseWhen key con o = do
         -- Slack only inconsistently includes the is_* attributes if false.
         is <- o .:? key .!= False
diff --git a/src/Web/Slack/Experimental/Blocks.hs b/src/Web/Slack/Experimental/Blocks.hs
--- a/src/Web/Slack/Experimental/Blocks.hs
+++ b/src/Web/Slack/Experimental/Blocks.hs
@@ -1,79 +1,78 @@
-module Web.Slack.Experimental.Blocks
-  ( -- * General Slack Messages
-    SlackText,
-    (<+>),
-    parens,
-    brackets,
-    angleBrackets,
-    ticks,
-    codeBlock,
-    bold,
-    italic,
-    newline,
-    unorderedList,
-    link,
-    monospaced,
-    mentionUser,
-    isSubStringOf,
-    SlackImage (..),
-    SlackMessage,
-    Markdown (..),
-    Image (..),
-    context,
-    textToMessage,
-    prefixFirstSlackMessage,
-    mentionUserGroupById,
-    textToContext,
-    slackMessage,
-    SlackBlock (..),
+module Web.Slack.Experimental.Blocks (
+  -- * General Slack Messages
+  SlackText,
+  (<+>),
+  parens,
+  brackets,
+  angleBrackets,
+  ticks,
+  codeBlock,
+  bold,
+  italic,
+  newline,
+  unorderedList,
+  link,
+  monospaced,
+  mentionUser,
+  isSubStringOf,
+  SlackImage (..),
+  SlackMessage,
+  Markdown (..),
+  Image (..),
+  context,
+  textToMessage,
+  prefixFirstSlackMessage,
+  mentionUserGroupById,
+  textToContext,
+  slackMessage,
+  SlackBlock (..),
 
-    -- ** Blocks' rich text formatting (receive only!)
-    RichItem (..),
-    RichStyle (..),
-    RichLinkAttrs (..),
-    RichTextSectionItem (..),
-    RichText (..),
+  -- ** Blocks' rich text formatting (receive only!)
+  RichItem (..),
+  RichStyle (..),
+  RichLinkAttrs (..),
+  RichTextSectionItem (..),
+  RichText (..),
 
-    -- * Rendered messages
-    RenderedSlackMessage (..),
-    render,
+  -- * Rendered messages
+  RenderedSlackMessage (..),
+  render,
 
-    -- * Introduction to Slack Interactive Messages
-    -- $interactive
+  -- * Introduction to Slack Interactive Messages
+  -- $interactive
 
-    -- * Creating Slack Interactive Messages
-    actions,
-    actionsWithBlockId,
-    SlackActionId (..),
-    SlackBlockId,
-    setting,
-    emptySetting,
-    SlackStyle (..),
-    plaintext,
-    plaintextonly,
-    mrkdwn,
-    button,
-    buttonSettings,
-    ButtonSettings
-      ( buttonUrl,
-        buttonValue,
-        buttonStyle,
-        buttonConfirm
-      ),
-    confirm,
-    confirmAreYouSure,
-    ConfirmSettings
-      ( confirmTitle,
-        confirmText,
-        confirmConfirm,
-        confirmDeny,
-        confirmStyle
-      ),
+  -- * Creating Slack Interactive Messages
+  actions,
+  actionsWithBlockId,
+  SlackActionId (..),
+  SlackBlockId,
+  setting,
+  emptySetting,
+  SlackStyle (..),
+  plaintext,
+  plaintextonly,
+  mrkdwn,
+  button,
+  buttonSettings,
+  ButtonSettings (
+    buttonUrl,
+    buttonValue,
+    buttonStyle,
+    buttonConfirm
+  ),
+  confirm,
+  confirmAreYouSure,
+  ConfirmSettings (
+    confirmTitle,
+    confirmText,
+    confirmConfirm,
+    confirmDeny,
+    confirmStyle
+  ),
 
-    -- * Responding to Slack Interactive Messages
-    SlackInteractiveResponse (..),
-  )
-where
+  -- * Responding to Slack Interactive Messages
+  SlackInteractiveResponse (..),
+) where
 
 import Data.Aeson.Text (encodeToLazyText)
 import Data.Text qualified as T
@@ -81,6 +80,7 @@
 import Web.Slack.Prelude
 import Web.Slack.Types
 
+-- | Concatenate two 'SlackText's with a space separator.
 (<+>) :: SlackText -> SlackText -> SlackText
 x <+> y = x <> " " <> y
 
@@ -97,7 +97,7 @@
 ticks x = "`" <> x <> "`"
 
 -- | Render a 'Slack' renderable value with ticks around it. Alias for @ticks . message@
-monospaced :: Slack a => a -> SlackText
+monospaced :: (Slack a) => a -> SlackText
 monospaced = ticks . message
 
 codeBlock :: SlackText -> SlackText
@@ -109,6 +109,7 @@
 italic :: SlackText -> SlackText
 italic x = "_" <> x <> "_"
 
+-- | Add a newline before a 'SlackText'.
 newline :: SlackText -> SlackText
 newline x = "\n" <> x
 
@@ -161,22 +162,43 @@
    in (SlackMessage truncatedBlocks, or isTruncateds)
 
 truncateSlackBlock :: SlackBlock -> (SlackBlock, Bool)
-truncateSlackBlock sb@(SlackBlockSection (SlackText texts) mAccessory) =
-  let messageLength = sum $ map T.length texts
+truncateSlackBlock sb@(SlackBlockSection SlackSection {..}) =
+  let texts = maybe mempty unSlackTexts slackSectionText
+      messageLength = sum $ map T.length texts
       lengthLimit = 3000
       truncationMessage = "\n...Rest of message truncated for slack\n"
       truncationMessageLength = T.length truncationMessage
       truncateTexts ts = take (lengthLimit - truncationMessageLength) (concat ts)
+      truncatedSection =
+        SlackBlockSection
+          SlackSection
+            { slackSectionText = Just $ SlackText [truncateTexts texts <> "\n...Rest of message truncated for slack\n"]
+            , slackSectionAccessory
+            , slackSectionBlockId
+            , slackSectionFields
+            }
    in if messageLength > lengthLimit
-        then (SlackBlockSection (SlackText [truncateTexts texts <> "\n...Rest of message truncated for slack\n"]) mAccessory, True)
+        then (truncatedSection, True)
         else (sb, False)
 -- possible to also truncate SlackContexts, but we never put long strings in there.
 truncateSlackBlock x = (x, False)
 
 prefixFirstSlackBlockSection :: Text -> [SlackBlock] -> ([SlackBlock], Bool)
-prefixFirstSlackBlockSection prefix (SlackBlockSection text mAccessory : sbs) = (SlackBlockSection (message prefix <> text) mAccessory : sbs, True)
-prefixFirstSlackBlockSection prefix (sb : sbs) = let (prefixedSbs, match) = prefixFirstSlackBlockSection prefix sbs in (sb : prefixedSbs, match)
-prefixFirstSlackBlockSection _ [] = ([], False)
+prefixFirstSlackBlockSection prefix (SlackBlockSection SlackSection {..} : sbs) =
+  let prefixedSection =
+        SlackBlockSection
+          SlackSection
+            { slackSectionText = mappend (message prefix) <$> slackSectionText
+            , slackSectionBlockId
+            , slackSectionFields
+            , slackSectionAccessory
+            }
+   in (prefixedSection : sbs, True)
+prefixFirstSlackBlockSection prefix (sb : sbs) =
+  let (prefixedSbs, match) = prefixFirstSlackBlockSection prefix sbs
+   in (sb : prefixedSbs, match)
+prefixFirstSlackBlockSection _ [] =
+  ([], False)
 
 prefixFirstSlackMessage :: Text -> [SlackMessage] -> [SlackMessage]
 prefixFirstSlackMessage prefix (sm : sms) =
@@ -189,7 +211,7 @@
 
 -- | Concatenate a list of 'SlackText' into a single block, and wrap it up as a full message
 slackMessage :: [SlackText] -> SlackMessage
-slackMessage = SlackMessage . pure . (`SlackBlockSection` Nothing) . mconcat
+slackMessage = SlackMessage . pure . SlackBlockSection . slackSectionWithText . mconcat
 
 -- $interactive
 --
diff --git a/src/Web/Slack/Experimental/Blocks/Types.hs b/src/Web/Slack/Experimental/Blocks/Types.hs
--- a/src/Web/Slack/Experimental/Blocks/Types.hs
+++ b/src/Web/Slack/Experimental/Blocks/Types.hs
@@ -4,7 +4,7 @@
 module Web.Slack.Experimental.Blocks.Types where
 
 import Control.Monad (MonadFail (..))
-import Data.Aeson (Object, Value (..), withArray)
+import Data.Aeson (Object, Result (..), Value (..), fromJSON, withArray)
 import Data.Aeson.Types ((.!=))
 import Data.StringVariants
 import Data.Vector qualified as V
@@ -49,7 +49,7 @@
 
 -- | Create a 'SlackPlainTextOnly'. Some API points can can take either markdown or plain text,
 -- but some can take only plain text. This enforces the latter.
-plaintextonly :: Slack a => a -> SlackPlainTextOnly
+plaintextonly :: (Slack a) => a -> SlackPlainTextOnly
 plaintextonly a = SlackPlainTextOnly $ message a
 
 data SlackTextObject
@@ -70,24 +70,24 @@
       ]
 
 -- | Create a plain text 'SlackTextObject' where the API allows either markdown or plain text.
-plaintext :: Slack a => a -> SlackTextObject
+plaintext :: (Slack a) => a -> SlackTextObject
 plaintext = SlackPlainText . message
 
 -- | Create a markdown 'SlackTextObject' where the API allows either markdown or plain text.
-mrkdwn :: Slack a => a -> SlackTextObject
+mrkdwn :: (Slack a) => a -> SlackTextObject
 mrkdwn = SlackMarkdownText . message
 
 instance FromJSON SlackTextObject where
   parseJSON = withObject "SlackTextObject" $ \obj -> do
     (slackTextType :: Text) <- obj .: "type"
     case slackTextType of
-      "text" -> do
+      "plain_text" -> do
         text <- obj .: "text"
         pure . SlackPlainText . SlackText $ lines text
       "mrkdwn" -> do
         text <- obj .: "text"
         pure . SlackMarkdownText . SlackText $ lines text
-      _ -> fail "Unknown SlackTextObject type, must be one of ['text', 'mrkdwn']"
+      _ -> fail "Unknown SlackTextObject type, must be one of ['plain_text', 'mrkdwn']"
 
 instance Show SlackText where
   show (SlackText arr) = show $ concat arr
@@ -165,6 +165,13 @@
   | SlackContentImage SlackImage
   deriving stock (Eq)
 
+slackContentToSlackText :: SlackContent -> Maybe SlackText
+slackContentToSlackText c = case c of
+  SlackContentText slackText ->
+    Just slackText
+  SlackContentImage _ ->
+    Nothing
+
 instance Show SlackContent where
   show (SlackContentText t) = show t
   show (SlackContentImage i) = show i
@@ -176,12 +183,12 @@
       , "text" .= t
       ]
   toJSON (SlackContentImage (SlackImage mtitle altText url)) =
-    object $
-      [ "type" .= ("image" :: Text)
-      , "image_url" .= url
-      , "alt_text" .= altText
-      ]
-        <> maybe [] mkTitle mtitle
+    object
+      $ [ "type" .= ("image" :: Text)
+        , "image_url" .= url
+        , "alt_text" .= altText
+        ]
+      <> maybe [] mkTitle mtitle
     where
       mkTitle title =
         [ "title"
@@ -361,10 +368,34 @@
 
 -- | Small helper function for constructing a section with a button accessory out of a button and text components
 sectionWithButtonAccessory :: SlackAction -> SlackText -> SlackBlock
-sectionWithButtonAccessory btn txt = SlackBlockSection txt (Just $ SlackButtonAccessory btn)
+sectionWithButtonAccessory btn txt =
+  SlackBlockSection
+    $ (slackSectionWithText txt)
+      { slackSectionAccessory = Just $ SlackButtonAccessory btn
+      }
 
+-- | <https://api.slack.com/reference/block-kit/blocks#section>
+data SlackSection = SlackSection
+  { slackSectionText :: Maybe SlackText
+  -- ^ May be absent if 'slackSectionFields' is present.
+  , slackSectionBlockId :: Maybe SlackBlockId
+  , slackSectionFields :: Maybe [SlackText]
+  -- ^ Required if 'slackSectionText' is not provided.
+  , slackSectionAccessory :: Maybe SlackAccessory
+  }
+  deriving stock (Eq, Show)
+
+slackSectionWithText :: SlackText -> SlackSection
+slackSectionWithText t =
+  SlackSection
+    { slackSectionText = Just t
+    , slackSectionBlockId = Nothing
+    , slackSectionFields = Nothing
+    , slackSectionAccessory = Nothing
+    }
+
 data SlackBlock
-  = SlackBlockSection SlackText (Maybe SlackAccessory)
+  = SlackBlockSection SlackSection
   | SlackBlockImage SlackImage
   | SlackBlockContext SlackContext
   | SlackBlockDivider
@@ -374,15 +405,13 @@
   deriving stock (Eq)
 
 instance Show SlackBlock where
-  show (SlackBlockSection t Nothing) = show t
-  show (SlackBlockSection t (Just mAccessory)) =
-    show $ mconcat [show t, " [", show mAccessory, "]"]
+  show (SlackBlockSection section) = show section
   show (SlackBlockImage i) = show i
   show (SlackBlockContext contents) = show contents
   show SlackBlockDivider = "|"
   show (SlackBlockActions mBlockId as) =
-    show $
-      mconcat
+    show
+      $ mconcat
         [ "actions("
         , show mBlockId
         , ") = ["
@@ -393,11 +422,13 @@
   show (SlackBlockHeader p) = show p
 
 instance ToJSON SlackBlock where
-  toJSON (SlackBlockSection slackText mSectionAccessory) =
+  toJSON (SlackBlockSection SlackSection {..}) =
     objectOptional
       [ "type" .=! ("section" :: Text)
-      , "text" .=! SlackContentText slackText
-      , "accessory" .=? mSectionAccessory
+      , "text" .=? (SlackContentText <$> slackSectionText)
+      , "block_id" .=? slackSectionBlockId
+      , "fields" .=? (map SlackContentText <$> slackSectionFields)
+      , "accessory" .=? slackSectionAccessory
       ]
   toJSON (SlackBlockImage i) = toJSON (SlackContentImage i)
   toJSON (SlackBlockContext contents) =
@@ -429,13 +460,24 @@
     (slackBlockType :: Text) <- obj .: "type"
     case slackBlockType of
       "section" -> do
-        (sectionContentObj :: Value) <- obj .: "text"
-        SlackContentText sectionContentText <- parseJSON sectionContentObj
-        mSectionAccessory <- obj .:? "accessory"
-        pure $ SlackBlockSection sectionContentText mSectionAccessory
+        slackSectionTextContent <- obj .:? "text"
+        let slackSectionText = slackSectionTextContent >>= slackContentToSlackText
+        slackSectionBlockId <- obj .:? "block_id"
+        slackSectionFieldsContent <- obj .:? "fields"
+        let slackSectionFields = slackSectionFieldsContent >>= traverse slackContentToSlackText
+        (slackSectionAccessoryValue :: Maybe Value) <- obj .:? "accessory"
+        -- The section accessory can be any block element but `SlackAcessory`
+        -- only implements button.
+        let slackSectionAccessory =
+              slackSectionAccessoryValue >>= \v ->
+                case fromJSON v of
+                  Error _ ->
+                    Nothing
+                  Success slackAccessory ->
+                    Just slackAccessory
+        pure $ SlackBlockSection SlackSection {..}
       "context" -> do
-        (contextElementsObj :: Value) <- obj .: "elements"
-        slackContent <- parseJSON contextElementsObj
+        slackContent <- obj .: "elements"
         pure $ SlackBlockContext slackContent
       "image" -> do
         SlackContentImage i <- parseJSON $ Object obj
@@ -448,8 +490,9 @@
       "rich_text" -> do
         elements <- obj .: "elements"
         mBlockId <- obj .:? "block_id"
-        pure . SlackBlockRichText $
-          RichText
+        pure
+          . SlackBlockRichText
+          $ RichText
             { blockId = mBlockId
             , elements
             }
@@ -481,7 +524,7 @@
   markdown :: SlackText -> a
 
 instance Markdown SlackMessage where
-  markdown t = SlackMessage [SlackBlockSection t Nothing]
+  markdown t = SlackMessage [SlackBlockSection (slackSectionWithText t)]
 
 instance Markdown SlackContext where
   markdown t = SlackContext [SlackContentText t]
@@ -502,11 +545,11 @@
 textToContext = context . markdown . message
 
 -- | Generates interactive components such as buttons.
-actions :: ToSlackActionList as => as -> SlackMessage
+actions :: (ToSlackActionList as) => as -> SlackMessage
 actions as = SlackMessage [SlackBlockActions Nothing $ toSlackActionList as]
 
 -- | Generates interactive components such as buttons with a 'SlackBlockId'.
-actionsWithBlockId :: ToSlackActionList as => SlackBlockId -> as -> SlackMessage
+actionsWithBlockId :: (ToSlackActionList as) => SlackBlockId -> as -> SlackMessage
 actionsWithBlockId slackBlockId as = SlackMessage [SlackBlockActions (Just slackBlockId) $ toSlackActionList as]
 
 -- | Settings for [button elements](https://api.slack.com/reference/block-kit/block-elements#button).
@@ -536,8 +579,8 @@
 -- | Button builder.
 button :: SlackActionId -> SlackButtonText -> ButtonSettings -> SlackAction
 button actionId buttonText ButtonSettings {..} =
-  SlackAction actionId $
-    SlackButton
+  SlackAction actionId
+    $ SlackButton
       { slackButtonText = buttonText
       , slackButtonUrl = unOptionalSetting buttonUrl
       , slackButtonValue = unOptionalSetting buttonValue
@@ -545,6 +588,13 @@
       , slackButtonConfirm = unOptionalSetting buttonConfirm
       }
 
+-- | A divider block.
+-- https://api.slack.com/reference/block-kit/blocks#divider
+--
+-- @since 1.6.2.0
+divider :: SlackMessage
+divider = SlackMessage [SlackBlockDivider]
+
 -- | Settings for [confirmation dialog objects](https://api.slack.com/reference/block-kit/composition-objects#confirm).
 data ConfirmSettings = ConfirmSettings
   { confirmTitle :: Text
@@ -603,7 +653,7 @@
   , slackConfirmDeny :: SlackPlainTextOnly -- max length 30
   , slackConfirmStyle :: Maybe SlackStyle
   }
-  deriving stock (Eq)
+  deriving stock (Eq, Show)
 
 instance ToJSON SlackConfirmObject where
   toJSON SlackConfirmObject {..} =
diff --git a/src/Web/Slack/Experimental/Events/Types.hs b/src/Web/Slack/Experimental/Events/Types.hs
--- a/src/Web/Slack/Experimental/Events/Types.hs
+++ b/src/Web/Slack/Experimental/Events/Types.hs
@@ -1,4 +1,7 @@
+{-# LANGUAGE DeriveGeneric #-}
 {-# LANGUAGE DuplicateRecordFields #-}
+{-# LANGUAGE NamedFieldPuns #-}
+{-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE TemplateHaskell #-}
 
 -- FIXME(jadel): Use NoFieldSelectors when we drop everything before 9.2.
@@ -8,6 +11,8 @@
 
 import Data.Aeson
 import Data.Aeson.TH
+import Data.Aeson.Types (Parser)
+import Data.Scientific qualified as Sci
 import Data.Time.Clock.System (SystemTime)
 import Web.Slack.AesonUtils
 import Web.Slack.Experimental.Blocks (SlackBlock)
@@ -22,6 +27,123 @@
 
 $(deriveJSON snakeCaseOptions ''ChannelType)
 
+-- | <https://api.slack.com/events/message/message_attachment>
+-- Ported from https://github.com/slackapi/node-slack-sdk/blob/fc87d51/packages/types/src/message-attachments.ts
+--
+-- @since 2.0.0.3
+data AttachmentField = AttachmentField
+  { title :: Text
+  , value :: Text
+  , short :: Maybe Bool
+  }
+  deriving stock (Show)
+
+$(deriveFromJSON snakeCaseOptions ''AttachmentField)
+
+-- | @since 2.0.0.3
+data AttachmentMessageBlockMessage = AttachmentMessageBlockMessage
+  { blocks :: [SlackBlock]
+  }
+  deriving stock (Show)
+
+$(deriveFromJSON snakeCaseOptions ''AttachmentMessageBlockMessage)
+
+-- | @since 2.0.0.3
+data AttachmentMessageBlock = AttachmentMessageBlock
+  { team :: TeamId
+  , channel :: ConversationId
+  , ts :: Text
+  , message :: AttachmentMessageBlockMessage
+  }
+  deriving stock (Show)
+
+$(deriveFromJSON snakeCaseOptions ''AttachmentMessageBlock)
+
+-- | <https://api.slack.com/events/message/message_attachment>
+-- Ported from https://github.com/slackapi/node-slack-sdk/blob/fc87d51/packages/types/src/message-attachments.ts
+--
+-- @since 2.0.0.3
+data DecodedMessageAttachment = DecodedMessageAttachment
+  { fallback :: Maybe Text
+  , color :: Maybe Text
+  , pretext :: Maybe Text
+  , authorName :: Maybe Text
+  , authorLink :: Maybe Text
+  , authorIcon :: Maybe Text
+  , title :: Maybe Text
+  , titleLink :: Maybe Text
+  , text :: Maybe Text
+  , fields :: Maybe [AttachmentField]
+  , imageUrl :: Maybe Text
+  , thumbUrl :: Maybe Text
+  , footer :: Maybe Text
+  , footerIcon :: Maybe Text
+  , ts :: Maybe Text
+  , -- the following are undocumented
+    isMsgUnfurl :: Maybe Bool
+  , messageBlocks :: Maybe [AttachmentMessageBlock]
+  -- ^ unfurled message blocks
+  , authorId :: Maybe UserId
+  , channelId :: Maybe ConversationId
+  , channelTeam :: Maybe TeamId
+  , isAppUnfurl :: Maybe Bool
+  , appUnfurlUrl :: Maybe Text
+  , fromUrl :: Maybe Text
+  }
+  deriving stock (Show)
+
+instance FromJSON DecodedMessageAttachment where
+  parseJSON = withObject "DecodedMessageAttachment" $ \v -> do
+    fallback <- v .:? "fallback"
+    color <- v .:? "color"
+    pretext <- v .:? "pretext"
+    authorName <- v .:? "author_name"
+    authorLink <- v .:? "author_link"
+    authorIcon <- v .:? "author_icon"
+    title <- v .:? "title"
+    titleLink <- v .:? "title_link"
+    text <- v .:? "text"
+    fields <- v .:? "fields"
+    imageUrl <- v .:? "image_url"
+    thumbUrl <- v .:? "thumb_url"
+    footer <- v .:? "footer"
+    footerIcon <- v .:? "footer_icon"
+    ts <- v .:? "ts" >>= maybe (return Nothing) parseTs
+    isMsgUnfurl <- v .:? "is_msg_unfurl"
+    messageBlocks <- v .:? "message_blocks"
+    authorId <- v .:? "author_id"
+    channelId <- v .:? "channel_id"
+    channelTeam <- v .:? "channel_team"
+    isAppUnfurl <- v .:? "is_app_unfurl"
+    appUnfurlUrl <- v .:? "app_unfurl_url"
+    fromUrl <- v .:? "from_url"
+    pure DecodedMessageAttachment {..}
+    where
+      parseTs :: Value -> Parser (Maybe Text)
+      parseTs (String s) = pure $ Just s
+      parseTs (Number n) =
+        let s = Sci.formatScientific Sci.Fixed Nothing n
+            formatted = if '.' `elem` s then s else s ++ ".000000"
+         in pure $ Just (pack formatted)
+      parseTs _ = pure Nothing
+
+data MessageAttachment = MessageAttachment
+  { decoded :: Maybe DecodedMessageAttachment
+  -- ^ If the attachment can be decoded, this will be populated
+  , raw :: Value
+  -- ^ Slack does not document the attachment schema/spec very well and we can't
+  -- decode many attachments. In these cases clients can work with the raw JSON.
+  }
+  deriving stock (Show)
+
+instance FromJSON MessageAttachment where
+  parseJSON = withObject "MessageAttachment" $ \v -> do
+    let ov = Object v
+    -- Attempt to parse the entire object as DecodedMessageAttachment
+    decodedContent <- optional $ parseJSON ov
+    -- Return the structured data with raw JSON preserved
+    pure MessageAttachment {decoded = decodedContent, raw = ov}
+
 -- | <https://api.slack.com/events/message>
 -- and
 -- <https://api.slack.com/events/message/file_share>
@@ -48,11 +170,40 @@
   --   See @botMessage.json@ golden parser test.
   , botId :: Maybe Text
   -- ^ Present if it's sent by a bot user
+  , attachments :: Maybe [MessageAttachment]
+  -- ^ @since 2.0.0.3
+  -- Present if the message has attachments
   }
   deriving stock (Show)
 
 $(deriveFromJSON snakeCaseOptions ''MessageEvent)
 
+-- | <https://api.slack.com/events/message/bot_message>
+-- This is similar to a MessageEvent but sent by a bot, for example
+-- messages that Reacji Channeler sends.
+--
+-- @since 2.0.0.2
+data BotMessageEvent = BotMessageEvent
+  { blocks :: Maybe [SlackBlock]
+  , channel :: ConversationId
+  , text :: Text
+  , channelType :: ChannelType
+  , files :: Maybe [FileObject]
+  , ts :: Text
+  , threadTs :: Maybe Text
+  -- ^ Present if the message is in a thread
+  , appId :: Maybe Text
+  -- ^ Some (or all) bots also have an App ID
+  , botId :: Text
+  -- ^ Always present for bot_message subtype
+  , attachments :: Maybe [MessageAttachment]
+  -- ^ @since 2.0.0.3
+  -- Present if the message has attachments
+  }
+  deriving stock (Show)
+
+$(deriveFromJSON snakeCaseOptions ''BotMessageEvent)
+
 -- | <https://api.slack.com/events/message/message_changed>
 --
 -- FIXME(jadel): implement. This is mega cursed! in the normal message event
@@ -124,6 +275,7 @@
 
 data Event
   = EventMessage MessageEvent
+  | EventBotMessage BotMessageEvent
   | EventMessageChanged
   | -- | Weird message event of subtype channel_join. Sent "sometimes", according
     -- to a random Slack blog post from 2017:
@@ -142,6 +294,7 @@
     subtype :: Maybe Text <- obj .:? "subtype"
     case (tag, subtype) of
       ("message", Nothing) -> EventMessage <$> parseJSON @MessageEvent (Object obj)
+      ("message", Just "bot_message") -> EventBotMessage <$> parseJSON @BotMessageEvent (Object obj)
       ("message", Just "message_changed") -> pure EventMessageChanged
       ("message", Just "channel_join") -> pure EventChannelJoinMessage
       -- n.b. these are unified since it is *identical* to a Message event with
diff --git a/src/Web/Slack/Experimental/RequestVerification.hs b/src/Web/Slack/Experimental/RequestVerification.hs
--- a/src/Web/Slack/Experimental/RequestVerification.hs
+++ b/src/Web/Slack/Experimental/RequestVerification.hs
@@ -1,12 +1,11 @@
-module Web.Slack.Experimental.RequestVerification
-  ( SlackSigningSecret (..),
-    SlackSignature (..),
-    SlackRequestTimestamp (..),
-    SlackVerificationFailed (..),
-    validateRequest,
-    validateRequest',
-  )
-where
+module Web.Slack.Experimental.RequestVerification (
+  SlackSigningSecret (..),
+  SlackSignature (..),
+  SlackRequestTimestamp (..),
+  SlackVerificationFailed (..),
+  validateRequest,
+  validateRequest',
+) where
 
 import Crypto.Hash (SHA256, digestFromByteString)
 import Crypto.MAC.HMAC
@@ -70,7 +69,7 @@
 
 -- | Pure version of 'validateRequest'. Probably only useful for tests.
 validateRequest' ::
-  FromJSON a =>
+  (FromJSON a) =>
   NominalDiffTime ->
   SlackSigningSecret ->
   SlackSignature ->
@@ -81,21 +80,23 @@
   let fiveMinutes = 5 * 60
   -- timestamp must be an Int for proper basestring construction below
   timestamp <-
-    maybeToRight (VerificationMalformedTimestamp timestampString) $
-      fst <$> readInt timestampString
+    maybeToRight (VerificationMalformedTimestamp timestampString)
+      $ fst
+      <$> readInt timestampString
   if abs (now - fromIntegral timestamp) > fiveMinutes
     then Left $ VerificationTimestampOutOfRange timestamp
     else Right ()
   sigHeaderStripped <-
-    maybeToRight (VerificationUnknownSignatureVersion sigHeader) $
-      stripPrefix "v0=" sigHeader
+    maybeToRight (VerificationUnknownSignatureVersion sigHeader)
+      $ stripPrefix "v0=" sigHeader
   sigDecoded <-
-    mapLeft VerificationMalformedSignature $
-      B16.decode sigHeaderStripped
+    mapLeft VerificationMalformedSignature
+      $ B16.decode sigHeaderStripped
   sig :: HMAC SHA256 <-
-    maybeToRight (VerificationUndecodableSignature sigDecoded) $
-      HMAC <$> digestFromByteString sigDecoded
+    maybeToRight (VerificationUndecodableSignature sigDecoded)
+      $ HMAC
+      <$> digestFromByteString sigDecoded
   let basestring = encodeUtf8 ("v0:" <> tshow timestamp <> ":") <> body
-  when (hmac secret basestring /= sig) $
-    Left VerificationSignatureMismatch
+  when (hmac secret basestring /= sig)
+    $ Left VerificationSignatureMismatch
   mapLeft (VerificationCannotParse . pack) $ eitherDecodeStrict body
diff --git a/src/Web/Slack/Internal.hs b/src/Web/Slack/Internal.hs
--- a/src/Web/Slack/Internal.hs
+++ b/src/Web/Slack/Internal.hs
@@ -27,7 +27,7 @@
 -- Internal type!
 newtype ResponseJSON a = ResponseJSON (Either ResponseSlackError a)
 
-instance FromJSON a => FromJSON (ResponseJSON a) where
+instance (FromJSON a) => FromJSON (ResponseJSON a) where
   parseJSON = withObject "Response" $ \o -> do
     ok <- o .: "ok"
     ResponseJSON
diff --git a/src/Web/Slack/MessageParser.hs b/src/Web/Slack/MessageParser.hs
--- a/src/Web/Slack/MessageParser.hs
+++ b/src/Web/Slack/MessageParser.hs
@@ -4,12 +4,11 @@
 {-# LANGUAGE RecordWildCards #-}
 
 -- | See https://api.slack.com/docs/message-formatting
-module Web.Slack.MessageParser
-  ( messageToHtml,
-    HtmlRenderers (..),
-    defaultHtmlRenderers,
-  )
-where
+module Web.Slack.MessageParser (
+  messageToHtml,
+  HtmlRenderers (..),
+  defaultHtmlRenderers,
+) where
 
 -- FIXME: Web.Slack.Prelude
 
diff --git a/src/Web/Slack/Pager.hs b/src/Web/Slack/Pager.hs
--- a/src/Web/Slack/Pager.hs
+++ b/src/Web/Slack/Pager.hs
@@ -1,11 +1,10 @@
-module Web.Slack.Pager
-  ( Response,
-    LoadPage,
-    loadingPage,
-    fetchAllBy,
-    module Web.Slack.Pager.Types,
-  )
-where
+module Web.Slack.Pager (
+  Response,
+  LoadPage,
+  loadingPage,
+  fetchAllBy,
+  module Web.Slack.Pager.Types,
+) where
 
 import Web.Slack.Common qualified as Common
 import Web.Slack.Conversation qualified as Conversation
diff --git a/src/Web/Slack/Prelude.hs b/src/Web/Slack/Prelude.hs
--- a/src/Web/Slack/Prelude.hs
+++ b/src/Web/Slack/Prelude.hs
@@ -1,14 +1,13 @@
-module Web.Slack.Prelude
-  ( module ClassyPrelude,
-    module Data.Aeson,
-    module Data.Aeson.TH,
-    cs,
-    ToHttpApiData,
-    NonEmpty (..),
-    Default (..),
-    Proxy (..),
-  )
-where
+module Web.Slack.Prelude (
+  module ClassyPrelude,
+  module Data.Aeson,
+  module Data.Aeson.TH,
+  cs,
+  ToHttpApiData,
+  NonEmpty (..),
+  Default (..),
+  Proxy (..),
+) where
 
 import ClassyPrelude hiding (link)
 import Data.Aeson (FromJSON (..), ToJSON (..), object, withObject, (.:), (.:?), (.=))
diff --git a/src/Web/Slack/Types.hs b/src/Web/Slack/Types.hs
--- a/src/Web/Slack/Types.hs
+++ b/src/Web/Slack/Types.hs
@@ -5,18 +5,17 @@
 -- |
 -- Module: Web.Slack.Types
 -- Description:
-module Web.Slack.Types
-  ( Color (..),
-    UserId (..),
-    ConversationId (..),
-    TeamId (..),
-    Cursor (..),
-    SlackTimestamp (..),
-    mkSlackTimestamp,
-    timestampFromText,
-    SlackMessageText (..),
-  )
-where
+module Web.Slack.Types (
+  Color (..),
+  UserId (..),
+  ConversationId (..),
+  TeamId (..),
+  Cursor (..),
+  SlackTimestamp (..),
+  mkSlackTimestamp,
+  timestampFromText,
+  SlackMessageText (..),
+) where
 
 import Control.Monad (MonadFail (..))
 import Data.Aeson
@@ -87,9 +86,9 @@
 
 instance FromJSON SlackTimestamp where
   parseJSON =
-    withText "Slack ts" $
-      either (fail . ("Invalid Slack ts: " ++)) pure
-        . timestampFromText
+    withText "Slack ts"
+      $ either (fail . ("Invalid Slack ts: " ++)) pure
+      . timestampFromText
 
 instance ToJSON SlackTimestamp where
   toJSON = String . slackTimestampTs
diff --git a/src/Web/Slack/User.hs b/src/Web/Slack/User.hs
--- a/src/Web/Slack/User.hs
+++ b/src/Web/Slack/User.hs
@@ -4,15 +4,14 @@
 {-# LANGUAGE TemplateHaskell #-}
 
 -- | @users.*@ methods in the Slack API
-module Web.Slack.User
-  ( Profile (..),
-    User (..),
-    ListReq (..),
-    ListRsp (..),
-    Email (..),
-    UserRsp (..),
-  )
-where
+module Web.Slack.User (
+  Profile (..),
+  User (..),
+  ListReq (..),
+  ListRsp (..),
+  Email (..),
+  UserRsp (..),
+) where
 
 import Data.Time.Clock.POSIX
 import Web.FormUrlEncoded
diff --git a/src/Web/Slack/UsersConversations.hs b/src/Web/Slack/UsersConversations.hs
--- a/src/Web/Slack/UsersConversations.hs
+++ b/src/Web/Slack/UsersConversations.hs
@@ -3,13 +3,12 @@
 
 -- | Client for Slack's @users.conversations@ endpoint.
 -- <https://api.slack.com/methods/users.conversations>
-module Web.Slack.UsersConversations
-  ( UsersConversationsRequest (..),
-    UsersConversationsResponse (..),
-    usersConversations,
-    usersConversationsAll,
-  )
-where
+module Web.Slack.UsersConversations (
+  UsersConversationsRequest (..),
+  UsersConversationsResponse (..),
+  usersConversations,
+  usersConversationsAll,
+) where
 
 import Servant.API
 import Servant.Client hiding (Response)
diff --git a/src/Web/Slack/Util.hs b/src/Web/Slack/Util.hs
--- a/src/Web/Slack/Util.hs
+++ b/src/Web/Slack/Util.hs
@@ -5,12 +5,11 @@
 -- |
 -- Module: Web.Slack.Util
 -- Description:
-module Web.Slack.Util
-  ( formOpts,
-    jsonOpts,
-    toQueryParamIfJust,
-  )
-where
+module Web.Slack.Util (
+  formOpts,
+  jsonOpts,
+  toQueryParamIfJust,
+) where
 
 -- FIXME: Web.Slack.Prelude
 
@@ -59,6 +58,6 @@
 addUnderscores =
   camelTo2 '_'
 
-toQueryParamIfJust :: ToHttpApiData a => Text -> Maybe a -> Form
+toQueryParamIfJust :: (ToHttpApiData a) => Text -> Maybe a -> Form
 toQueryParamIfJust key =
   fromList . maybeToList . fmap (\justVal -> (key, toQueryParam justVal))
diff --git a/tests/JSONGolden.hs b/tests/JSONGolden.hs
--- a/tests/JSONGolden.hs
+++ b/tests/JSONGolden.hs
@@ -20,7 +20,7 @@
 filename :: Text -> Text -> FilePath
 filename tycon name = $(LitE . StringL <$> makeRelativeToProject "tests/golden") </> unpack tycon </> unpack name
 
-typeName :: forall a. Typeable a => Text
+typeName :: forall a. (Typeable a) => Text
 typeName = pack . tyConName . typeRepTyCon $ typeRep @a
 
 goldenTestDecode :: forall a. (FromJSON a, Show a, Typeable a) => Text -> LByteString -> Golden Text
diff --git a/tests/TestImport.hs b/tests/TestImport.hs
--- a/tests/TestImport.hs
+++ b/tests/TestImport.hs
@@ -1,15 +1,14 @@
-module TestImport
-  ( fromJust,
-    module Control.Monad.Fail,
-    module Test.Hspec,
-    module Test.Hspec.QuickCheck,
-    module ClassyPrelude,
-    module Data.Aeson,
-    module Data.Aeson.TH,
-    cs,
-    module Test.QuickCheck,
-  )
-where
+module TestImport (
+  fromJust,
+  module Control.Monad.Fail,
+  module Test.Hspec,
+  module Test.Hspec.QuickCheck,
+  module ClassyPrelude,
+  module Data.Aeson,
+  module Data.Aeson.TH,
+  cs,
+  module Test.QuickCheck,
+) where
 
 import ClassyPrelude hiding (link)
 import Control.Monad.Fail
diff --git a/tests/TestImport/Aeson.hs b/tests/TestImport/Aeson.hs
--- a/tests/TestImport/Aeson.hs
+++ b/tests/TestImport/Aeson.hs
@@ -9,6 +9,8 @@
       parsed = A.parse (parseJSON @a) encoded
       roundTwo = fmap (toJSON @a) parsed
    in -- The encoding is the same
-      A.Success encoded == roundTwo
+      A.Success encoded
+        == roundTwo
         -- AND the object itself is the same
-        && A.Success a == parsed
+        && A.Success a
+        == parsed
diff --git a/tests/Web/Slack/ConversationSpec.hs b/tests/Web/Slack/ConversationSpec.hs
--- a/tests/Web/Slack/ConversationSpec.hs
+++ b/tests/Web/Slack/ConversationSpec.hs
@@ -3,10 +3,9 @@
 {-# LANGUAGE StandaloneDeriving #-}
 {-# OPTIONS_GHC -fno-warn-orphans #-}
 
-module Web.Slack.ConversationSpec
-  ( spec,
-  )
-where
+module Web.Slack.ConversationSpec (
+  spec,
+) where
 
 -- aeson
 import Data.Aeson
diff --git a/tests/Web/Slack/Experimental/Blocks/TypesSpec.hs b/tests/Web/Slack/Experimental/Blocks/TypesSpec.hs
new file mode 100644
--- /dev/null
+++ b/tests/Web/Slack/Experimental/Blocks/TypesSpec.hs
@@ -0,0 +1,162 @@
+module Web.Slack.Experimental.Blocks.TypesSpec where
+
+import Data.Aeson qualified as Aeson
+import Data.StringVariants.NonEmptyText.Internal (pattern NonEmptyText)
+import Refined.Unsafe (reallyUnsafeRefine)
+import TestImport
+import Web.Slack.Experimental.Blocks.Types
+
+jsonRoundtrips :: (Show a, Eq a, Aeson.ToJSON a, Aeson.FromJSON a) => a -> Spec
+jsonRoundtrips a = do
+  it "can decode its own json encoding" do
+    (Aeson.fromJSON . Aeson.toJSON) a `shouldBe` Aeson.Success a
+
+spec :: Spec
+spec = do
+  let
+    aSlackAccessory = SlackButtonAccessory aSlackAction
+    aSlackAction = SlackAction
+      do SlackActionId $ NonEmptyText "action-id"
+      do aSlackButton
+    aSlackActionList =
+      SlackActionList
+        . reallyUnsafeRefine
+        $ [ aSlackAction
+          , SlackAction
+              do SlackActionId $ NonEmptyText "another-action-id"
+              do
+                SlackButton
+                  do SlackButtonText $ NonEmptyText "another-button-text"
+                  do Nothing
+                  do Nothing
+                  do Nothing
+                  do Nothing
+          ]
+    aSlackBlockSection = SlackBlockSection aSlackSection
+    aSlackBlockImage = SlackBlockImage aSlackImage
+    aSlackBlockContext = SlackBlockContext aSlackContext
+    aSlackBlockActions = SlackBlockActions
+      do Just $ NonEmptyText "block-actions"
+      do aSlackActionList
+    aSlackBlockHeader = SlackBlockHeader $ SlackPlainTextOnly "block-header"
+    aSlackButton =
+      SlackButton
+        { slackButtonText = SlackButtonText (NonEmptyText "button-text")
+        , slackButtonUrl = Just (NonEmptyText "button-url")
+        , slackButtonValue = Just (NonEmptyText "button-value")
+        , slackButtonStyle = Just SlackStylePrimary
+        , slackButtonConfirm = Just aSlackConfirmObject
+        }
+    aSlackConfirmObject =
+      SlackConfirmObject
+        { slackConfirmTitle = SlackPlainTextOnly "button-confirm-title"
+        , slackConfirmText = SlackPlainText "button-confirm-text"
+        , slackConfirmConfirm = SlackPlainTextOnly "button-confirm-confirm"
+        , slackConfirmDeny = SlackPlainTextOnly "button-confirm-deny"
+        , slackConfirmStyle = Just SlackStyleDanger
+        }
+    aSlackContentText = SlackContentText "content-text"
+    aSlackContentImage = SlackContentImage aSlackImage
+    aSlackContext = SlackContext [aSlackContentText, aSlackContentImage]
+    aSlackImage =
+      SlackImage
+        { slackImageTitle = Just "image-title"
+        , slackImageAltText = "image-alt-text"
+        , slackImageUrl = "image-url"
+        }
+    aSlackMessage =
+      SlackMessage
+        [ aSlackBlockSection
+        , aSlackBlockImage
+        , aSlackBlockContext
+        , aSlackBlockActions
+        , aSlackBlockHeader
+        -- not tested: SlackBlockRichText
+        ]
+    aSlackPlainTextOnly = SlackPlainTextOnly "plain-text-only"
+    aSlackPlainText = SlackPlainText "plain-text"
+    aSlackMarkdownText = SlackMarkdownText "markdown-text"
+    aSlackSection =
+      SlackSection
+        { slackSectionText = Just "section-text"
+        , slackSectionBlockId = Just (NonEmptyText "section-block-id")
+        , slackSectionFields = Just ["field-0", "field-1", "field-2"]
+        , slackSectionAccessory = Just aSlackAccessory
+        }
+
+  describe "SlackAccessory" do
+    jsonRoundtrips aSlackAccessory
+
+  describe "SlackAction" do
+    jsonRoundtrips aSlackAction
+
+  describe "SlackBlock" do
+    describe "SlackBlockSection" do
+      jsonRoundtrips aSlackBlockSection
+
+    describe "SlackBlockImage" do
+      jsonRoundtrips aSlackBlockImage
+
+    describe "SlackBlockContext" do
+      jsonRoundtrips aSlackBlockContext
+
+    describe "SlackBlockDivider" do
+      jsonRoundtrips SlackBlockDivider
+
+    -- SlackBlock's ToJSON instance is lossy; SlackBlockRichText values get
+    -- encoded as '{}'
+    --
+    -- describe "SlackBlockRichText" do
+    --   jsonRoundtrips aSlackBlockRichText
+
+    describe "SlackBlockActions" do
+      jsonRoundtrips aSlackBlockActions
+
+    describe "SlackBlockHeader" do
+      jsonRoundtrips aSlackBlockHeader
+
+  describe "SlackConfirmObject" do
+    jsonRoundtrips aSlackConfirmObject
+
+  describe "SlackContent" do
+    describe "SlackContentText" do
+      jsonRoundtrips aSlackContentText
+
+    describe "SlackContentImage" do
+      jsonRoundtrips aSlackContentImage
+
+  describe "SlackContext" do
+    jsonRoundtrips aSlackContext
+
+  describe "SlackMessage" do
+    jsonRoundtrips aSlackMessage
+
+  describe "SlackPlainTextOnly" do
+    jsonRoundtrips aSlackPlainTextOnly
+
+  describe "SlackTextObject" do
+    describe "SlackPlainText" do
+      jsonRoundtrips aSlackPlainText
+
+    describe "SlackMarkdownText" do
+      jsonRoundtrips aSlackMarkdownText
+
+-- Untestable for roundtripping:
+--
+--  FromJSON only
+--    - RichItem
+--    - RichStyle
+--    - RichText
+--    - RichTextSectionItem
+--    - SlackActionComponent
+--    - SlackActionResponse
+--    - SlackInteractivePayload
+--    - SlackInteractiveResponseResponse
+--
+--  ToJSON only
+--    - SlackInteractiveResponse
+--    - SlackText
+--
+--  Note also that SlackBlock's encoding is lossy, encoding
+--  SlackBlockRichText as '{}', so that case is not tested
+--  for round-tripping
diff --git a/tests/Web/Slack/Experimental/BlocksSpec.hs b/tests/Web/Slack/Experimental/BlocksSpec.hs
--- a/tests/Web/Slack/Experimental/BlocksSpec.hs
+++ b/tests/Web/Slack/Experimental/BlocksSpec.hs
@@ -14,13 +14,34 @@
 headerBlock = tell . pure . SlackBlockHeader . SlackPlainTextOnly
 
 sectionBlock :: SlackText -> WriterT [SlackBlock] Identity ()
-sectionBlock text = tell . pure $ SlackBlockSection text Nothing
+sectionBlock = tell . pure . SlackBlockSection . slackSectionWithText
 
+sectionBlockWithFields :: SlackText -> [SlackText] -> WriterT [SlackBlock] Identity ()
+sectionBlockWithFields text fields =
+  tell
+    $ pure
+    $ SlackBlockSection
+    $ SlackSection
+      { slackSectionText = Just text
+      , slackSectionBlockId = Nothing
+      , slackSectionFields = Just fields
+      , slackSectionAccessory = Nothing
+      }
+
 sectionBlockWithAccessory ::
   SlackText ->
   SlackAction ->
   WriterT [SlackBlock] Identity ()
-sectionBlockWithAccessory a b = tell . pure $ SlackBlockSection a (Just . SlackButtonAccessory $ b)
+sectionBlockWithAccessory t b =
+  tell
+    $ pure
+    $ SlackBlockSection
+      SlackSection
+        { slackSectionText = Just t
+        , slackSectionBlockId = Nothing
+        , slackSectionFields = Nothing
+        , slackSectionAccessory = Just $ SlackButtonAccessory b
+        }
 
 dividerBlock :: WriterT [SlackBlock] Identity ()
 dividerBlock = tell . pure $ SlackBlockDivider
@@ -45,8 +66,9 @@
 
 slackShowBlockFormat :: BlockKitBuilderMessage
 slackShowBlockFormat =
-  BlockKitBuilderMessage $
-    execWriter $ do
+  BlockKitBuilderMessage
+    $ execWriter
+    $ do
       headerBlock ("Blah: " <> list ["a", "b", "c"])
       dividerBlock
       sectionBlock (bold $ list ["blah", "blah2", "blah3"])
@@ -63,10 +85,17 @@
       sectionBlockWithAccessory
         (bold . textMessage $ "blah")
         (button slackActionDoNothing ":bank: Look at it!" buttonSettings {buttonUrl = google})
+      sectionBlockWithFields
+        (message @Text "Section with text and fields")
+        [ (bold $ message @Text "Field 1") <> (newline $ message @Text "Foo")
+        , (bold $ message @Text "Field 2") <> (newline $ message @Text "Bar")
+        , (bold $ message @Text "Field 3") <> (newline $ message @Text "Baz")
+        , (bold $ message @Text "Field 4") <> (newline $ message @Text "Qux")
+        ]
       contextBlock [SlackContentText ":key: Context!"]
       dividerBlock
-      actionsBlock Nothing $
-        toSlackActionList
+      actionsBlock Nothing
+        $ toSlackActionList
           ( button slackActionDoNothing ":mag: View" buttonSettings {buttonUrl = google}
           , button slackActionDoNothing2 ":office: View" buttonSettings {buttonUrl = google}
           , button slackActionDoNothing3 ":bank: View" buttonSettings {buttonUrl = google}
diff --git a/tests/Web/Slack/Experimental/Events/TypesSpec.hs b/tests/Web/Slack/Experimental/Events/TypesSpec.hs
--- a/tests/Web/Slack/Experimental/Events/TypesSpec.hs
+++ b/tests/Web/Slack/Experimental/Events/TypesSpec.hs
@@ -23,6 +23,14 @@
         , "slackbotIm"
         , "channel_left"
         , "share_without_message"
+        , "share_with_message"
+        , "circleci"
         , -- https://slack.com/help/articles/206819278-Send-emails-to-Slack
           "email_message"
+        , "message_subtype_bot_message"
+        , "forwarded_message"
+        , "github_notification"
+        , "github_notification_ts_string"
+        , "github_with_link"
+        , "non_spec_attachment"
         ]
diff --git a/tests/Web/Slack/MessageParserSpec.hs b/tests/Web/Slack/MessageParserSpec.hs
--- a/tests/Web/Slack/MessageParserSpec.hs
+++ b/tests/Web/Slack/MessageParserSpec.hs
@@ -20,36 +20,46 @@
 spec :: Spec
 spec =
   describe "message contents parsing" $ do
-    it "handles the trivial case well" $
-      msgToHtml "hello" `shouldBe` "hello"
-    it "converts a simple message to HTML correctly" $
-      msgToHtml "_hello_ *world* <http://www.google.com|google> `code` ```longer\ncode```"
-        `shouldBe` "<i>hello</i> <b>world</b> <a href='http://www.google.com'>google</a> <code>code</code> <pre>longer\ncode</pre>"
-    it "degrades properly to return the input message if it's incorrect" $
-      msgToHtml "link not closed <bad"
-        `shouldBe` "link not closed <bad"
-    it "creates italics sections only at word boundaries" $
-      msgToHtml "false_positive" `shouldBe` "false_positive"
-    it "handles bold, strikethrough & italics simultaneously" $
-      msgToHtml "*_~both~_*" `shouldBe` "<b><i><strike>both</strike></i></b>"
-    it "aborts nicely on interspersed bold & italics" $
-      msgToHtml "inter *sper_ *sed_" `shouldBe` "inter *sper_ *sed_"
-    it "parses blockquotes properly" $
-      msgToHtml "look at this:\n&gt; test *wow*" `shouldBe` "look at this:<br/><blockquote>test <b>wow</b></blockquote>"
-    it "parses code blocks properly" $
-      msgToHtml "look at this:\n```test *wow*```" `shouldBe` "look at this:<br/><pre>test *wow*</pre>"
-    it "handles non-italics underscores in text well" $
+    it "handles the trivial case well"
+      $ msgToHtml "hello"
+      `shouldBe` "hello"
+    it "converts a simple message to HTML correctly"
+      $ msgToHtml "_hello_ *world* <http://www.google.com|google> `code` ```longer\ncode```"
+      `shouldBe` "<i>hello</i> <b>world</b> <a href='http://www.google.com'>google</a> <code>code</code> <pre>longer\ncode</pre>"
+    it "degrades properly to return the input message if it's incorrect"
+      $ msgToHtml "link not closed <bad"
+      `shouldBe` "link not closed <bad"
+    it "creates italics sections only at word boundaries"
+      $ msgToHtml "false_positive"
+      `shouldBe` "false_positive"
+    it "handles bold, strikethrough & italics simultaneously"
+      $ msgToHtml "*_~both~_*"
+      `shouldBe` "<b><i><strike>both</strike></i></b>"
+    it "aborts nicely on interspersed bold & italics"
+      $ msgToHtml "inter *sper_ *sed_"
+      `shouldBe` "inter *sper_ *sed_"
+    it "parses blockquotes properly"
+      $ msgToHtml "look at this:\n&gt; test *wow*"
+      `shouldBe` "look at this:<br/><blockquote>test <b>wow</b></blockquote>"
+    it "parses code blocks properly"
+      $ msgToHtml "look at this:\n```test *wow*```"
+      `shouldBe` "look at this:<br/><pre>test *wow*</pre>"
+    it "handles non-italics underscores in text well"
+      $
       -- need to put other HTML symbols, otherwise if the parsing fails
       -- i won't find out since we default to returning the input on
       -- parsing failure
-      msgToHtml "a:\n&gt;b.\n:slightly_smiling_face:" `shouldBe` "a:<br/><blockquote>b.</blockquote>:>slightly_smiling_face<:"
-    it "properly parses multiline blockquotes" $
-      msgToHtml "&gt; first row\n&gt; second row\nthird row\n&gt; fourth row"
-        `shouldBe` "<blockquote>first row<br/>second row</blockquote>third row<br/><blockquote>fourth row</blockquote>"
-    it "converts usernames" $
-      msgToHtml "<@USER1> should be converted, <@USER1|default> stay default"
-        `shouldBe` "@user_one should be converted, @default stay default"
-    it "converts carriage returns" $
-      msgToHtml "a\nb" `shouldBe` "a<br/>b"
-    it "handles full stops as punctuation" $
-      msgToHtml "*b*." `shouldBe` "<b>b</b>."
+      msgToHtml "a:\n&gt;b.\n:slightly_smiling_face:"
+      `shouldBe` "a:<br/><blockquote>b.</blockquote>:>slightly_smiling_face<:"
+    it "properly parses multiline blockquotes"
+      $ msgToHtml "&gt; first row\n&gt; second row\nthird row\n&gt; fourth row"
+      `shouldBe` "<blockquote>first row<br/>second row</blockquote>third row<br/><blockquote>fourth row</blockquote>"
+    it "converts usernames"
+      $ msgToHtml "<@USER1> should be converted, <@USER1|default> stay default"
+      `shouldBe` "@user_one should be converted, @default stay default"
+    it "converts carriage returns"
+      $ msgToHtml "a\nb"
+      `shouldBe` "a<br/>b"
+    it "handles full stops as punctuation"
+      $ msgToHtml "*b*."
+      `shouldBe` "<b>b</b>."
diff --git a/tests/Web/Slack/PagerSpec.hs b/tests/Web/Slack/PagerSpec.hs
--- a/tests/Web/Slack/PagerSpec.hs
+++ b/tests/Web/Slack/PagerSpec.hs
@@ -5,20 +5,20 @@
 import Data.Time.Clock (addUTCTime, nominalDay)
 import Test.Pull.Fake.IO (FakeStream, newFakeStream, pull)
 import TestImport
-import Web.Slack.Common
-  ( Message (..),
-    MessageType (..),
-    SlackMessageText (..),
-    mkSlackTimestamp,
-  )
-import Web.Slack.Conversation
-  ( ConversationId (ConversationId),
-    HistoryReq (..),
-    HistoryRsp (..),
-    RepliesReq (..),
-    mkHistoryReq,
-    mkRepliesReq,
-  )
+import Web.Slack.Common (
+  Message (..),
+  MessageType (..),
+  SlackMessageText (..),
+  mkSlackTimestamp,
+ )
+import Web.Slack.Conversation (
+  ConversationId (ConversationId),
+  HistoryReq (..),
+  HistoryRsp (..),
+  RepliesReq (..),
+  mkHistoryReq,
+  mkRepliesReq,
+ )
 import Web.Slack.Pager
 import Web.Slack.Types (UserId (..))
 
@@ -38,16 +38,17 @@
               -- The last page's cursor can be either an empty string, null, or non-exisitent in the object.
               (pageN, cursor) <- zip [1 .. 3] ["cursor1=", "cursor2=", ""]
               let pageNT = Text.pack (show pageN)
-              pure . Right $
-                HistoryRsp
+              pure
+                . Right
+                $ HistoryRsp
                   { historyRspMessages = do
                       messageN <- [1 .. messagesPerPage]
                       let messagesPerPageNDT = fromIntegral messagesPerPage
                           messageNDT = fromIntegral messageN
                           messageNT = Text.pack (show messageN)
                           createdBefore = negate $ nominalDay * ((pageN - 1) * messagesPerPageNDT + messageNDT)
-                      pure $
-                        Message
+                      pure
+                        $ Message
                           MessageTypeMessage
                           (Just . UserId $ "U" <> pageNT <> messageNT)
                           (SlackMessageText $ "message " <> pageNT <> "-" <> messageNT)
@@ -57,8 +58,9 @@
         responsesToReturn <- newFakeStream allResponses
         return (now, oldest, messagesPerPage, allResponses, responsesToReturn)
 
-  describe "conversationsHistoryAllBy" $
-    it "collect all results by sending requests" $ do
+  describe "conversationsHistoryAllBy"
+    $ it "collect all results by sending requests"
+    $ do
       (now, oldest, messagesPerPage, allResponses, responsesToReturn) <- prepare
       let initialRequest =
             (mkHistoryReq (ConversationId "C01234567"))
@@ -72,8 +74,9 @@
       expected <- fmap (map historyRspMessages) . either throwIO return $ sequenceA allResponses
       actual `shouldReturn` expected
 
-  describe "repliesFetchAllBy" $
-    it "collect all results by sending requests" $ do
+  describe "repliesFetchAllBy"
+    $ it "collect all results by sending requests"
+    $ do
       (now, oldest, messagesPerPage, allResponses, responsesToReturn) <- prepare
       let initialRequest =
             (mkRepliesReq (ConversationId "C98765432") oldest)
@@ -88,7 +91,7 @@
       actual `shouldReturn` expected
 
 -- | Runs the given action repeatedly until it returns an empty list.
-unfoldPageM :: Monad m => m [a] -> m [[a]]
+unfoldPageM :: (Monad m) => m [a] -> m [[a]]
 unfoldPageM act = reverse <$> go []
   where
     go accum = do
diff --git a/tests/golden/BlockKitBuilderMessage/simple_blocks.golden.json b/tests/golden/BlockKitBuilderMessage/simple_blocks.golden.json
--- a/tests/golden/BlockKitBuilderMessage/simple_blocks.golden.json
+++ b/tests/golden/BlockKitBuilderMessage/simple_blocks.golden.json
@@ -90,6 +90,31 @@
             "type": "section"
         },
         {
+            "fields": [
+                {
+                    "text": "*Field 1*\nFoo",
+                    "type": "mrkdwn"
+                },
+                {
+                    "text": "*Field 2*\nBar",
+                    "type": "mrkdwn"
+                },
+                {
+                    "text": "*Field 3*\nBaz",
+                    "type": "mrkdwn"
+                },
+                {
+                    "text": "*Field 4*\nQux",
+                    "type": "mrkdwn"
+                }
+            ],
+            "text": {
+                "text": "Section with text and fields",
+                "type": "mrkdwn"
+            },
+            "type": "section"
+        },
+        {
             "elements": [
                 {
                     "text": ":key: Context!",
diff --git a/tests/golden/SlackWebhookEvent/botMessage.golden b/tests/golden/SlackWebhookEvent/botMessage.golden
--- a/tests/golden/SlackWebhookEvent/botMessage.golden
+++ b/tests/golden/SlackWebhookEvent/botMessage.golden
@@ -37,6 +37,7 @@
                 , threadTs = Just "1664216109.798919"
                 , appId = Just "A0442TUPHGR"
                 , botId = Just "B0439P161B9"
+                , attachments = Nothing
                 }
             )
         }
diff --git a/tests/golden/SlackWebhookEvent/circleci.golden b/tests/golden/SlackWebhookEvent/circleci.golden
new file mode 100644
--- /dev/null
+++ b/tests/golden/SlackWebhookEvent/circleci.golden
@@ -0,0 +1,57 @@
+EventEventCallback
+    ( EventCallback
+        { eventId = EventId
+            { unEventId = "Ev0000000000" }
+        , teamId = TeamId
+            { unTeamId = "T0123456789" }
+        , eventTime = MkSystemTime
+            { systemSeconds = 1671046987
+            , systemNanoseconds = 0
+            }
+        , event = EventMessage
+            ( MessageEvent
+                { blocks = Just
+                    [ SlackPlainTextOnly "Job Failed. :red_circle:"
+                    , SlackSection
+                        { slackSectionText = Nothing
+                        , slackSectionBlockId = Just
+                            ( NonEmptyText "jO2E" )
+                        , slackSectionFields = Just [ "*Job*: something" ]
+                        , slackSectionAccessory = Nothing
+                        }
+                    , SlackSection
+                        { slackSectionText = Nothing
+                        , slackSectionBlockId = Just
+                            ( NonEmptyText "adB9" )
+                        , slackSectionFields = Just
+                            [ "*Project*: something"
+                            , "*Branch*: master"
+                            , "*Author*: someone"
+                            ]
+                        , slackSectionAccessory = Nothing
+                        }
+                    , SlackSection
+                        { slackSectionText = Nothing
+                        , slackSectionBlockId = Just
+                            ( NonEmptyText "=sdEQ" )
+                        , slackSectionFields = Just [ "*Mentions*: <!subteam^S0123468791|@someone>" ]
+                        , slackSectionAccessory = Nothing
+                        }
+                    , "actions(Just (NonEmptyText "eeK")) = ["SlackActionId {unSlackActionId = NonEmptyText \"zHNw\"} [button SlackButtonText (NonEmptyText \"View Job\")]"]"
+                    ]
+                , channel = ConversationId
+                    { unConversationId = "C012345678" }
+                , text = "CircleCI job failed."
+                , channelType = Channel
+                , files = Nothing
+                , user = UserId
+                    { unUserId = "U04130YGVK8" }
+                , ts = "1671046987.237089"
+                , threadTs = Nothing
+                , appId = Just "A56789123"
+                , botId = Just "B01234687"
+                , attachments = Nothing
+                }
+            )
+        }
+    )
diff --git a/tests/golden/SlackWebhookEvent/circleci.json b/tests/golden/SlackWebhookEvent/circleci.json
new file mode 100644
--- /dev/null
+++ b/tests/golden/SlackWebhookEvent/circleci.json
@@ -0,0 +1,119 @@
+{
+  "token": "aaaa",
+  "team_id": "T0123456789",
+  "api_app_id": "A12346789",
+  "event": {
+    "bot_id": "B01234687",
+    "type": "message",
+    "text": "CircleCI job failed.",
+    "user": "U04130YGVK8",
+    "ts": "1671046987.237089",
+    "app_id": "A56789123",
+    "blocks": [
+      {
+        "type": "header",
+        "block_id": "+6hb",
+        "text": {
+          "type": "plain_text",
+          "text": "Job Failed. :red_circle:",
+          "emoji": true
+        }
+      },
+      {
+        "type": "section",
+        "block_id": "jO2E",
+        "fields": [
+          {
+            "type": "mrkdwn",
+            "text": "*Job*: something",
+            "verbatim": false
+          }
+        ]
+      },
+      {
+        "type": "section",
+        "block_id": "adB9",
+        "accessory": {
+          "type": "image",
+          "image_url": "https://example.com",
+          "alt_text": "CircleCI logo"
+        },
+        "fields": [
+          {
+            "type": "mrkdwn",
+            "text": "*Project*: something",
+            "verbatim": false
+          },
+          {
+            "type": "mrkdwn",
+            "text": "*Branch*: master",
+            "verbatim": false
+          },
+          {
+            "type": "mrkdwn",
+            "text": "*Author*: someone",
+            "verbatim": false
+          }
+        ]
+      },
+      {
+        "type": "section",
+        "block_id": "=sdEQ",
+        "fields": [
+          {
+            "type": "mrkdwn",
+            "text": "*Mentions*: <!subteam^S0123468791|@someone>",
+            "verbatim": false
+          }
+        ]
+      },
+      {
+        "type": "actions",
+        "block_id": "eeK",
+        "elements": [
+          {
+            "type": "button",
+            "action_id": "zHNw",
+            "text": {
+              "type": "plain_text",
+              "text": "View Job",
+              "emoji": true
+            },
+            "url": "https://circleci.com/gh/aaaaaaaaaaaaaaaaaaa/aaaaaaaaaaa/000000"
+          }
+        ]
+      }
+    ],
+    "team": "T0123456789",
+    "bot_profile": {
+      "id": "B01234687",
+      "deleted": false,
+      "name": "CircleCI integration",
+      "updated": 1662492349,
+      "app_id": "A56789123",
+      "icons": {
+        "image_36": "https://example.com",
+        "image_48": "https://example.com",
+        "image_72": "https://example.com"
+      },
+      "team_id": "T0123456789"
+    },
+    "channel": "C012345678",
+    "event_ts": "1671046987.237089",
+    "channel_type": "channel"
+  },
+  "type": "event_callback",
+  "event_id": "Ev0000000000",
+  "event_time": 1671046987,
+  "authorizations": [
+    {
+      "enterprise_id": null,
+      "team_id": "T0123456789",
+      "user_id": "U01234678",
+      "is_bot": true,
+      "is_enterprise_install": false
+    }
+  ],
+  "is_ext_shared_channel": false,
+  "event_context": "aaaa"
+}
diff --git a/tests/golden/SlackWebhookEvent/email_message.golden b/tests/golden/SlackWebhookEvent/email_message.golden
--- a/tests/golden/SlackWebhookEvent/email_message.golden
+++ b/tests/golden/SlackWebhookEvent/email_message.golden
@@ -37,6 +37,7 @@
                 , threadTs = Nothing
                 , appId = Nothing
                 , botId = Just "B012346789"
+                , attachments = Nothing
                 }
             )
         }
diff --git a/tests/golden/SlackWebhookEvent/forwarded_message.golden b/tests/golden/SlackWebhookEvent/forwarded_message.golden
new file mode 100644
--- /dev/null
+++ b/tests/golden/SlackWebhookEvent/forwarded_message.golden
@@ -0,0 +1,238 @@
+EventEventCallback
+    ( EventCallback
+        { eventId = EventId
+            { unEventId = "Ev07KHG83J1F" }
+        , teamId = TeamId
+            { unTeamId = "T043DB835ML" }
+        , eventTime = MkSystemTime
+            { systemSeconds = 1724952300
+            , systemNanoseconds = 0
+            }
+        , event = EventMessage
+            ( MessageEvent
+                { blocks = Nothing
+                , channel = ConversationId
+                    { unConversationId = "C07KHDGQ7K3" }
+                , text = ""
+                , channelType = Channel
+                , files = Nothing
+                , user = UserId
+                    { unUserId = "U05JAA9EN4T" }
+                , ts = "1724952300.110719"
+                , threadTs = Nothing
+                , appId = Nothing
+                , botId = Nothing
+                , attachments = Just
+                    [ MessageAttachment
+                        { decoded = Just
+                            ( DecodedMessageAttachment
+                                { fallback = Just "[August 29th, 2024 10:24 AM] lev: 123"
+                                , color = Just "D0D0D0"
+                                , pretext = Nothing
+                                , authorName = Just "lev"
+                                , authorLink = Just "https://myworkspace.slack.com/team/U05JAA9EN4T"
+                                , authorIcon = Just "https://avatars.slack-edge.com/2023-07-22/5607926127815_66b9d49327ec16a887e5_48.png"
+                                , title = Nothing
+                                , titleLink = Nothing
+                                , text = Just "123"
+                                , fields = Nothing
+                                , imageUrl = Nothing
+                                , thumbUrl = Nothing
+                                , footer = Just "Slack Conversation"
+                                , footerIcon = Nothing
+                                , ts = Just "1724952281.623809"
+                                , isMsgUnfurl = Just True
+                                , messageBlocks = Just
+                                    [ AttachmentMessageBlock
+                                        { team = TeamId
+                                            { unTeamId = "T043DB835ML" }
+                                        , channel = ConversationId
+                                            { unConversationId = "C07KTH1T4CQ" }
+                                        , ts = "1724952281.623809"
+                                        , message = AttachmentMessageBlockMessage
+                                            { blocks =
+                                                [ RichText
+                                                    { blockId = Just
+                                                        ( NonEmptyText "nXUog" )
+                                                    , elements =
+                                                        [ RichTextSectionItemRichText
+                                                            [ RichItemText "123"
+                                                                ( RichStyle
+                                                                    { rsBold = False
+                                                                    , rsItalic = False
+                                                                    }
+                                                                )
+                                                            ]
+                                                        ]
+                                                    }
+                                                ]
+                                            }
+                                        }
+                                    ]
+                                , authorId = Just
+                                    ( UserId
+                                        { unUserId = "U05JAA9EN4T" }
+                                    )
+                                , channelId = Just
+                                    ( ConversationId
+                                        { unConversationId = "C07KTH1T4CQ" }
+                                    )
+                                , channelTeam = Just
+                                    ( TeamId
+                                        { unTeamId = "T043DB835ML" }
+                                    )
+                                , isAppUnfurl = Nothing
+                                , appUnfurlUrl = Nothing
+                                , fromUrl = Just "https://myworkspace.slack.com/archives/C07KTH1T4CQ/p1724952281623809"
+                                }
+                            )
+                        , raw = Object
+                            ( fromList
+                                [
+                                    ( "author_icon"
+                                    , String "https://avatars.slack-edge.com/2023-07-22/5607926127815_66b9d49327ec16a887e5_48.png"
+                                    )
+                                ,
+                                    ( "author_id"
+                                    , String "U05JAA9EN4T"
+                                    )
+                                ,
+                                    ( "author_link"
+                                    , String "https://myworkspace.slack.com/team/U05JAA9EN4T"
+                                    )
+                                ,
+                                    ( "author_name"
+                                    , String "lev"
+                                    )
+                                ,
+                                    ( "author_subname"
+                                    , String "lev"
+                                    )
+                                ,
+                                    ( "channel_id"
+                                    , String "C07KTH1T4CQ"
+                                    )
+                                ,
+                                    ( "channel_team"
+                                    , String "T043DB835ML"
+                                    )
+                                ,
+                                    ( "color"
+                                    , String "D0D0D0"
+                                    )
+                                ,
+                                    ( "fallback"
+                                    , String "[August 29th, 2024 10:24 AM] lev: 123"
+                                    )
+                                ,
+                                    ( "footer"
+                                    , String "Slack Conversation"
+                                    )
+                                ,
+                                    ( "from_url"
+                                    , String "https://myworkspace.slack.com/archives/C07KTH1T4CQ/p1724952281623809"
+                                    )
+                                ,
+                                    ( "is_msg_unfurl"
+                                    , Bool True
+                                    )
+                                ,
+                                    ( "is_share"
+                                    , Bool True
+                                    )
+                                ,
+                                    ( "message_blocks"
+                                    , Array
+                                        [ Object
+                                            ( fromList
+                                                [
+                                                    ( "channel"
+                                                    , String "C07KTH1T4CQ"
+                                                    )
+                                                ,
+                                                    ( "message"
+                                                    , Object
+                                                        ( fromList
+                                                            [
+                                                                ( "blocks"
+                                                                , Array
+                                                                    [ Object
+                                                                        ( fromList
+                                                                            [
+                                                                                ( "block_id"
+                                                                                , String "nXUog"
+                                                                                )
+                                                                            ,
+                                                                                ( "elements"
+                                                                                , Array
+                                                                                    [ Object
+                                                                                        ( fromList
+                                                                                            [
+                                                                                                ( "elements"
+                                                                                                , Array
+                                                                                                    [ Object
+                                                                                                        ( fromList
+                                                                                                            [
+                                                                                                                ( "text"
+                                                                                                                , String "123"
+                                                                                                                )
+                                                                                                            ,
+                                                                                                                ( "type"
+                                                                                                                , String "text"
+                                                                                                                )
+                                                                                                            ]
+                                                                                                        )
+                                                                                                    ]
+                                                                                                )
+                                                                                            ,
+                                                                                                ( "type"
+                                                                                                , String "rich_text_section"
+                                                                                                )
+                                                                                            ]
+                                                                                        )
+                                                                                    ]
+                                                                                )
+                                                                            ,
+                                                                                ( "type"
+                                                                                , String "rich_text"
+                                                                                )
+                                                                            ]
+                                                                        )
+                                                                    ]
+                                                                )
+                                                            ]
+                                                        )
+                                                    )
+                                                ,
+                                                    ( "team"
+                                                    , String "T043DB835ML"
+                                                    )
+                                                ,
+                                                    ( "ts"
+                                                    , String "1724952281.623809"
+                                                    )
+                                                ]
+                                            )
+                                        ]
+                                    )
+                                ,
+                                    ( "mrkdwn_in"
+                                    , Array
+                                        [ String "text" ]
+                                    )
+                                ,
+                                    ( "text"
+                                    , String "123"
+                                    )
+                                ,
+                                    ( "ts"
+                                    , String "1724952281.623809"
+                                    )
+                                ]
+                            )
+                        }
+                    ]
+                }
+            )
+        }
+    )
diff --git a/tests/golden/SlackWebhookEvent/forwarded_message.json b/tests/golden/SlackWebhookEvent/forwarded_message.json
new file mode 100644
--- /dev/null
+++ b/tests/golden/SlackWebhookEvent/forwarded_message.json
@@ -0,0 +1,78 @@
+{
+    "token": "aaaa",
+    "team_id": "T043DB835ML",
+    "context_team_id": "T043DB835ML",
+    "context_enterprise_id": null,
+    "api_app_id": "A07JRKQPZDH",
+    "event": {
+        "user": "U05JAA9EN4T",
+        "type": "message",
+        "ts": "1724952300.110719",
+        "text": "",
+        "team": "T043DB835ML",
+        "attachments": [
+            {
+                "ts": "1724952281.623809",
+                "author_id": "U05JAA9EN4T",
+                "channel_id": "C07KTH1T4CQ",
+                "channel_team": "T043DB835ML",
+                "is_msg_unfurl": true,
+                "message_blocks": [
+                    {
+                        "team": "T043DB835ML",
+                        "channel": "C07KTH1T4CQ",
+                        "ts": "1724952281.623809",
+                        "message": {
+                            "blocks": [
+                                {
+                                    "type": "rich_text",
+                                    "block_id": "nXUog",
+                                    "elements": [
+                                        {
+                                            "type": "rich_text_section",
+                                            "elements": [
+                                                {
+                                                    "type": "text",
+                                                    "text": "123"
+                                                }
+                                            ]
+                                        }
+                                    ]
+                                }
+                            ]
+                        }
+                    }
+                ],
+                "color": "D0D0D0",
+                "from_url": "https://myworkspace.slack.com/archives/C07KTH1T4CQ/p1724952281623809",
+                "is_share": true,
+                "fallback": "[August 29th, 2024 10:24 AM] lev: 123",
+                "text": "123",
+                "author_name": "lev",
+                "author_link": "https://myworkspace.slack.com/team/U05JAA9EN4T",
+                "author_icon": "https://avatars.slack-edge.com/2023-07-22/5607926127815_66b9d49327ec16a887e5_48.png",
+                "author_subname": "lev",
+                "mrkdwn_in": [
+                    "text"
+                ],
+                "footer": "Slack Conversation"
+            }
+        ],
+        "channel": "C07KHDGQ7K3",
+        "event_ts": "1724952300.110719",
+        "channel_type": "channel"
+    },
+    "type": "event_callback",
+    "event_id": "Ev07KHG83J1F",
+    "event_time": 1724952300,
+    "authorizations": [
+        {
+            "enterprise_id": null,
+            "team_id": "T043DB835ML",
+            "user_id": "U07K4E18KJM",
+            "is_bot": true,
+            "is_enterprise_install": false
+        }
+    ],
+    "is_ext_shared_channel": false
+}
diff --git a/tests/golden/SlackWebhookEvent/github_notification.golden b/tests/golden/SlackWebhookEvent/github_notification.golden
new file mode 100644
--- /dev/null
+++ b/tests/golden/SlackWebhookEvent/github_notification.golden
@@ -0,0 +1,197 @@
+EventEventCallback
+    ( EventCallback
+        { eventId = EventId
+            { unEventId = "Ev07MH6R7FDE" }
+        , teamId = TeamId
+            { unTeamId = "T043DB835ML" }
+        , eventTime = MkSystemTime
+            { systemSeconds = 1725998548
+            , systemNanoseconds = 0
+            }
+        , event = EventMessage
+            ( MessageEvent
+                { blocks = Nothing
+                , channel = ConversationId
+                    { unConversationId = "C07LRFB3C8M" }
+                , text = ""
+                , channelType = Channel
+                , files = Nothing
+                , user = UserId
+                    { unUserId = "U07M725KAD7" }
+                , ts = "1725998548.581159"
+                , threadTs = Nothing
+                , appId = Just "A01BP7R4KNY"
+                , botId = Just "B07LDR01Z63"
+                , attachments = Just
+                    [ MessageAttachment
+                        { decoded = Just
+                            ( DecodedMessageAttachment
+                                { fallback = Just "[myorg/myrepo] Issue opened by ldub"
+                                , color = Just "36a64f"
+                                , pretext = Just "Issue created by <https://github.com/ldub|ldub>"
+                                , authorName = Nothing
+                                , authorLink = Nothing
+                                , authorIcon = Nothing
+                                , title = Just "<https://github.com/myorg/myrepo/issues/2|#2 test issue 2>"
+                                , titleLink = Nothing
+                                , text = Just "another oneeeee"
+                                , fields = Nothing
+                                , imageUrl = Nothing
+                                , thumbUrl = Nothing
+                                , footer = Just "<https://github.com/myorg/myrepo|myorg/myrepo>"
+                                , footerIcon = Just "https://slack.github.com/static/img/favicon-neutral.png"
+                                , ts = Just "1725998545.0"
+                                , isMsgUnfurl = Nothing
+                                , messageBlocks = Nothing
+                                , authorId = Nothing
+                                , channelId = Nothing
+                                , channelTeam = Nothing
+                                , isAppUnfurl = Nothing
+                                , appUnfurlUrl = Nothing
+                                , fromUrl = Nothing
+                                }
+                            )
+                        , raw = Object
+                            ( fromList
+                                [
+                                    ( "actions"
+                                    , Array
+                                        [ Object
+                                            ( fromList
+                                                [
+                                                    ( "id"
+                                                    , String "1"
+                                                    )
+                                                ,
+                                                    ( "name"
+                                                    , String "comment"
+                                                    )
+                                                ,
+                                                    ( "style"
+                                                    , String ""
+                                                    )
+                                                ,
+                                                    ( "text"
+                                                    , String "Comment"
+                                                    )
+                                                ,
+                                                    ( "type"
+                                                    , String "button"
+                                                    )
+                                                ,
+                                                    ( "value"
+                                                    , String "{&amp;amp;quot;selectedOrg&amp;amp;quot;:&amp;amp;quot;myorg&amp;amp;quot;,&amp;amp;quot;selectedOrgId&amp;amp;quot;:140364112,&amp;amp;quot;selectedRepo&amp;amp;quot;:&amp;amp;quot;myrepo&amp;amp;quot;,&amp;amp;quot;selectedRepoId&amp;amp;quot;:809927288,&amp;amp;quot;issueNumber&amp;amp;quot;:2,&amp;amp;quot;issueHtmlUrl&amp;amp;quot;:&amp;amp;quot;https://github.com/myorg/myrepo/issues/2&amp;amp;quot;,&amp;amp;quot;issueTitle&amp;amp;quot;:&amp;amp;quot;test issue 2&amp;amp;quot;}"
+                                                    )
+                                                ]
+                                            )
+                                        , Object
+                                            ( fromList
+                                                [
+                                                    ( "id"
+                                                    , String "2"
+                                                    )
+                                                ,
+                                                    ( "name"
+                                                    , String "edit"
+                                                    )
+                                                ,
+                                                    ( "style"
+                                                    , String ""
+                                                    )
+                                                ,
+                                                    ( "text"
+                                                    , String "Edit"
+                                                    )
+                                                ,
+                                                    ( "type"
+                                                    , String "button"
+                                                    )
+                                                ,
+                                                    ( "value"
+                                                    , String "{&amp;amp;quot;selectedOrg&amp;amp;quot;:&amp;amp;quot;myorg&amp;amp;quot;,&amp;amp;quot;selectedOrgId&amp;amp;quot;:140364112,&amp;amp;quot;selectedRepo&amp;amp;quot;:&amp;amp;quot;myrepo&amp;amp;quot;,&amp;amp;quot;selectedRepoId&amp;amp;quot;:809927288,&amp;amp;quot;issueNumber&amp;amp;quot;:2,&amp;amp;quot;issueHtmlUrl&amp;amp;quot;:&amp;amp;quot;https://github.com/myorg/myrepo/issues/2&amp;amp;quot;,&amp;amp;quot;issueTitle&amp;amp;quot;:&amp;amp;quot;test issue 2&amp;amp;quot;}"
+                                                    )
+                                                ]
+                                            )
+                                        , Object
+                                            ( fromList
+                                                [
+                                                    ( "id"
+                                                    , String "3"
+                                                    )
+                                                ,
+                                                    ( "name"
+                                                    , String "close"
+                                                    )
+                                                ,
+                                                    ( "style"
+                                                    , String "danger"
+                                                    )
+                                                ,
+                                                    ( "text"
+                                                    , String "Close"
+                                                    )
+                                                ,
+                                                    ( "type"
+                                                    , String "button"
+                                                    )
+                                                ,
+                                                    ( "value"
+                                                    , String "{&amp;amp;quot;selectedOrg&amp;amp;quot;:&amp;amp;quot;myorg&amp;amp;quot;,&amp;amp;quot;selectedOrgId&amp;amp;quot;:140364112,&amp;amp;quot;selectedRepo&amp;amp;quot;:&amp;amp;quot;myrepo&amp;amp;quot;,&amp;amp;quot;selectedRepoId&amp;amp;quot;:809927288,&amp;amp;quot;issueNumber&amp;amp;quot;:2,&amp;amp;quot;issueHtmlUrl&amp;amp;quot;:&amp;amp;quot;https://github.com/myorg/myrepo/issues/2&amp;amp;quot;,&amp;amp;quot;issueTitle&amp;amp;quot;:&amp;amp;quot;test issue 2&amp;amp;quot;}"
+                                                    )
+                                                ]
+                                            )
+                                        ]
+                                    )
+                                ,
+                                    ( "callback_id"
+                                    , String "issue-opened-interaction"
+                                    )
+                                ,
+                                    ( "color"
+                                    , String "36a64f"
+                                    )
+                                ,
+                                    ( "fallback"
+                                    , String "[myorg/myrepo] Issue opened by ldub"
+                                    )
+                                ,
+                                    ( "footer"
+                                    , String "<https://github.com/myorg/myrepo|myorg/myrepo>"
+                                    )
+                                ,
+                                    ( "footer_icon"
+                                    , String "https://slack.github.com/static/img/favicon-neutral.png"
+                                    )
+                                ,
+                                    ( "id"
+                                    , Number 1.0
+                                    )
+                                ,
+                                    ( "mrkdwn_in"
+                                    , Array
+                                        [ String "text" ]
+                                    )
+                                ,
+                                    ( "pretext"
+                                    , String "Issue created by <https://github.com/ldub|ldub>"
+                                    )
+                                ,
+                                    ( "text"
+                                    , String "another oneeeee"
+                                    )
+                                ,
+                                    ( "title"
+                                    , String "<https://github.com/myorg/myrepo/issues/2|#2 test issue 2>"
+                                    )
+                                ,
+                                    ( "ts"
+                                    , Number 1.725998545e9
+                                    )
+                                ]
+                            )
+                        }
+                    ]
+                }
+            )
+        }
+    )
diff --git a/tests/golden/SlackWebhookEvent/github_notification.json b/tests/golden/SlackWebhookEvent/github_notification.json
new file mode 100644
--- /dev/null
+++ b/tests/golden/SlackWebhookEvent/github_notification.json
@@ -0,0 +1,88 @@
+{
+    "token": "aaaa",
+    "team_id": "T043DB835ML",
+    "context_team_id": "T043DB835ML",
+    "context_enterprise_id": null,
+    "api_app_id": "A07JRKQPZDH",
+    "event": {
+        "user": "U07M725KAD7",
+        "type": "message",
+        "ts": "1725998548.581159",
+        "bot_id": "B07LDR01Z63",
+        "app_id": "A01BP7R4KNY",
+        "text": "",
+        "team": "T043DB835ML",
+        "bot_profile": {
+            "id": "B07LDR01Z63",
+            "deleted": false,
+            "name": "GitHub",
+            "updated": 1725998199,
+            "app_id": "A01BP7R4KNY",
+            "icons": {
+                "image_36": "https://avatars.slack-edge.com/2020-11-25/1527503386626_319578f21381f9641cd8_36.png",
+                "image_48": "https://avatars.slack-edge.com/2020-11-25/1527503386626_319578f21381f9641cd8_48.png",
+                "image_72": "https://avatars.slack-edge.com/2020-11-25/1527503386626_319578f21381f9641cd8_72.png"
+            },
+            "team_id": "T043DB835ML"
+        },
+        "attachments": [
+            {
+                "id": 1,
+                "footer_icon": "https://slack.github.com/static/img/favicon-neutral.png",
+                "ts": 1725998545,
+                "color": "36a64f",
+                "fallback": "[myorg/myrepo] Issue opened by ldub",
+                "text": "another oneeeee",
+                "pretext": "Issue created by <https://github.com/ldub|ldub>",
+                "title": "<https://github.com/myorg/myrepo/issues/2|#2 test issue 2>",
+                "callback_id": "issue-opened-interaction",
+                "footer": "<https://github.com/myorg/myrepo|myorg/myrepo>",
+                "mrkdwn_in": [
+                    "text"
+                ],
+                "actions": [
+                    {
+                        "id": "1",
+                        "name": "comment",
+                        "text": "Comment",
+                        "type": "button",
+                        "value": "{&amp;amp;quot;selectedOrg&amp;amp;quot;:&amp;amp;quot;myorg&amp;amp;quot;,&amp;amp;quot;selectedOrgId&amp;amp;quot;:140364112,&amp;amp;quot;selectedRepo&amp;amp;quot;:&amp;amp;quot;myrepo&amp;amp;quot;,&amp;amp;quot;selectedRepoId&amp;amp;quot;:809927288,&amp;amp;quot;issueNumber&amp;amp;quot;:2,&amp;amp;quot;issueHtmlUrl&amp;amp;quot;:&amp;amp;quot;https://github.com/myorg/myrepo/issues/2&amp;amp;quot;,&amp;amp;quot;issueTitle&amp;amp;quot;:&amp;amp;quot;test issue 2&amp;amp;quot;}",
+                        "style": ""
+                    },
+                    {
+                        "id": "2",
+                        "name": "edit",
+                        "text": "Edit",
+                        "type": "button",
+                        "value": "{&amp;amp;quot;selectedOrg&amp;amp;quot;:&amp;amp;quot;myorg&amp;amp;quot;,&amp;amp;quot;selectedOrgId&amp;amp;quot;:140364112,&amp;amp;quot;selectedRepo&amp;amp;quot;:&amp;amp;quot;myrepo&amp;amp;quot;,&amp;amp;quot;selectedRepoId&amp;amp;quot;:809927288,&amp;amp;quot;issueNumber&amp;amp;quot;:2,&amp;amp;quot;issueHtmlUrl&amp;amp;quot;:&amp;amp;quot;https://github.com/myorg/myrepo/issues/2&amp;amp;quot;,&amp;amp;quot;issueTitle&amp;amp;quot;:&amp;amp;quot;test issue 2&amp;amp;quot;}",
+                        "style": ""
+                    },
+                    {
+                        "id": "3",
+                        "name": "close",
+                        "text": "Close",
+                        "type": "button",
+                        "value": "{&amp;amp;quot;selectedOrg&amp;amp;quot;:&amp;amp;quot;myorg&amp;amp;quot;,&amp;amp;quot;selectedOrgId&amp;amp;quot;:140364112,&amp;amp;quot;selectedRepo&amp;amp;quot;:&amp;amp;quot;myrepo&amp;amp;quot;,&amp;amp;quot;selectedRepoId&amp;amp;quot;:809927288,&amp;amp;quot;issueNumber&amp;amp;quot;:2,&amp;amp;quot;issueHtmlUrl&amp;amp;quot;:&amp;amp;quot;https://github.com/myorg/myrepo/issues/2&amp;amp;quot;,&amp;amp;quot;issueTitle&amp;amp;quot;:&amp;amp;quot;test issue 2&amp;amp;quot;}",
+                        "style": "danger"
+                    }
+                ]
+            }
+        ],
+        "channel": "C07LRFB3C8M",
+        "event_ts": "1725998548.581159",
+        "channel_type": "channel"
+    },
+    "type": "event_callback",
+    "event_id": "Ev07MH6R7FDE",
+    "event_time": 1725998548,
+    "authorizations": [
+        {
+            "enterprise_id": null,
+            "team_id": "T043DB835ML",
+            "user_id": "U07K4E18KJM",
+            "is_bot": true,
+            "is_enterprise_install": false
+        }
+    ],
+    "is_ext_shared_channel": false
+}
diff --git a/tests/golden/SlackWebhookEvent/github_notification_ts_string.golden b/tests/golden/SlackWebhookEvent/github_notification_ts_string.golden
new file mode 100644
--- /dev/null
+++ b/tests/golden/SlackWebhookEvent/github_notification_ts_string.golden
@@ -0,0 +1,197 @@
+EventEventCallback
+    ( EventCallback
+        { eventId = EventId
+            { unEventId = "Ev07MH6R7FDE" }
+        , teamId = TeamId
+            { unTeamId = "T043DB835ML" }
+        , eventTime = MkSystemTime
+            { systemSeconds = 1725998548
+            , systemNanoseconds = 0
+            }
+        , event = EventMessage
+            ( MessageEvent
+                { blocks = Nothing
+                , channel = ConversationId
+                    { unConversationId = "C07LRFB3C8M" }
+                , text = ""
+                , channelType = Channel
+                , files = Nothing
+                , user = UserId
+                    { unUserId = "U07M725KAD7" }
+                , ts = "1725998548.581159"
+                , threadTs = Nothing
+                , appId = Just "A01BP7R4KNY"
+                , botId = Just "B07LDR01Z63"
+                , attachments = Just
+                    [ MessageAttachment
+                        { decoded = Just
+                            ( DecodedMessageAttachment
+                                { fallback = Just "[myorg/myrepo] Issue opened by ldub"
+                                , color = Just "36a64f"
+                                , pretext = Just "Issue created by <https://github.com/ldub|ldub>"
+                                , authorName = Nothing
+                                , authorLink = Nothing
+                                , authorIcon = Nothing
+                                , title = Just "<https://github.com/myorg/myrepo/issues/2|#2 test issue 2>"
+                                , titleLink = Nothing
+                                , text = Just "another oneeeee"
+                                , fields = Nothing
+                                , imageUrl = Nothing
+                                , thumbUrl = Nothing
+                                , footer = Just "<https://github.com/myorg/myrepo|myorg/myrepo>"
+                                , footerIcon = Just "https://slack.github.com/static/img/favicon-neutral.png"
+                                , ts = Just "1725998545.123456"
+                                , isMsgUnfurl = Nothing
+                                , messageBlocks = Nothing
+                                , authorId = Nothing
+                                , channelId = Nothing
+                                , channelTeam = Nothing
+                                , isAppUnfurl = Nothing
+                                , appUnfurlUrl = Nothing
+                                , fromUrl = Nothing
+                                }
+                            )
+                        , raw = Object
+                            ( fromList
+                                [
+                                    ( "actions"
+                                    , Array
+                                        [ Object
+                                            ( fromList
+                                                [
+                                                    ( "id"
+                                                    , String "1"
+                                                    )
+                                                ,
+                                                    ( "name"
+                                                    , String "comment"
+                                                    )
+                                                ,
+                                                    ( "style"
+                                                    , String ""
+                                                    )
+                                                ,
+                                                    ( "text"
+                                                    , String "Comment"
+                                                    )
+                                                ,
+                                                    ( "type"
+                                                    , String "button"
+                                                    )
+                                                ,
+                                                    ( "value"
+                                                    , String "{&amp;amp;quot;selectedOrg&amp;amp;quot;:&amp;amp;quot;myorg&amp;amp;quot;,&amp;amp;quot;selectedOrgId&amp;amp;quot;:140364112,&amp;amp;quot;selectedRepo&amp;amp;quot;:&amp;amp;quot;myrepo&amp;amp;quot;,&amp;amp;quot;selectedRepoId&amp;amp;quot;:809927288,&amp;amp;quot;issueNumber&amp;amp;quot;:2,&amp;amp;quot;issueHtmlUrl&amp;amp;quot;:&amp;amp;quot;https://github.com/myorg/myrepo/issues/2&amp;amp;quot;,&amp;amp;quot;issueTitle&amp;amp;quot;:&amp;amp;quot;test issue 2&amp;amp;quot;}"
+                                                    )
+                                                ]
+                                            )
+                                        , Object
+                                            ( fromList
+                                                [
+                                                    ( "id"
+                                                    , String "2"
+                                                    )
+                                                ,
+                                                    ( "name"
+                                                    , String "edit"
+                                                    )
+                                                ,
+                                                    ( "style"
+                                                    , String ""
+                                                    )
+                                                ,
+                                                    ( "text"
+                                                    , String "Edit"
+                                                    )
+                                                ,
+                                                    ( "type"
+                                                    , String "button"
+                                                    )
+                                                ,
+                                                    ( "value"
+                                                    , String "{&amp;amp;quot;selectedOrg&amp;amp;quot;:&amp;amp;quot;myorg&amp;amp;quot;,&amp;amp;quot;selectedOrgId&amp;amp;quot;:140364112,&amp;amp;quot;selectedRepo&amp;amp;quot;:&amp;amp;quot;myrepo&amp;amp;quot;,&amp;amp;quot;selectedRepoId&amp;amp;quot;:809927288,&amp;amp;quot;issueNumber&amp;amp;quot;:2,&amp;amp;quot;issueHtmlUrl&amp;amp;quot;:&amp;amp;quot;https://github.com/myorg/myrepo/issues/2&amp;amp;quot;,&amp;amp;quot;issueTitle&amp;amp;quot;:&amp;amp;quot;test issue 2&amp;amp;quot;}"
+                                                    )
+                                                ]
+                                            )
+                                        , Object
+                                            ( fromList
+                                                [
+                                                    ( "id"
+                                                    , String "3"
+                                                    )
+                                                ,
+                                                    ( "name"
+                                                    , String "close"
+                                                    )
+                                                ,
+                                                    ( "style"
+                                                    , String "danger"
+                                                    )
+                                                ,
+                                                    ( "text"
+                                                    , String "Close"
+                                                    )
+                                                ,
+                                                    ( "type"
+                                                    , String "button"
+                                                    )
+                                                ,
+                                                    ( "value"
+                                                    , String "{&amp;amp;quot;selectedOrg&amp;amp;quot;:&amp;amp;quot;myorg&amp;amp;quot;,&amp;amp;quot;selectedOrgId&amp;amp;quot;:140364112,&amp;amp;quot;selectedRepo&amp;amp;quot;:&amp;amp;quot;myrepo&amp;amp;quot;,&amp;amp;quot;selectedRepoId&amp;amp;quot;:809927288,&amp;amp;quot;issueNumber&amp;amp;quot;:2,&amp;amp;quot;issueHtmlUrl&amp;amp;quot;:&amp;amp;quot;https://github.com/myorg/myrepo/issues/2&amp;amp;quot;,&amp;amp;quot;issueTitle&amp;amp;quot;:&amp;amp;quot;test issue 2&amp;amp;quot;}"
+                                                    )
+                                                ]
+                                            )
+                                        ]
+                                    )
+                                ,
+                                    ( "callback_id"
+                                    , String "issue-opened-interaction"
+                                    )
+                                ,
+                                    ( "color"
+                                    , String "36a64f"
+                                    )
+                                ,
+                                    ( "fallback"
+                                    , String "[myorg/myrepo] Issue opened by ldub"
+                                    )
+                                ,
+                                    ( "footer"
+                                    , String "<https://github.com/myorg/myrepo|myorg/myrepo>"
+                                    )
+                                ,
+                                    ( "footer_icon"
+                                    , String "https://slack.github.com/static/img/favicon-neutral.png"
+                                    )
+                                ,
+                                    ( "id"
+                                    , Number 1.0
+                                    )
+                                ,
+                                    ( "mrkdwn_in"
+                                    , Array
+                                        [ String "text" ]
+                                    )
+                                ,
+                                    ( "pretext"
+                                    , String "Issue created by <https://github.com/ldub|ldub>"
+                                    )
+                                ,
+                                    ( "text"
+                                    , String "another oneeeee"
+                                    )
+                                ,
+                                    ( "title"
+                                    , String "<https://github.com/myorg/myrepo/issues/2|#2 test issue 2>"
+                                    )
+                                ,
+                                    ( "ts"
+                                    , String "1725998545.123456"
+                                    )
+                                ]
+                            )
+                        }
+                    ]
+                }
+            )
+        }
+    )
diff --git a/tests/golden/SlackWebhookEvent/github_notification_ts_string.json b/tests/golden/SlackWebhookEvent/github_notification_ts_string.json
new file mode 100644
--- /dev/null
+++ b/tests/golden/SlackWebhookEvent/github_notification_ts_string.json
@@ -0,0 +1,88 @@
+{
+    "token": "aaaa",
+    "team_id": "T043DB835ML",
+    "context_team_id": "T043DB835ML",
+    "context_enterprise_id": null,
+    "api_app_id": "A07JRKQPZDH",
+    "event": {
+        "user": "U07M725KAD7",
+        "type": "message",
+        "ts": "1725998548.581159",
+        "bot_id": "B07LDR01Z63",
+        "app_id": "A01BP7R4KNY",
+        "text": "",
+        "team": "T043DB835ML",
+        "bot_profile": {
+            "id": "B07LDR01Z63",
+            "deleted": false,
+            "name": "GitHub",
+            "updated": 1725998199,
+            "app_id": "A01BP7R4KNY",
+            "icons": {
+                "image_36": "https://avatars.slack-edge.com/2020-11-25/1527503386626_319578f21381f9641cd8_36.png",
+                "image_48": "https://avatars.slack-edge.com/2020-11-25/1527503386626_319578f21381f9641cd8_48.png",
+                "image_72": "https://avatars.slack-edge.com/2020-11-25/1527503386626_319578f21381f9641cd8_72.png"
+            },
+            "team_id": "T043DB835ML"
+        },
+        "attachments": [
+            {
+                "id": 1,
+                "footer_icon": "https://slack.github.com/static/img/favicon-neutral.png",
+                "ts": "1725998545.123456",
+                "color": "36a64f",
+                "fallback": "[myorg/myrepo] Issue opened by ldub",
+                "text": "another oneeeee",
+                "pretext": "Issue created by <https://github.com/ldub|ldub>",
+                "title": "<https://github.com/myorg/myrepo/issues/2|#2 test issue 2>",
+                "callback_id": "issue-opened-interaction",
+                "footer": "<https://github.com/myorg/myrepo|myorg/myrepo>",
+                "mrkdwn_in": [
+                    "text"
+                ],
+                "actions": [
+                    {
+                        "id": "1",
+                        "name": "comment",
+                        "text": "Comment",
+                        "type": "button",
+                        "value": "{&amp;amp;quot;selectedOrg&amp;amp;quot;:&amp;amp;quot;myorg&amp;amp;quot;,&amp;amp;quot;selectedOrgId&amp;amp;quot;:140364112,&amp;amp;quot;selectedRepo&amp;amp;quot;:&amp;amp;quot;myrepo&amp;amp;quot;,&amp;amp;quot;selectedRepoId&amp;amp;quot;:809927288,&amp;amp;quot;issueNumber&amp;amp;quot;:2,&amp;amp;quot;issueHtmlUrl&amp;amp;quot;:&amp;amp;quot;https://github.com/myorg/myrepo/issues/2&amp;amp;quot;,&amp;amp;quot;issueTitle&amp;amp;quot;:&amp;amp;quot;test issue 2&amp;amp;quot;}",
+                        "style": ""
+                    },
+                    {
+                        "id": "2",
+                        "name": "edit",
+                        "text": "Edit",
+                        "type": "button",
+                        "value": "{&amp;amp;quot;selectedOrg&amp;amp;quot;:&amp;amp;quot;myorg&amp;amp;quot;,&amp;amp;quot;selectedOrgId&amp;amp;quot;:140364112,&amp;amp;quot;selectedRepo&amp;amp;quot;:&amp;amp;quot;myrepo&amp;amp;quot;,&amp;amp;quot;selectedRepoId&amp;amp;quot;:809927288,&amp;amp;quot;issueNumber&amp;amp;quot;:2,&amp;amp;quot;issueHtmlUrl&amp;amp;quot;:&amp;amp;quot;https://github.com/myorg/myrepo/issues/2&amp;amp;quot;,&amp;amp;quot;issueTitle&amp;amp;quot;:&amp;amp;quot;test issue 2&amp;amp;quot;}",
+                        "style": ""
+                    },
+                    {
+                        "id": "3",
+                        "name": "close",
+                        "text": "Close",
+                        "type": "button",
+                        "value": "{&amp;amp;quot;selectedOrg&amp;amp;quot;:&amp;amp;quot;myorg&amp;amp;quot;,&amp;amp;quot;selectedOrgId&amp;amp;quot;:140364112,&amp;amp;quot;selectedRepo&amp;amp;quot;:&amp;amp;quot;myrepo&amp;amp;quot;,&amp;amp;quot;selectedRepoId&amp;amp;quot;:809927288,&amp;amp;quot;issueNumber&amp;amp;quot;:2,&amp;amp;quot;issueHtmlUrl&amp;amp;quot;:&amp;amp;quot;https://github.com/myorg/myrepo/issues/2&amp;amp;quot;,&amp;amp;quot;issueTitle&amp;amp;quot;:&amp;amp;quot;test issue 2&amp;amp;quot;}",
+                        "style": "danger"
+                    }
+                ]
+            }
+        ],
+        "channel": "C07LRFB3C8M",
+        "event_ts": "1725998548.581159",
+        "channel_type": "channel"
+    },
+    "type": "event_callback",
+    "event_id": "Ev07MH6R7FDE",
+    "event_time": 1725998548,
+    "authorizations": [
+        {
+            "enterprise_id": null,
+            "team_id": "T043DB835ML",
+            "user_id": "U07K4E18KJM",
+            "is_bot": true,
+            "is_enterprise_install": false
+        }
+    ],
+    "is_ext_shared_channel": false
+}
diff --git a/tests/golden/SlackWebhookEvent/github_with_link.golden b/tests/golden/SlackWebhookEvent/github_with_link.golden
new file mode 100644
--- /dev/null
+++ b/tests/golden/SlackWebhookEvent/github_with_link.golden
@@ -0,0 +1,145 @@
+EventEventCallback
+    ( EventCallback
+        { eventId = EventId
+            { unEventId = "Ev07U5U3EQCV" }
+        , teamId = TeamId
+            { unTeamId = "T043DB835ML" }
+        , eventTime = MkSystemTime
+            { systemSeconds = 1730339959
+            , systemNanoseconds = 0
+            }
+        , event = EventMessage
+            ( MessageEvent
+                { blocks = Nothing
+                , channel = ConversationId
+                    { unConversationId = "C07LRFB3C8M" }
+                , text = ""
+                , channelType = Channel
+                , files = Nothing
+                , user = UserId
+                    { unUserId = "U07M725KAD7" }
+                , ts = "1730339959.644979"
+                , threadTs = Nothing
+                , appId = Just "A01BP7R4KNY"
+                , botId = Just "B07LDR01Z63"
+                , attachments = Just
+                    [ MessageAttachment
+                        { decoded = Just
+                            ( DecodedMessageAttachment
+                                { fallback = Just "[myorg/myrepo] Pull request opened by ldub"
+                                , color = Just "36a64f"
+                                , pretext = Just "Pull request opened by <https://github.com/ldub|ldub>"
+                                , authorName = Nothing
+                                , authorLink = Nothing
+                                , authorIcon = Nothing
+                                , title = Just "<https://github.com/myorg/myrepo/pull/8|#8 https://myteam.slack.com/archives/C07KTH1T4CQ/p1730339894629249>"
+                                , titleLink = Nothing
+                                , text = Just "this is a fake pr with a link
+
+                                  <https://myteam.slack.com/archives/C07KTH1T4CQ/p1730339894629249|https://myteam.slack.com/archives/C07KTH1T4CQ/p1730339894629249>"
+                                , fields = Nothing
+                                , imageUrl = Nothing
+                                , thumbUrl = Nothing
+                                , footer = Just "<https://github.com/myorg/myrepo|myorg/myrepo>"
+                                , footerIcon = Just "https://slack.github.com/static/img/favicon-neutral.png"
+                                , ts = Just "1730339957.0"
+                                , isMsgUnfurl = Nothing
+                                , messageBlocks = Nothing
+                                , authorId = Nothing
+                                , channelId = Nothing
+                                , channelTeam = Nothing
+                                , isAppUnfurl = Nothing
+                                , appUnfurlUrl = Nothing
+                                , fromUrl = Nothing
+                                }
+                            )
+                        , raw = Object
+                            ( fromList
+                                [
+                                    ( "actions"
+                                    , Array
+                                        [ Object
+                                            ( fromList
+                                                [
+                                                    ( "id"
+                                                    , String "1"
+                                                    )
+                                                ,
+                                                    ( "name"
+                                                    , String "comment"
+                                                    )
+                                                ,
+                                                    ( "style"
+                                                    , String ""
+                                                    )
+                                                ,
+                                                    ( "text"
+                                                    , String "Comment"
+                                                    )
+                                                ,
+                                                    ( "type"
+                                                    , String "button"
+                                                    )
+                                                ,
+                                                    ( "value"
+                                                    , String "{&amp;amp;quot;selectedOrg&amp;amp;quot;:&amp;amp;quot;myorg&amp;amp;quot;,&amp;amp;quot;selectedOrgId&amp;amp;quot;:140364112,&amp;amp;quot;selectedRepo&amp;amp;quot;:&amp;amp;quot;myrepo&amp;amp;quot;,&amp;amp;quot;selectedRepoId&amp;amp;quot;:669978765,&amp;amp;quot;number&amp;amp;quot;:8,&amp;amp;quot;htmlUrl&amp;amp;quot;:&amp;amp;quot;https://github.com/myorg/myrepo/pull/8&amp;amp;quot;,&amp;amp;quot;title&amp;amp;quot;:&amp;amp;quot;https://myteam.slack.com/archives/C07KTH1T4CQ/p1730339894629249&amp;amp;quot;}"
+                                                    )
+                                                ]
+                                            )
+                                        ]
+                                    )
+                                ,
+                                    ( "callback_id"
+                                    , String "pr-opened-interaction"
+                                    )
+                                ,
+                                    ( "color"
+                                    , String "36a64f"
+                                    )
+                                ,
+                                    ( "fallback"
+                                    , String "[myorg/myrepo] Pull request opened by ldub"
+                                    )
+                                ,
+                                    ( "footer"
+                                    , String "<https://github.com/myorg/myrepo|myorg/myrepo>"
+                                    )
+                                ,
+                                    ( "footer_icon"
+                                    , String "https://slack.github.com/static/img/favicon-neutral.png"
+                                    )
+                                ,
+                                    ( "id"
+                                    , Number 1.0
+                                    )
+                                ,
+                                    ( "mrkdwn_in"
+                                    , Array
+                                        [ String "text" ]
+                                    )
+                                ,
+                                    ( "pretext"
+                                    , String "Pull request opened by <https://github.com/ldub|ldub>"
+                                    )
+                                ,
+                                    ( "text"
+                                    , String "this is a fake pr with a link
+
+                                      <https://myteam.slack.com/archives/C07KTH1T4CQ/p1730339894629249|https://myteam.slack.com/archives/C07KTH1T4CQ/p1730339894629249>"
+                                    )
+                                ,
+                                    ( "title"
+                                    , String "<https://github.com/myorg/myrepo/pull/8|#8 https://myteam.slack.com/archives/C07KTH1T4CQ/p1730339894629249>"
+                                    )
+                                ,
+                                    ( "ts"
+                                    , Number 1.730339957e9
+                                    )
+                                ]
+                            )
+                        }
+                    ]
+                }
+            )
+        }
+    )
diff --git a/tests/golden/SlackWebhookEvent/github_with_link.json b/tests/golden/SlackWebhookEvent/github_with_link.json
new file mode 100644
--- /dev/null
+++ b/tests/golden/SlackWebhookEvent/github_with_link.json
@@ -0,0 +1,72 @@
+{
+    "token": "aaaa",
+    "team_id": "T043DB835ML",
+    "context_team_id": "T043DB835ML",
+    "context_enterprise_id": null,
+    "api_app_id": "A07JRKQPZDH",
+    "event": {
+        "user": "U07M725KAD7",
+        "type": "message",
+        "ts": "1730339959.644979",
+        "bot_id": "B07LDR01Z63",
+        "app_id": "A01BP7R4KNY",
+        "text": "",
+        "team": "T043DB835ML",
+        "bot_profile": {
+            "id": "B07LDR01Z63",
+            "deleted": false,
+            "name": "GitHub",
+            "updated": 1725998199,
+            "app_id": "A01BP7R4KNY",
+            "icons": {
+                "image_36": "https://avatars.slack-edge.com/2020-11-25/1527503386626_319578f21381f9641cd8_36.png",
+                "image_48": "https://avatars.slack-edge.com/2020-11-25/1527503386626_319578f21381f9641cd8_48.png",
+                "image_72": "https://avatars.slack-edge.com/2020-11-25/1527503386626_319578f21381f9641cd8_72.png"
+            },
+            "team_id": "T043DB835ML"
+        },
+        "attachments": [
+            {
+                "id": 1,
+                "footer_icon": "https://slack.github.com/static/img/favicon-neutral.png",
+                "ts": 1730339957,
+                "color": "36a64f",
+                "fallback": "[myorg/myrepo] Pull request opened by ldub",
+                "text": "this is a fake pr with a link\n\n<https://myteam.slack.com/archives/C07KTH1T4CQ/p1730339894629249|https://myteam.slack.com/archives/C07KTH1T4CQ/p1730339894629249>",
+                "pretext": "Pull request opened by <https://github.com/ldub|ldub>",
+                "title": "<https://github.com/myorg/myrepo/pull/8|#8 https://myteam.slack.com/archives/C07KTH1T4CQ/p1730339894629249>",
+                "callback_id": "pr-opened-interaction",
+                "footer": "<https://github.com/myorg/myrepo|myorg/myrepo>",
+                "mrkdwn_in": [
+                    "text"
+                ],
+                "actions": [
+                    {
+                        "id": "1",
+                        "name": "comment",
+                        "text": "Comment",
+                        "type": "button",
+                        "value": "{&amp;amp;quot;selectedOrg&amp;amp;quot;:&amp;amp;quot;myorg&amp;amp;quot;,&amp;amp;quot;selectedOrgId&amp;amp;quot;:140364112,&amp;amp;quot;selectedRepo&amp;amp;quot;:&amp;amp;quot;myrepo&amp;amp;quot;,&amp;amp;quot;selectedRepoId&amp;amp;quot;:669978765,&amp;amp;quot;number&amp;amp;quot;:8,&amp;amp;quot;htmlUrl&amp;amp;quot;:&amp;amp;quot;https://github.com/myorg/myrepo/pull/8&amp;amp;quot;,&amp;amp;quot;title&amp;amp;quot;:&amp;amp;quot;https://myteam.slack.com/archives/C07KTH1T4CQ/p1730339894629249&amp;amp;quot;}",
+                        "style": ""
+                    }
+                ]
+            }
+        ],
+        "channel": "C07LRFB3C8M",
+        "event_ts": "1730339959.644979",
+        "channel_type": "channel"
+    },
+    "type": "event_callback",
+    "event_id": "Ev07U5U3EQCV",
+    "event_time": 1730339959,
+    "authorizations": [
+        {
+            "enterprise_id": null,
+            "team_id": "T043DB835ML",
+            "user_id": "U07K4E18KJM",
+            "is_bot": true,
+            "is_enterprise_install": false
+        }
+    ],
+    "is_ext_shared_channel": false
+}
diff --git a/tests/golden/SlackWebhookEvent/link.golden b/tests/golden/SlackWebhookEvent/link.golden
--- a/tests/golden/SlackWebhookEvent/link.golden
+++ b/tests/golden/SlackWebhookEvent/link.golden
@@ -41,6 +41,7 @@
                 , threadTs = Nothing
                 , appId = Nothing
                 , botId = Nothing
+                , attachments = Nothing
                 }
             )
         }
diff --git a/tests/golden/SlackWebhookEvent/messageExample.golden b/tests/golden/SlackWebhookEvent/messageExample.golden
--- a/tests/golden/SlackWebhookEvent/messageExample.golden
+++ b/tests/golden/SlackWebhookEvent/messageExample.golden
@@ -37,6 +37,7 @@
                 , threadTs = Nothing
                 , appId = Nothing
                 , botId = Nothing
+                , attachments = Nothing
                 }
             )
         }
diff --git a/tests/golden/SlackWebhookEvent/messageIm.golden b/tests/golden/SlackWebhookEvent/messageIm.golden
--- a/tests/golden/SlackWebhookEvent/messageIm.golden
+++ b/tests/golden/SlackWebhookEvent/messageIm.golden
@@ -37,6 +37,7 @@
                 , threadTs = Nothing
                 , appId = Nothing
                 , botId = Nothing
+                , attachments = Nothing
                 }
             )
         }
diff --git a/tests/golden/SlackWebhookEvent/message_file_share.golden b/tests/golden/SlackWebhookEvent/message_file_share.golden
--- a/tests/golden/SlackWebhookEvent/message_file_share.golden
+++ b/tests/golden/SlackWebhookEvent/message_file_share.golden
@@ -52,6 +52,7 @@
                 , threadTs = Nothing
                 , appId = Nothing
                 , botId = Nothing
+                , attachments = Nothing
                 }
             )
         }
diff --git a/tests/golden/SlackWebhookEvent/message_file_share_slack_connect.golden b/tests/golden/SlackWebhookEvent/message_file_share_slack_connect.golden
--- a/tests/golden/SlackWebhookEvent/message_file_share_slack_connect.golden
+++ b/tests/golden/SlackWebhookEvent/message_file_share_slack_connect.golden
@@ -27,6 +27,7 @@
                 , threadTs = Nothing
                 , appId = Nothing
                 , botId = Nothing
+                , attachments = Nothing
                 }
             )
         }
diff --git a/tests/golden/SlackWebhookEvent/message_rich_text.golden b/tests/golden/SlackWebhookEvent/message_rich_text.golden
--- a/tests/golden/SlackWebhookEvent/message_rich_text.golden
+++ b/tests/golden/SlackWebhookEvent/message_rich_text.golden
@@ -79,6 +79,7 @@
                 , threadTs = Nothing
                 , appId = Nothing
                 , botId = Nothing
+                , attachments = Nothing
                 }
             )
         }
diff --git a/tests/golden/SlackWebhookEvent/message_subtype_bot_message.golden b/tests/golden/SlackWebhookEvent/message_subtype_bot_message.golden
new file mode 100644
--- /dev/null
+++ b/tests/golden/SlackWebhookEvent/message_subtype_bot_message.golden
@@ -0,0 +1,46 @@
+EventEventCallback
+    ( EventCallback
+        { eventId = EventId
+            { unEventId = "Ev07JQHFTAKH" }
+        , teamId = TeamId
+            { unTeamId = "T043DB835ML" }
+        , eventTime = MkSystemTime
+            { systemSeconds = 1724955010
+            , systemNanoseconds = 0
+            }
+        , event = EventBotMessage
+            ( BotMessageEvent
+                { blocks = Just
+                    [ RichText
+                        { blockId = Just
+                            ( NonEmptyText "nmh" )
+                        , elements =
+                            [ RichTextSectionItemRichText
+                                [ RichItemLink
+                                    ( RichLinkAttrs
+                                        { style = RichStyle
+                                            { rsBold = False
+                                            , rsItalic = False
+                                            }
+                                        , url = "https://myworkspace.slack.com/archives/C07KTH1T4CQ/p1724954997876929"
+                                        , text = Nothing
+                                        }
+                                    )
+                                ]
+                            ]
+                        }
+                    ]
+                , channel = ConversationId
+                    { unConversationId = "C07KH38CR5E" }
+                , text = "<https://myworkspace.slack.com/archives/C07KTH1T4CQ/p1724954997876929>"
+                , channelType = Channel
+                , files = Nothing
+                , ts = "1724955010.440469"
+                , threadTs = Nothing
+                , appId = Just "A1BFDR28J"
+                , botId = "B07JWPS5Y5S"
+                , attachments = Nothing
+                }
+            )
+        }
+    )
diff --git a/tests/golden/SlackWebhookEvent/message_subtype_bot_message.json b/tests/golden/SlackWebhookEvent/message_subtype_bot_message.json
new file mode 100644
--- /dev/null
+++ b/tests/golden/SlackWebhookEvent/message_subtype_bot_message.json
@@ -0,0 +1,53 @@
+{
+    "token": "d90zMGO2eDLrkLHJYcKevn2b",
+    "team_id": "T043DB835ML",
+    "context_team_id": "T043DB835ML",
+    "context_enterprise_id": null,
+    "api_app_id": "A07JRKQPZDH",
+    "event": {
+        "subtype": "bot_message",
+        "text": "<https://myworkspace.slack.com/archives/C07KTH1T4CQ/p1724954997876929>",
+        "username": "Reacji Channeler",
+        "icons": {
+            "emoji": "bulb"
+        },
+        "type": "message",
+        "ts": "1724955010.440469",
+        "bot_id": "B07JWPS5Y5S",
+        "app_id": "A1BFDR28J",
+        "blocks": [
+            {
+                "type": "rich_text",
+                "block_id": "nmh",
+                "elements": [
+                    {
+                        "type": "rich_text_section",
+                        "elements": [
+                            {
+                                "type": "link",
+                                "url": "https://myworkspace.slack.com/archives/C07KTH1T4CQ/p1724954997876929"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ],
+        "channel": "C07KH38CR5E",
+        "event_ts": "1724955010.440469",
+        "channel_type": "channel"
+    },
+    "type": "event_callback",
+    "event_id": "Ev07JQHFTAKH",
+    "event_time": 1724955010,
+    "authorizations": [
+        {
+            "enterprise_id": null,
+            "team_id": "T043DB835ML",
+            "user_id": "U07K4E18KJM",
+            "is_bot": true,
+            "is_enterprise_install": false
+        }
+    ],
+    "is_ext_shared_channel": false,
+    "event_context": "4-eyJldCI6Im1lc3NhZ2UiLCJ0aWQiOiJUMDQzREI4MzVNTCIsImFpZCI6IkEwN0pSS1FQWkRIIiwiY2lkIjoiQzA3S0gzOENSNUUifQ=="
+}
diff --git a/tests/golden/SlackWebhookEvent/non_spec_attachment.golden b/tests/golden/SlackWebhookEvent/non_spec_attachment.golden
new file mode 100644
--- /dev/null
+++ b/tests/golden/SlackWebhookEvent/non_spec_attachment.golden
@@ -0,0 +1,99 @@
+EventEventCallback
+    ( EventCallback
+        { eventId = EventId
+            { unEventId = "Ev07MH6R7FDE" }
+        , teamId = TeamId
+            { unTeamId = "T043DB835ML" }
+        , eventTime = MkSystemTime
+            { systemSeconds = 1725998548
+            , systemNanoseconds = 0
+            }
+        , event = EventMessage
+            ( MessageEvent
+                { blocks = Nothing
+                , channel = ConversationId
+                    { unConversationId = "C07LRFB3C8M" }
+                , text = ""
+                , channelType = Channel
+                , files = Nothing
+                , user = UserId
+                    { unUserId = "U07M725KAD7" }
+                , ts = "1725998548.581159"
+                , threadTs = Nothing
+                , appId = Just "A01BP7R4KNY"
+                , botId = Just "B07LDR01Z63"
+                , attachments = Just
+                    [ MessageAttachment
+                        { decoded = Just
+                            ( DecodedMessageAttachment
+                                { fallback = Nothing
+                                , color = Nothing
+                                , pretext = Nothing
+                                , authorName = Nothing
+                                , authorLink = Nothing
+                                , authorIcon = Nothing
+                                , title = Nothing
+                                , titleLink = Nothing
+                                , text = Nothing
+                                , fields = Nothing
+                                , imageUrl = Nothing
+                                , thumbUrl = Nothing
+                                , footer = Nothing
+                                , footerIcon = Nothing
+                                , ts = Nothing
+                                , isMsgUnfurl = Nothing
+                                , messageBlocks = Nothing
+                                , authorId = Nothing
+                                , channelId = Nothing
+                                , channelTeam = Nothing
+                                , isAppUnfurl = Nothing
+                                , appUnfurlUrl = Nothing
+                                , fromUrl = Nothing
+                                }
+                            )
+                        , raw = Object
+                            ( fromList
+                                [
+                                    ( "any"
+                                    , Object
+                                        ( fromList
+                                            [
+                                                ( "specific"
+                                                , String "format"
+                                                )
+                                            ]
+                                        )
+                                    )
+                                ,
+                                    ( "but"
+                                    , String "It should still parse fine."
+                                    )
+                                ,
+                                    ( "does"
+                                    , String "not"
+                                    )
+                                ,
+                                    ( "follow"
+                                    , Number 0.0
+                                    )
+                                ,
+                                    ( "or"
+                                    , Array
+                                        [ String "spec" ]
+                                    )
+                                ,
+                                    ( "that"
+                                    , String "Slack has ever published."
+                                    )
+                                ,
+                                    ( "this"
+                                    , String "attachments"
+                                    )
+                                ]
+                            )
+                        }
+                    ]
+                }
+            )
+        }
+    )
diff --git a/tests/golden/SlackWebhookEvent/non_spec_attachment.json b/tests/golden/SlackWebhookEvent/non_spec_attachment.json
new file mode 100644
--- /dev/null
+++ b/tests/golden/SlackWebhookEvent/non_spec_attachment.json
@@ -0,0 +1,58 @@
+{
+    "token": "aaaa",
+    "team_id": "T043DB835ML",
+    "context_team_id": "T043DB835ML",
+    "context_enterprise_id": null,
+    "api_app_id": "A07JRKQPZDH",
+    "event": {
+        "user": "U07M725KAD7",
+        "type": "message",
+        "ts": "1725998548.581159",
+        "bot_id": "B07LDR01Z63",
+        "app_id": "A01BP7R4KNY",
+        "text": "",
+        "team": "T043DB835ML",
+        "bot_profile": {
+            "id": "B07LDR01Z63",
+            "deleted": false,
+            "name": "GitHub",
+            "updated": 1725998199,
+            "app_id": "A01BP7R4KNY",
+            "icons": {
+                "image_36": "https://avatars.slack-edge.com/2020-11-25/1527503386626_319578f21381f9641cd8_36.png",
+                "image_48": "https://avatars.slack-edge.com/2020-11-25/1527503386626_319578f21381f9641cd8_48.png",
+                "image_72": "https://avatars.slack-edge.com/2020-11-25/1527503386626_319578f21381f9641cd8_72.png"
+            },
+            "team_id": "T043DB835ML"
+        },
+        "attachments": [
+            {
+                "this": "attachments",
+                "does": "not",
+                "follow": 0,
+                "any": {
+                    "specific": "format"
+                },
+                "or": ["spec"],
+                "that": "Slack has ever published.",
+                "but": "It should still parse fine."
+            }
+        ],
+        "channel": "C07LRFB3C8M",
+        "event_ts": "1725998548.581159",
+        "channel_type": "channel"
+    },
+    "type": "event_callback",
+    "event_id": "Ev07MH6R7FDE",
+    "event_time": 1725998548,
+    "authorizations": [
+        {
+            "enterprise_id": null,
+            "team_id": "T043DB835ML",
+            "user_id": "U07K4E18KJM",
+            "is_bot": true,
+            "is_enterprise_install": false
+        }
+    ],
+    "is_ext_shared_channel": false
+}
diff --git a/tests/golden/SlackWebhookEvent/share_with_message.golden b/tests/golden/SlackWebhookEvent/share_with_message.golden
new file mode 100644
--- /dev/null
+++ b/tests/golden/SlackWebhookEvent/share_with_message.golden
@@ -0,0 +1,253 @@
+EventEventCallback
+    ( EventCallback
+        { eventId = EventId
+            { unEventId = "Ev07K61TELMR" }
+        , teamId = TeamId
+            { unTeamId = "T043DB835ML" }
+        , eventTime = MkSystemTime
+            { systemSeconds = 1724966800
+            , systemNanoseconds = 0
+            }
+        , event = EventMessage
+            ( MessageEvent
+                { blocks = Just
+                    [ RichText
+                        { blockId = Just
+                            ( NonEmptyText "Yyg6K" )
+                        , elements =
+                            [ RichTextSectionItemRichText
+                                [ RichItemText "hello check that out!"
+                                    ( RichStyle
+                                        { rsBold = False
+                                        , rsItalic = False
+                                        }
+                                    )
+                                ]
+                            ]
+                        }
+                    ]
+                , channel = ConversationId
+                    { unConversationId = "C07KHDGQ7K3" }
+                , text = "hello check that out!"
+                , channelType = Channel
+                , files = Nothing
+                , user = UserId
+                    { unUserId = "U05JAA9EN4T" }
+                , ts = "1724966800.923979"
+                , threadTs = Nothing
+                , appId = Nothing
+                , botId = Nothing
+                , attachments = Just
+                    [ MessageAttachment
+                        { decoded = Just
+                            ( DecodedMessageAttachment
+                                { fallback = Just "[August 29th, 2024 2:26 PM] lev: this will be shared with a message"
+                                , color = Just "D0D0D0"
+                                , pretext = Nothing
+                                , authorName = Just "lev"
+                                , authorLink = Just "https://myworkspace.slack.com/team/U05JAA9EN4T"
+                                , authorIcon = Just "https://avatars.slack-edge.com/2023-07-22/5607926127815_66b9d49327ec16a887e5_48.png"
+                                , title = Nothing
+                                , titleLink = Nothing
+                                , text = Just "this will be shared with a message"
+                                , fields = Nothing
+                                , imageUrl = Nothing
+                                , thumbUrl = Nothing
+                                , footer = Just "Slack Conversation"
+                                , footerIcon = Nothing
+                                , ts = Just "1724966776.474889"
+                                , isMsgUnfurl = Just True
+                                , messageBlocks = Just
+                                    [ AttachmentMessageBlock
+                                        { team = TeamId
+                                            { unTeamId = "T043DB835ML" }
+                                        , channel = ConversationId
+                                            { unConversationId = "C07KTH1T4CQ" }
+                                        , ts = "1724966776.474889"
+                                        , message = AttachmentMessageBlockMessage
+                                            { blocks =
+                                                [ RichText
+                                                    { blockId = Just
+                                                        ( NonEmptyText "BXn1o" )
+                                                    , elements =
+                                                        [ RichTextSectionItemRichText
+                                                            [ RichItemText "this will be shared with a message"
+                                                                ( RichStyle
+                                                                    { rsBold = False
+                                                                    , rsItalic = False
+                                                                    }
+                                                                )
+                                                            ]
+                                                        ]
+                                                    }
+                                                ]
+                                            }
+                                        }
+                                    ]
+                                , authorId = Just
+                                    ( UserId
+                                        { unUserId = "U05JAA9EN4T" }
+                                    )
+                                , channelId = Just
+                                    ( ConversationId
+                                        { unConversationId = "C07KTH1T4CQ" }
+                                    )
+                                , channelTeam = Just
+                                    ( TeamId
+                                        { unTeamId = "T043DB835ML" }
+                                    )
+                                , isAppUnfurl = Nothing
+                                , appUnfurlUrl = Nothing
+                                , fromUrl = Just "https://myworkspace.slack.com/archives/C07KTH1T4CQ/p1724966776474889"
+                                }
+                            )
+                        , raw = Object
+                            ( fromList
+                                [
+                                    ( "author_icon"
+                                    , String "https://avatars.slack-edge.com/2023-07-22/5607926127815_66b9d49327ec16a887e5_48.png"
+                                    )
+                                ,
+                                    ( "author_id"
+                                    , String "U05JAA9EN4T"
+                                    )
+                                ,
+                                    ( "author_link"
+                                    , String "https://myworkspace.slack.com/team/U05JAA9EN4T"
+                                    )
+                                ,
+                                    ( "author_name"
+                                    , String "lev"
+                                    )
+                                ,
+                                    ( "author_subname"
+                                    , String "lev"
+                                    )
+                                ,
+                                    ( "channel_id"
+                                    , String "C07KTH1T4CQ"
+                                    )
+                                ,
+                                    ( "channel_team"
+                                    , String "T043DB835ML"
+                                    )
+                                ,
+                                    ( "color"
+                                    , String "D0D0D0"
+                                    )
+                                ,
+                                    ( "fallback"
+                                    , String "[August 29th, 2024 2:26 PM] lev: this will be shared with a message"
+                                    )
+                                ,
+                                    ( "footer"
+                                    , String "Slack Conversation"
+                                    )
+                                ,
+                                    ( "from_url"
+                                    , String "https://myworkspace.slack.com/archives/C07KTH1T4CQ/p1724966776474889"
+                                    )
+                                ,
+                                    ( "is_msg_unfurl"
+                                    , Bool True
+                                    )
+                                ,
+                                    ( "is_share"
+                                    , Bool True
+                                    )
+                                ,
+                                    ( "message_blocks"
+                                    , Array
+                                        [ Object
+                                            ( fromList
+                                                [
+                                                    ( "channel"
+                                                    , String "C07KTH1T4CQ"
+                                                    )
+                                                ,
+                                                    ( "message"
+                                                    , Object
+                                                        ( fromList
+                                                            [
+                                                                ( "blocks"
+                                                                , Array
+                                                                    [ Object
+                                                                        ( fromList
+                                                                            [
+                                                                                ( "block_id"
+                                                                                , String "BXn1o"
+                                                                                )
+                                                                            ,
+                                                                                ( "elements"
+                                                                                , Array
+                                                                                    [ Object
+                                                                                        ( fromList
+                                                                                            [
+                                                                                                ( "elements"
+                                                                                                , Array
+                                                                                                    [ Object
+                                                                                                        ( fromList
+                                                                                                            [
+                                                                                                                ( "text"
+                                                                                                                , String "this will be shared with a message"
+                                                                                                                )
+                                                                                                            ,
+                                                                                                                ( "type"
+                                                                                                                , String "text"
+                                                                                                                )
+                                                                                                            ]
+                                                                                                        )
+                                                                                                    ]
+                                                                                                )
+                                                                                            ,
+                                                                                                ( "type"
+                                                                                                , String "rich_text_section"
+                                                                                                )
+                                                                                            ]
+                                                                                        )
+                                                                                    ]
+                                                                                )
+                                                                            ,
+                                                                                ( "type"
+                                                                                , String "rich_text"
+                                                                                )
+                                                                            ]
+                                                                        )
+                                                                    ]
+                                                                )
+                                                            ]
+                                                        )
+                                                    )
+                                                ,
+                                                    ( "team"
+                                                    , String "T043DB835ML"
+                                                    )
+                                                ,
+                                                    ( "ts"
+                                                    , String "1724966776.474889"
+                                                    )
+                                                ]
+                                            )
+                                        ]
+                                    )
+                                ,
+                                    ( "mrkdwn_in"
+                                    , Array
+                                        [ String "text" ]
+                                    )
+                                ,
+                                    ( "text"
+                                    , String "this will be shared with a message"
+                                    )
+                                ,
+                                    ( "ts"
+                                    , String "1724966776.474889"
+                                    )
+                                ]
+                            )
+                        }
+                    ]
+                }
+            )
+        }
+    )
diff --git a/tests/golden/SlackWebhookEvent/share_with_message.json b/tests/golden/SlackWebhookEvent/share_with_message.json
new file mode 100644
--- /dev/null
+++ b/tests/golden/SlackWebhookEvent/share_with_message.json
@@ -0,0 +1,95 @@
+{
+    "token": "d90zMGO2eDLrkLHJYcKevn2b",
+    "team_id": "T043DB835ML",
+    "context_team_id": "T043DB835ML",
+    "context_enterprise_id": null,
+    "api_app_id": "A07JRKQPZDH",
+    "event": {
+        "user": "U05JAA9EN4T",
+        "type": "message",
+        "ts": "1724966800.923979",
+        "text": "hello check that out!",
+        "team": "T043DB835ML",
+        "attachments": [
+            {
+                "ts": "1724966776.474889",
+                "author_id": "U05JAA9EN4T",
+                "channel_id": "C07KTH1T4CQ",
+                "channel_team": "T043DB835ML",
+                "is_msg_unfurl": true,
+                "message_blocks": [
+                    {
+                        "team": "T043DB835ML",
+                        "channel": "C07KTH1T4CQ",
+                        "ts": "1724966776.474889",
+                        "message": {
+                            "blocks": [
+                                {
+                                    "type": "rich_text",
+                                    "block_id": "BXn1o",
+                                    "elements": [
+                                        {
+                                            "type": "rich_text_section",
+                                            "elements": [
+                                                {
+                                                    "type": "text",
+                                                    "text": "this will be shared with a message"
+                                                }
+                                            ]
+                                        }
+                                    ]
+                                }
+                            ]
+                        }
+                    }
+                ],
+                "color": "D0D0D0",
+                "from_url": "https://myworkspace.slack.com/archives/C07KTH1T4CQ/p1724966776474889",
+                "is_share": true,
+                "fallback": "[August 29th, 2024 2:26 PM] lev: this will be shared with a message",
+                "text": "this will be shared with a message",
+                "author_name": "lev",
+                "author_link": "https://myworkspace.slack.com/team/U05JAA9EN4T",
+                "author_icon": "https://avatars.slack-edge.com/2023-07-22/5607926127815_66b9d49327ec16a887e5_48.png",
+                "author_subname": "lev",
+                "mrkdwn_in": [
+                    "text"
+                ],
+                "footer": "Slack Conversation"
+            }
+        ],
+        "blocks": [
+            {
+                "type": "rich_text",
+                "block_id": "Yyg6K",
+                "elements": [
+                    {
+                        "type": "rich_text_section",
+                        "elements": [
+                            {
+                                "type": "text",
+                                "text": "hello check that out!"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ],
+        "channel": "C07KHDGQ7K3",
+        "event_ts": "1724966800.923979",
+        "channel_type": "channel"
+    },
+    "type": "event_callback",
+    "event_id": "Ev07K61TELMR",
+    "event_time": 1724966800,
+    "authorizations": [
+        {
+            "enterprise_id": null,
+            "team_id": "T043DB835ML",
+            "user_id": "U07K4E18KJM",
+            "is_bot": true,
+            "is_enterprise_install": false
+        }
+    ],
+    "is_ext_shared_channel": false
+}
diff --git a/tests/golden/SlackWebhookEvent/share_without_message.golden b/tests/golden/SlackWebhookEvent/share_without_message.golden
--- a/tests/golden/SlackWebhookEvent/share_without_message.golden
+++ b/tests/golden/SlackWebhookEvent/share_without_message.golden
@@ -22,6 +22,220 @@
                 , threadTs = Nothing
                 , appId = Nothing
                 , botId = Nothing
+                , attachments = Just
+                    [ MessageAttachment
+                        { decoded = Just
+                            ( DecodedMessageAttachment
+                                { fallback = Just "[October 12th, 2022 4:04 PM] jadel: blahblahblahblahblah"
+                                , color = Just "D0D0D0"
+                                , pretext = Nothing
+                                , authorName = Just "jadel"
+                                , authorLink = Just "https://jadeapptesting.slack.com/team/U043H11ES4V"
+                                , authorIcon = Just "https://secure.gravatar.com/avatar/dcd5bc53dcfaca62ddc3f5726d07ba13.jpg?s=48&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0019-48.png"
+                                , title = Nothing
+                                , titleLink = Nothing
+                                , text = Just "blahblahblahblahblah"
+                                , fields = Nothing
+                                , imageUrl = Nothing
+                                , thumbUrl = Nothing
+                                , footer = Just "Posted in #testing-slack-app"
+                                , footerIcon = Nothing
+                                , ts = Just "1665615886.364019"
+                                , isMsgUnfurl = Just True
+                                , messageBlocks = Just
+                                    [ AttachmentMessageBlock
+                                        { team = TeamId
+                                            { unTeamId = "T043DB835ML" }
+                                        , channel = ConversationId
+                                            { unConversationId = "C043KSKGJUB" }
+                                        , ts = "1665615886.364019"
+                                        , message = AttachmentMessageBlockMessage
+                                            { blocks =
+                                                [ RichText
+                                                    { blockId = Just
+                                                        ( NonEmptyText "TNHa4" )
+                                                    , elements =
+                                                        [ RichTextSectionItemRichText
+                                                            [ RichItemText "blahblahblahblahblah"
+                                                                ( RichStyle
+                                                                    { rsBold = False
+                                                                    , rsItalic = False
+                                                                    }
+                                                                )
+                                                            ]
+                                                        ]
+                                                    }
+                                                ]
+                                            }
+                                        }
+                                    ]
+                                , authorId = Just
+                                    ( UserId
+                                        { unUserId = "U043H11ES4V" }
+                                    )
+                                , channelId = Just
+                                    ( ConversationId
+                                        { unConversationId = "C043KSKGJUB" }
+                                    )
+                                , channelTeam = Just
+                                    ( TeamId
+                                        { unTeamId = "T043DB835ML" }
+                                    )
+                                , isAppUnfurl = Nothing
+                                , appUnfurlUrl = Nothing
+                                , fromUrl = Just "https://jadeapptesting.slack.com/archives/C043KSKGJUB/p1665615886364019"
+                                }
+                            )
+                        , raw = Object
+                            ( fromList
+                                [
+                                    ( "author_icon"
+                                    , String "https://secure.gravatar.com/avatar/dcd5bc53dcfaca62ddc3f5726d07ba13.jpg?s=48&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0019-48.png"
+                                    )
+                                ,
+                                    ( "author_id"
+                                    , String "U043H11ES4V"
+                                    )
+                                ,
+                                    ( "author_link"
+                                    , String "https://jadeapptesting.slack.com/team/U043H11ES4V"
+                                    )
+                                ,
+                                    ( "author_name"
+                                    , String "jadel"
+                                    )
+                                ,
+                                    ( "author_subname"
+                                    , String "jadel"
+                                    )
+                                ,
+                                    ( "channel_id"
+                                    , String "C043KSKGJUB"
+                                    )
+                                ,
+                                    ( "channel_name"
+                                    , String "testing-slack-app"
+                                    )
+                                ,
+                                    ( "channel_team"
+                                    , String "T043DB835ML"
+                                    )
+                                ,
+                                    ( "color"
+                                    , String "D0D0D0"
+                                    )
+                                ,
+                                    ( "fallback"
+                                    , String "[October 12th, 2022 4:04 PM] jadel: blahblahblahblahblah"
+                                    )
+                                ,
+                                    ( "footer"
+                                    , String "Posted in #testing-slack-app"
+                                    )
+                                ,
+                                    ( "from_url"
+                                    , String "https://jadeapptesting.slack.com/archives/C043KSKGJUB/p1665615886364019"
+                                    )
+                                ,
+                                    ( "is_msg_unfurl"
+                                    , Bool True
+                                    )
+                                ,
+                                    ( "is_share"
+                                    , Bool True
+                                    )
+                                ,
+                                    ( "message_blocks"
+                                    , Array
+                                        [ Object
+                                            ( fromList
+                                                [
+                                                    ( "channel"
+                                                    , String "C043KSKGJUB"
+                                                    )
+                                                ,
+                                                    ( "message"
+                                                    , Object
+                                                        ( fromList
+                                                            [
+                                                                ( "blocks"
+                                                                , Array
+                                                                    [ Object
+                                                                        ( fromList
+                                                                            [
+                                                                                ( "block_id"
+                                                                                , String "TNHa4"
+                                                                                )
+                                                                            ,
+                                                                                ( "elements"
+                                                                                , Array
+                                                                                    [ Object
+                                                                                        ( fromList
+                                                                                            [
+                                                                                                ( "elements"
+                                                                                                , Array
+                                                                                                    [ Object
+                                                                                                        ( fromList
+                                                                                                            [
+                                                                                                                ( "text"
+                                                                                                                , String "blahblahblahblahblah"
+                                                                                                                )
+                                                                                                            ,
+                                                                                                                ( "type"
+                                                                                                                , String "text"
+                                                                                                                )
+                                                                                                            ]
+                                                                                                        )
+                                                                                                    ]
+                                                                                                )
+                                                                                            ,
+                                                                                                ( "type"
+                                                                                                , String "rich_text_section"
+                                                                                                )
+                                                                                            ]
+                                                                                        )
+                                                                                    ]
+                                                                                )
+                                                                            ,
+                                                                                ( "type"
+                                                                                , String "rich_text"
+                                                                                )
+                                                                            ]
+                                                                        )
+                                                                    ]
+                                                                )
+                                                            ]
+                                                        )
+                                                    )
+                                                ,
+                                                    ( "team"
+                                                    , String "T043DB835ML"
+                                                    )
+                                                ,
+                                                    ( "ts"
+                                                    , String "1665615886.364019"
+                                                    )
+                                                ]
+                                            )
+                                        ]
+                                    )
+                                ,
+                                    ( "mrkdwn_in"
+                                    , Array
+                                        [ String "text" ]
+                                    )
+                                ,
+                                    ( "text"
+                                    , String "blahblahblahblahblah"
+                                    )
+                                ,
+                                    ( "ts"
+                                    , String "1665615886.364019"
+                                    )
+                                ]
+                            )
+                        }
+                    ]
                 }
             )
         }
diff --git a/tests/golden/SlackWebhookEvent/slackbotIm.golden b/tests/golden/SlackWebhookEvent/slackbotIm.golden
--- a/tests/golden/SlackWebhookEvent/slackbotIm.golden
+++ b/tests/golden/SlackWebhookEvent/slackbotIm.golden
@@ -46,6 +46,7 @@
                 , threadTs = Nothing
                 , appId = Nothing
                 , botId = Nothing
+                , attachments = Nothing
                 }
             )
         }
