diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -4,3 +4,90 @@
 [![Hackage](https://badgen.net/hackage/v/patrol)](https://hackage.haskell.org/package/patrol)
 
 Patrol is a Sentry SDK for Haskell.
+
+## Usage
+
+### Basic exception reporting
+
+The simplest way to report an exception is with `captureException`. It reads the
+DSN from the `SENTRY_DSN` environment variable.
+
+```haskell
+import qualified Patrol
+
+main :: IO ()
+main = do
+  result <- doSomething
+  case result of
+    Left err -> do
+      _ <- Patrol.captureException err
+      pure ()
+    Right val -> use val
+```
+
+### Customizing the event
+
+Use `captureExceptionWith` to add tags, set the environment, attach user info, or
+otherwise modify the event before it is sent.
+
+```haskell
+import qualified Data.Map as Map
+import qualified Data.Text as Text
+import qualified Patrol
+import qualified Patrol.Type.Dsn as Dsn
+import qualified Patrol.Type.Event as Event
+import qualified Patrol.Type.Level as Level
+import qualified Patrol.Type.User as User
+
+reportException :: Dsn.Dsn -> SomeException -> IO ()
+reportException dsn err = do
+  _ <- Patrol.captureExceptionWith modifyEvent dsn err
+  pure ()
+  where
+    modifyEvent :: Event.Event -> IO Event.Event
+    modifyEvent event = pure event
+      { Event.tags = Map.fromList
+          [ (Text.pack "component", Text.pack "api")
+          ]
+      , Event.level = Just Level.Warning
+      , Event.user = Just User.empty
+          { User.id = Text.pack "user-123"
+          , User.email = Text.pack "user@example.com"
+          }
+      , Event.environment = Text.pack "staging"
+      }
+```
+
+### Warp middleware
+
+Here is an example of a [Warp](https://hackage.haskell.org/package/warp)
+middleware that reports non-success HTTP responses to Sentry.
+
+```haskell
+import qualified Data.Map as Map
+import qualified Data.Text as Text
+import qualified Data.Text.Encoding as Text
+import qualified Network.HTTP.Types as Http
+import qualified Network.Wai as Wai
+import qualified Patrol
+import qualified Patrol.Type.Dsn as Dsn
+import qualified Patrol.Type.Event as Event
+
+sentryMiddleware :: Dsn.Dsn -> Wai.Middleware
+sentryMiddleware dsn app request respond =
+  app request $ \response -> do
+    let status = Wai.responseStatus response
+    Control.Monad.when (Http.statusCode status >= 500) $ do
+      let err = userError $ "HTTP " <> show (Http.statusCode status)
+      _ <- Patrol.captureExceptionWith (modifyEvent request status) dsn err
+      pure ()
+    respond response
+  where
+    modifyEvent :: Wai.Request -> Http.Status -> Event.Event -> IO Event.Event
+    modifyEvent request status event = pure event
+      { Event.tags = Map.fromList
+          [ (Text.pack "path", Text.decodeUtf8 (Wai.rawPathInfo request))
+          , (Text.pack "status_code", Text.pack (show (Http.statusCode status)))
+          ]
+      }
+```
diff --git a/patrol.cabal b/patrol.cabal
--- a/patrol.cabal
+++ b/patrol.cabal
@@ -1,6 +1,6 @@
 cabal-version: 2.2
 name: patrol
-version: 1.2.0.4
+version: 1.2.0.5
 synopsis: Sentry SDK
 description: Patrol is a Sentry SDK.
 build-type: Simple
@@ -51,7 +51,7 @@
   import: library
   autogen-modules: Paths_patrol
   build-depends:
-    aeson ^>=2.1.2.1 || ^>=2.2.2,
+    aeson ^>=2.1.2 || ^>=2.2.2 || ^>=2.3.0,
     bytestring ^>=0.12.0.2,
     case-insensitive ^>=1.2.1,
     containers ^>=0.7 || ^>=0.8,
@@ -75,8 +75,8 @@
     Patrol.Type.AppContext
     Patrol.Type.AppleDebugImage
     Patrol.Type.Breadcrumb
-    Patrol.Type.BreadcrumbType
     Patrol.Type.Breadcrumbs
+    Patrol.Type.BreadcrumbType
     Patrol.Type.BrowserContext
     Patrol.Type.CError
     Patrol.Type.ClientSdkInfo
@@ -155,8 +155,8 @@
     Patrol.Type.AppContextSpec
     Patrol.Type.AppleDebugImageSpec
     Patrol.Type.BreadcrumbSpec
-    Patrol.Type.BreadcrumbTypeSpec
     Patrol.Type.BreadcrumbsSpec
+    Patrol.Type.BreadcrumbTypeSpec
     Patrol.Type.BrowserContextSpec
     Patrol.Type.CErrorSpec
     Patrol.Type.ClientSdkInfoSpec
