diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,5 @@
+# Revision history for ebird-client
+
+## 0.1.0.0 -- 2023-07-30
+
+* First version. Released on an unsuspecting world.
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2023 Finley McIlwaine
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/ebird-client.cabal b/ebird-client.cabal
new file mode 100644
--- /dev/null
+++ b/ebird-client.cabal
@@ -0,0 +1,69 @@
+cabal-version:      3.0
+name:               ebird-client
+version:            0.1.0.0
+synopsis:
+    Client functions for querying the eBird API.
+description:
+    [eBird](https://ebird.org/home) is a massive collection of ornithological
+    science projects developed by the
+    [Cornell Lab of Ornithology](https://www.birds.cornell.edu/home/). The
+    [eBird API](https://documenter.getpostman.com/view/664302/S1ENwy59)
+    offers programmatic access to the incredible dataset backing these
+    projects.
+
+    This library contains functions for retrieving data from the
+    [eBird API](https://documenter.getpostman.com/view/664302/S1ENwy59), as
+    defined in the
+    [ebird-api](https://hackage.haskell.org/package/ebird-api) library.
+
+    If you'd like to run the queries defined in this library directly on your
+    command line, checkout out the
+    [ebird-cli](https://hackage.haskell.org/package/ebird-cli).
+license:            MIT
+license-file:       LICENSE
+author:             Finley McIlwaine
+maintainer:         finleymcilwaine@gmail.com
+copyright:          2023 Finley McIlwaine
+category:           Web
+build-type:         Simple
+extra-doc-files:    CHANGELOG.md
+bug-reports:        https://github.com/FinleyMcIlwaine/ebird-haskell/issues
+homepage:           https://github.com/FinleyMcIlwaine/ebird-haskell
+
+tested-with:
+    GHC == 8.10.7
+  , GHC == 9.2.7
+  , GHC == 9.4.5
+  , GHC == 9.6.2
+
+common common
+    build-depends:
+        base >= 4.13.3.0 && < 4.19
+    default-extensions:
+      ImportQualifiedPost
+      LambdaCase
+      OverloadedStrings
+      RecordWildCards
+    default-language: Haskell2010
+
+library
+    import: common
+    exposed-modules:
+        Data.EBird.Client
+        Data.EBird.Client.Generated
+        Data.EBird.Client.Hotspots
+        Data.EBird.Client.Observations
+        Data.EBird.Client.Product
+        Data.EBird.Client.Regions
+        Data.EBird.Client.Taxonomy
+    build-depends:
+      , ebird-api >= 0.1.0.0 && < 0.2
+
+      , data-default    >= 0.7.1.1 && < 0.8
+      , http-client-tls >= 0.3.5.3 && < 0.4
+      , optics          >= 0.4     && < 0.5
+      , servant         >= 0.18.3  && < 0.21
+      , servant-client  >= 0.18.3  && < 0.21
+      , text            >= 1.2.4.1 && < 2.1
+    hs-source-dirs:
+        src
diff --git a/src/Data/EBird/Client.hs b/src/Data/EBird/Client.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/EBird/Client.hs
@@ -0,0 +1,83 @@
+{-# LANGUAGE DataKinds        #-}
+{-# LANGUAGE TypeApplications #-}
+{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-}
+{-# HLINT ignore "Eta reduce" #-}
+
+-- |
+-- Module      : Data.EBird.Client
+-- Copyright   : (c) 2023 Finley McIlwaine
+-- License     : MIT (see LICENSE)
+--
+-- Maintainer  : Finley McIlwaine <finleymcilwaine@gmail.com>
+--
+-- Functions that support querying the official [eBird
+-- API](https://documenter.getpostman.com/view/664302/S1ENwy59) as defined in
+-- the [ebird-api](https://hackage.haskell.org/package/ebird-api) library.
+
+module Data.EBird.Client (
+    -- * Execute client functions
+    askEBird
+
+    -- * eBird API client functions
+    -- ** Observations queries
+  , recentObservations
+  , recentNotableObservations
+  , recentNearbyObservations
+  , recentNearbySpeciesObservations
+  , recentNearestSpeciesObservations
+  , recentNearbyNotableObservations
+  , historicalObservations
+
+    -- ** Product queries
+  , recentChecklists
+  , top100
+  , checklistFeed
+  , regionalStatistics
+  , speciesList
+  , viewChecklist
+
+    -- ** Hotspot queries
+  , regionHotspots
+  , nearbyHotspots
+  , hotspotInfo
+
+    -- ** Taxonomy queries
+  , taxonomy
+  , taxonomicForms
+  , taxaLocaleCodes
+  , taxonomyVersions
+  , taxonomicGroups
+
+    -- ** Region queries
+  , regionInfo
+  , subRegionList
+  , adjacentRegions
+
+    -- * Less convenient, generated queries
+  , module Data.EBird.Client.Generated
+
+    -- * Convenient re-exports
+  , module Data.EBird.API
+  , ClientError
+  ) where
+
+import Network.HTTP.Client.TLS
+import Servant.Client
+
+import Data.EBird.API
+import Data.EBird.Client.Generated
+import Data.EBird.Client.Hotspots
+import Data.EBird.Client.Observations
+import Data.EBird.Client.Product
+import Data.EBird.Client.Regions
+import Data.EBird.Client.Taxonomy
+
+-- | Send a request to the official eBird API.
+askEBird :: ClientM a -> IO (Either ClientError a)
+askEBird question = do
+    manager' <- newTlsManager
+    runClientM question (mkClientEnv manager' ebirdHQ)
+  where
+    -- Home of the official eBird API
+    ebirdHQ :: BaseUrl
+    ebirdHQ = BaseUrl Https "api.ebird.org" 443 ""
diff --git a/src/Data/EBird/Client/Generated.hs b/src/Data/EBird/Client/Generated.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/EBird/Client/Generated.hs
@@ -0,0 +1,764 @@
+{-# LANGUAGE DataKinds        #-}
+{-# LANGUAGE TypeApplications #-}
+
+{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-}
+{-# HLINT ignore "Eta reduce" #-}
+
+-- |
+-- Module      : Data.EBird.Client.Generated
+-- Copyright   : (c) 2023 Finley McIlwaine
+-- License     : MIT (see LICENSE)
+--
+-- Maintainer  : Finley McIlwaine <finleymcilwaine@gmail.com>
+--
+-- Client functions generated using
+-- [servant-client](https://hackage.haskell.org/package/servant-client). The
+-- queries here match exactly the schemas defined in
+-- [ebird-api](https://hackage.haskell.org/package/ebird-api), and are therefore
+-- potentially a bit more clunky to use. See the wrappers in 'Data.EBird.Client' for
+-- more convenient options.
+
+module Data.EBird.Client.Generated
+  ( -- * Generated eBird API client functions
+    --
+    -- | Generated directly from the definition of the API in
+    -- [ebird-api](https://hackage.haskell.org/package/ebird-api).
+
+    -- ** Observations queries
+    recentObservations_
+  , recentNotableObservations_
+  , recentSpeciesObservations_
+  , recentNearbyObservations_
+  , recentNearbySpeciesObservations_
+  , recentNearestSpeciesObservations_
+  , recentNearbyNotableObservations_
+  , historicalObservations_
+
+    -- ** Product queries
+  , recentChecklists_
+  , top100_
+  , checklistFeed_
+  , regionalStatistics_
+  , speciesList_
+  , viewChecklist_
+
+    -- ** Hotspot queries
+  , regionHotspots_
+  , nearbyHotspots_
+  , hotspotInfo_
+
+    -- ** Taxonomy queries
+  , taxonomy_
+  , taxonomicForms_
+  , taxaLocaleCodes_
+  , taxonomyVersions_
+  , taxonomicGroups_
+
+    -- ** Region queries
+  , regionInfo_
+  , subRegionList_
+  , adjacentRegions_
+  ) where
+
+
+import Data.Text (Text)
+import Data.Proxy
+import Servant.API.Alternative
+import Servant.Client
+
+import Data.EBird.API
+
+-------------------------------------------------------------------------------
+-- Observation APIs
+-------------------------------------------------------------------------------
+
+-- | Get a list of recent observations within a region. Results only include the
+-- most recent observation for each species in the region.
+--
+-- See the [eBird API documentation for the corresponding
+-- endpoint](https://documenter.getpostman.com/view/664302/S1ENwy59#3d2a17c1-2129-475c-b4c8-7d362d6000cd).
+recentObservations_
+  :: Text
+  -- ^ eBird API key
+  -> RegionCode
+  -- ^ Region(s) to get observations from
+  -> Maybe Integer
+  -- ^ How many days back to look for observations
+  --
+  -- /1 - 30, default: 14/
+  -> Maybe TaxonomyCategories
+  -- ^ Only include observations in these taxonomy categories
+  --
+  -- /default: all categories/
+  -> Maybe Bool
+  -- ^ Only get observations from hotspots
+  --
+  -- /default: 'False'/
+  -> Maybe Bool
+  -- ^ Include observations which have not been reviewed
+  --
+  -- /default: 'False'/
+  -> Maybe Integer
+  -- ^ Maximum number of observations to get
+  --
+  -- /1 - 10000, default: all/
+  -> Maybe RegionCode
+  -- ^ Up to 10 extra regions to get observations from
+  --
+  -- /default: none/
+  -> Maybe SPPLocale
+  -- ^ Return observations with common names in this locale
+  --
+  -- /default: 'En'/
+  -> ClientM [Observation 'Simple]
+
+-- | Get a list of recent notable observations within a region. Results only
+-- include the most recent observation for each species in the region.
+--
+-- See the [eBird API documentation for the corresponding
+-- endpoint](https://documenter.getpostman.com/view/664302/S1ENwy59#397b9b8c-4ab9-4136-baae-3ffa4e5b26e4).
+recentNotableObservations_
+  :: Text
+  -- ^ eBird API key
+  -> RegionCode
+  -- ^ Region(s) to get observations from
+  -> Maybe Integer
+  -- ^ How many days back to look for observations
+  --
+  -- /1 - 30, default: 14/
+  -> Maybe DetailLevel
+  -- ^ Detail level for the resulting observations
+  --
+  -- /default: 'Simple'/
+  -> Maybe Bool
+  -- ^ Only get observations from hotspots
+  --
+  -- /default: 'False'/
+  -> Maybe Integer
+  -- ^ Maximum number of observations to get
+  --
+  -- /1 - 10000, default: all/
+  -> Maybe RegionCode
+  -- ^ Up to 10 extra regions to get observations from
+  --
+  -- /default: none/
+  -> Maybe SPPLocale
+  -- ^ Return observations with common names in this locale
+  --
+  -- /default: 'En'/
+  -> ClientM [SomeObservation]
+
+-- | Get a list of recent observations of a specific species within a region.
+--
+-- See the [eBird API documentation for the corresponding
+-- endpoint](https://documenter.getpostman.com/view/664302/S1ENwy59#755ce9ab-dc27-4cfc-953f-c69fb0f282d9).
+recentSpeciesObservations_
+  :: Text
+  -- ^ eBird API key
+  -> RegionCode
+  -- ^ Region(s) to get observations from
+  -> SpeciesCode
+  -- ^ Species to get observations of (e.g. "barswa" for Barn Swallow)
+  -> Maybe Integer
+  -- ^ How many days back to look for observations
+  --
+  -- /1 - 30, default: 14/
+  -> Maybe Bool
+  -- ^ Only get observations from hotspots
+  --
+  -- /default: 'False'/
+  -> Maybe Bool
+  -- ^ Include observations which have not been reviewed
+  --
+  -- /default: 'False'/
+  -> Maybe Integer
+  -- ^ Maximum number of observations to get
+  --
+  -- /1 - 10000, default: all/
+  -> Maybe RegionCode
+  -- ^ Up to 10 extra regions to get observations from
+  --
+  -- /default: none/
+  -> Maybe SPPLocale
+  -- ^ Return observations with common names in this locale
+  --
+  -- /default: 'En'/
+  -> ClientM [Observation 'Simple]
+
+-- | Get a list of recent observations within some radius of some
+-- latitude/longitude.
+--
+-- See the [eBird API documentation for the corresponding
+-- endpoint](https://documenter.getpostman.com/view/664302/S1ENwy59#62b5ffb3-006e-4e8a-8e50-21d90d036edc).
+recentNearbyObservations_
+  :: Text
+  -- ^ eBird API key
+  -> Double
+  -- ^ Latitude of the location to get observations near
+  -> Double
+  -- ^ Longitude of the location to get observations near
+  -> Maybe Integer
+  -- ^ Search radius from the given latitude/longitude in kilometers
+  --
+  -- /0 - 50, default: 25/
+  -> Maybe Integer
+  -- ^ How many days back to look for observations
+  --
+  -- /1 - 30, default: 14/
+  -> Maybe TaxonomyCategories
+  -- ^ Only include observations in these taxonomy categories
+  --
+  -- /default: all/
+  -> Maybe Bool
+  -- ^ Only get observations from hotspots
+  --
+  -- /default: 'False'/
+  -> Maybe Bool
+  -- ^ Include observations which have not been reviewed
+  --
+  -- /default: 'False'/
+  -> Maybe Integer
+  -- ^ Maximum number of observations to get
+  --
+  -- /1 - 10000, default: all/
+  -> Maybe SortObservationsBy
+  -- ^ Sort observations by taxonomy ('SortObservationsBySpecies') or by date
+  -- ('SortObservationsByDate', most recent first)
+  --
+  -- /default: 'SortObservationsByDate'/
+  -> Maybe SPPLocale
+  -- ^ Return observations with common names in this locale
+  --
+  -- /default: 'En'/
+  -> ClientM [Observation 'Simple]
+
+-- | Get a list of recent observations of a species within some radius of some
+-- latitude/longitude.
+--
+-- See the [eBird API documentation for the corresponding
+-- endpoint](https://documenter.getpostman.com/view/664302/S1ENwy59#20fb2c3b-ee7f-49ae-a912-9c3f16a40397).
+recentNearbySpeciesObservations_
+  :: Text
+  -- ^ eBird API key
+  -> SpeciesCode
+  -- ^ Species to get observations of (e.g. "bohwax" for Bohemian Waxwing)
+  -> Double
+  -- ^ Latitude of the location to get observations near
+  -> Double
+  -- ^ Longitude of the location to get observations near
+  -> Maybe Integer
+  -- ^ Search radius from the given latitude/longitude in kilometers
+  --
+  -- /0 - 50, default: 25/
+  -> Maybe Integer
+  -- ^ How many days back to look for observations
+  --
+  -- /1 - 30, default: 14/
+  -> Maybe TaxonomyCategories
+  -- ^ Only include observations in these taxonomy categories
+  --
+  -- /default: all/
+  -> Maybe Bool
+  -- ^ Only get observations from hotspots
+  --
+  -- /default: 'False'/
+  -> Maybe Bool
+  -- ^ Include observations which have not been reviewed
+  --
+  -- /default: 'False'/
+  -> Maybe Integer
+  -- ^ Maximum number of observations to get
+  --
+  -- /1 - 10000, default: all/
+  -> Maybe SortObservationsBy
+  -- ^ Sort observations by taxonomy ('SortObservationsBySpecies') or by date
+  -- ('SortObservationsByDate', most recent first)
+  --
+  -- /default: 'SortObservationsByDate'/
+  -> Maybe SPPLocale
+  -- ^ Return observations with common names in this locale
+  --
+  -- /default: 'En'/
+  -> ClientM [Observation 'Simple]
+
+-- | Get a list of recent observations of some species nearest to some
+-- latitude/longitude.
+--
+-- See the [eBird API documentation for the corresponding
+-- endpoint](https://documenter.getpostman.com/view/664302/S1ENwy59#6bded97f-9997-477f-ab2f-94f254954ccb).
+recentNearestSpeciesObservations_
+  :: Text
+  -- ^ eBird API key
+  -> SpeciesCode
+  -- ^ Species to get observations of
+  -> Double
+  -- ^ Latitude of the location to get observations near
+  -> Double
+  -- ^ Longitude of the location to get observations near
+  -> Maybe Integer
+  -- ^ Search radius from the given latitude/longitude in kilometers
+  --
+  -- /0 - 50, default: 25/
+  -> Maybe Integer
+  -- ^ How many days back to look for observations
+  --
+  -- /0 - 30, default: 14/
+  -> Maybe Bool
+  -- ^ Only get observations from hotspots
+  --
+  -- /default: 'False'/
+  -> Maybe Bool
+  -- ^ Include observations which have not been reviewed
+  --
+  -- /default: 'False'/
+  -> Maybe Integer
+  -- ^ Maximum number of observations to get
+  --
+  -- /1 - 10000, default: all/
+  -> Maybe SPPLocale
+  -- ^ Return observations with common names in this locale
+  --
+  -- /default: 'En'/
+  -> ClientM [Observation 'Simple]
+
+-- | Get a list of recent /notable/ observations of some near some
+-- latitude/longitude.
+--
+-- See the [eBird API documentation for the corresponding
+-- endpoint](https://documenter.getpostman.com/view/664302/S1ENwy59#caa348bb-71f6-471c-b203-9e1643377cbc).
+recentNearbyNotableObservations_
+  :: Text
+  -- ^ eBird API key
+  -> Double
+  -- ^ Latitude of the location to get observations near
+  -> Double
+  -- ^ Longitude of the location to get observations near
+  -> Maybe Integer
+  -- ^ Search radius from the given latitude/longitude in kilometers
+  --
+  -- /0 - 50, default: 25/
+  -> Maybe DetailLevel
+  -- ^ Detail level for the resulting observations
+  --
+  -- /default: 'Simple'/
+  -> Maybe Integer
+  -- ^ How many days back to look for observations
+  --
+  -- /0 - 30, default: 14/
+  -> Maybe Bool
+  -- ^ Only get observations from hotspots
+  --
+  -- /default: 'False'/
+  -> Maybe Integer
+  -- ^ Maximum number of observations to get
+  --
+  -- /1 - 10000, default: all/
+  -> Maybe SPPLocale
+  -- ^ Return observations with common names in this locale
+  --
+  -- /default: 'En'/
+  -> ClientM [SomeObservation]
+
+-- | Get a list of observations for each species seen on a specific date. The
+-- specific observations returned are determined by the 'SelectObservation'
+-- parameter - first observation of the species ('SelectFirstObservation') or
+-- last observation ('SelectLastObservation', default).
+--
+-- See the [eBird API documentation for the corresponding
+-- endpoint](https://documenter.getpostman.com/view/664302/S1ENwy59#2d8c6ee8-c435-4e91-9f66-6d3eeb09edd2).
+historicalObservations_
+  :: Text
+  -- ^ eBird API key
+  -> RegionCode
+  -- ^ Region(s) to get observation from
+  -> Integer
+  -- ^ Year, from 1800 to present
+  -> Integer
+  -- ^ Month (1 - 12)
+  -> Integer
+  -- ^ Day in the month
+  -> Maybe TaxonomyCategories
+  -- ^ Only include observations in these taxonomy categories
+  --
+  -- /default: all/
+  -> Maybe DetailLevel
+  -- ^ Detail level for the resulting observations
+  --
+  -- /default: 'Simple'/
+  -> Maybe Bool
+  -- ^ Only get observations from hotspots
+  --
+  -- /default: 'False'/
+  -> Maybe Bool
+  -- ^ Include observations which have not been reviewed
+  --
+  -- /default: 'False'/
+  -> Maybe Integer
+  -- ^ Maximum number of observations to get
+  --
+  -- /1 - 10000, default: all/
+  -> Maybe SelectObservation
+  -- ^ Whether to display the first or last observation of a species on the
+  -- date, in the case that there are multiple observations of the same species
+  -- on the date
+  --
+  -- /default: 'SelectLastObservation'/
+  -> Maybe RegionCode
+  -- ^ Up to 50 extra regions to get observations from
+  --
+  -- /default: none/
+  -> Maybe SPPLocale
+  -- ^ Return observations with common names in this locale
+  --
+  -- /default: 'En'/
+  -> ClientM [SomeObservation]
+
+-------------------------------------------------------------------------------
+-- Product APIs
+-------------------------------------------------------------------------------
+
+-- | Get a list recently submitted checklists within a region.
+--
+-- See the [eBird API documentation for the corresponding
+-- endpoint](https://documenter.getpostman.com/view/664302/S1ENwy59#95a206d1-a20d-44e0-8c27-acb09ccbea1a).
+recentChecklists_
+  :: Text
+  -- ^ eBird API key
+  -> RegionCode
+  -- ^ Region(s) to get checklists from
+  -> Maybe Integer
+  -- ^ Maximum number of checklists to fetch
+  --
+  -- /1 - 200, default: 10/
+  -> ClientM [ChecklistFeedEntry]
+
+-- | Get a list of top contributors for a region on a specific date, ranked by
+-- number of species observed or number of checklists submitted.
+--
+-- See the [eBird API documentation for the corresponding
+-- endpoint](https://documenter.getpostman.com/view/664302/S1ENwy59#2d8d3f94-c4b0-42bd-9c8e-71edfa6347ba).
+top100_
+  :: Text
+  -- ^ eBird API key
+  -> Region
+  -- ^ Region to fetch the ranking for
+  -> Integer
+  -- ^ Year, from 1800 to present
+  -> Integer
+  -- ^ Month (1 - 12)
+  -> Integer
+  -- ^ Day in the month
+  -> Maybe RankTop100By
+  -- ^ Rank the resulting list by number of species observed or by number of
+  -- checklists completed
+  --
+  -- /default: 'RankTop100BySpecies'/
+  -> Maybe Integer
+  -- ^ Maximum number of entries to fetch
+  --
+  -- /1 - 100, default: 100/
+  -> ClientM [Top100ListEntry]
+
+-- | Get a list of checklists submitted within a region on a specific date.
+--
+-- See the [eBird API documentation for the corresponding
+-- endpoint](https://documenter.getpostman.com/view/664302/S1ENwy59#4416a7cc-623b-4340-ab01-80c599ede73e).
+checklistFeed_
+  :: Text
+  -- ^ eBird API key
+  -> Region
+  -- ^ Region to fetch the checklist feed for
+  -> Integer
+  -- ^ Year, from 1800 to present
+  -> Integer
+  -- ^ Month (1 - 12)
+  -> Integer
+  -- ^ Day in the month
+  -> Maybe SortChecklistsBy
+  -- ^ Sort the resulting list by date of checklist submission or date of
+  -- checklist creation
+  --
+  -- /default: 'SortChecklistsByDateCreated'/
+  -> Maybe Integer
+  -- ^ Maximum number of checklists to fetch
+  --
+  -- /1 - 200, default: 10/
+  -> ClientM [ChecklistFeedEntry]
+
+-- | Get the 'RegionalStatistics' for a region on a specific date.
+--
+-- See the [eBird API documentation for the corresponding
+-- endpoint](https://documenter.getpostman.com/view/664302/S1ENwy59#506e63ab-abc0-4256-b74c-cd9e77968329).
+regionalStatistics_
+  :: Text
+  -- ^ eBird API key
+  -> Region
+  -- ^ Region to fetch the statistics for
+  -> Integer
+  -- ^ Year, from 1800 to present
+  -> Integer
+  -- ^ Month (1 - 12)
+  -> Integer
+  -- ^ Day in the month
+  -> ClientM RegionalStatistics
+
+-- | Get a list of all species ever seen in a region.
+--
+-- See the [eBird API documentation for the corresponding
+-- endpoint](https://documenter.getpostman.com/view/664302/S1ENwy59#55bd1b26-6951-4a88-943a-d3a8aa1157dd).
+speciesList_
+  :: Text
+  -- ^ eBird API key
+  -> Region
+  -- ^ Region to fetch the species list for
+  -> ClientM [SpeciesCode]
+
+-- | Get information about a checklist.
+--
+-- See the [eBird API documentation for the corresponding
+-- endpoint](https://documenter.getpostman.com/view/664302/S1ENwy59#2ee89672-4211-4fc1-8493-5df884fbb386).
+viewChecklist_
+  :: Text
+  -- ^ eBird API key
+  -> Text
+  -- ^ Checklist submission ID, e.g. \"S144646447\"
+  -> ClientM Checklist
+
+-------------------------------------------------------------------------------
+-- Hotspot APIs
+-------------------------------------------------------------------------------
+
+-- | Get all hotspots in a list of one or more regions ('RegionCode').
+--
+-- See the [eBird API documentation for the corresponding
+-- endpoint](https://documenter.getpostman.com/view/664302/S1ENwy59#f4f59f90-854e-4ba6-8207-323a8cf0bfe0).
+--
+-- __NOTE:__ The eBird API is broken. Always hardcode the 'CSVOrJSONFormat'
+-- argument to 'JSONFormat'.
+regionHotspots_
+  :: RegionCode
+  -- ^ Region(s) to get hotspots in
+  -> Maybe Integer
+  -- ^ Only fetch hotspots that have been visited within this many days ago
+  --
+  -- /1 - 30, default: no limit/
+  -> Maybe CSVOrJSONFormat
+  -- ^ Format results in CSV or JSON format
+  --
+  -- __NOTE:__ This argument should /always/ be hardcoded to 'JSONFormat', even
+  -- though the default is 'CSVFormat'. It is only here for to be consistent
+  -- with the eBird API. Unfortunately, the endpoint for this query switches
+  -- content types based on this query parameter instead of an \"Accept\" header.
+  -- That means servant is unable to determine whether the result will be CSV or
+  -- JSON encoded. For now, the workaround is to always hardcode this to
+  -- 'JSONFormat'.
+  --
+  -- /default: 'CSVFormat'/
+  -> ClientM [Hotspot]
+
+-- | Get all hotspots within a radius of some latitude/longitude.
+--
+-- See the [eBird API documentation for the corresponding
+-- endpoint](https://documenter.getpostman.com/view/664302/S1ENwy59#674e81c1-6a0c-4836-8a7e-6ea1fe8e6677).
+--
+-- __NOTE:__ The eBird API is broken. Always hardcode the 'CSVOrJSONFormat'
+-- argument to 'JSONFormat'.
+nearbyHotspots_
+  :: Double
+  -- ^ Latitude of the location to get hotspots near
+  -> Double
+  -- ^ Longitude of the location to get hotspots near
+  -> Maybe Integer
+  -- ^ Only fetch hotspots that have been visited within this many days ago
+  --
+  -- /1 - 30, default: no limit/
+  -> Maybe Integer
+  -- ^ Search radius in kilometers
+  --
+  -- /0 - 50, default: 25/
+  -> Maybe CSVOrJSONFormat
+  -- ^ Format results in CSV or JSON format
+  --
+  -- __NOTE:__ This argument should /always/ be hardcoded to 'JSONFormat', even
+  -- though the default is 'CSVFormat'. It is only here for to be consistent
+  -- with the eBird API. Unfortunately, the endpoint for this query switches
+  -- content types based on this query parameter instead of an \"Accept\" header.
+  -- That means servant is unable to determine whether the result will be CSV or
+  -- JSON encoded. For now, the workaround is to always hardcode this to
+  -- 'JSONFormat'.
+  --
+  -- /default: 'CSVFormat'/
+  -> ClientM [Hotspot]
+
+-- | Get information about a hotspot.
+--
+-- See the [eBird API documentation for the corresponding
+-- endpoint](https://documenter.getpostman.com/view/664302/S1ENwy59#e25218db-566b-4d8b-81ca-e79a8f68c599).
+hotspotInfo_
+  :: Text
+  -- ^ Location ID of the hotspot (e.g. \"L2373040\")
+  -> ClientM LocationData
+
+-------------------------------------------------------------------------------
+-- Taxonomy APIs
+-------------------------------------------------------------------------------
+
+-- | Get any version of the eBird taxonomy, with optional filtering based on
+-- taxonomy categories and species.
+--
+-- See the [eBird API documentation for the corresponding
+-- endpoint](https://documenter.getpostman.com/view/664302/S1ENwy59#952a4310-536d-4ad1-8f3e-77cfb624d1bc).
+--
+-- __NOTE:__ The eBird API is broken. Always hardcode the 'CSVOrJSONFormat'
+-- argument to 'JSONFormat'.
+taxonomy_
+  :: Maybe TaxonomyCategories
+  -- ^ Only include species of these 'TaxonomyCategory's in the taxonomy
+  --
+  -- /default: all categories/
+  -> Maybe CSVOrJSONFormat
+  -- ^ Format the taxonomy in CSV or JSON
+  --
+  -- __NOTE:__ This argument should /always/ be hardcoded to 'JSONFormat', even
+  -- though the default is 'CSVFormat'. It is only here for to be consistent
+  -- with the eBird API. Unfortunately, the endpoint for this query switches
+  -- content types based on this query parameter instead of an \"Accept\" header.
+  -- That means servant is unable to determine whether the result will be CSV or
+  -- JSON encoded. For now, the workaround is to always hardcode this to
+  -- 'JSONFormat'.
+  --
+  -- /default: 'CSVFormat'/
+  -> Maybe SPPLocale
+  -- ^ Use this locale for common names
+  --
+  -- /default: 'En'/
+  -> Maybe SpeciesCodes
+  -- ^ Only fetch records for these species
+  --
+  -- /default: all/
+  -> Maybe Text
+  -- ^ Fetch this version of the eBird taxonomy
+  --
+  -- /default: latest/
+  -> ClientM [Taxon]
+
+-- | Get the list of sub species of a given species recognized in the eBird
+-- taxonomy.
+--
+-- See the [eBird API documentation for the corresponding
+-- endpoint](https://documenter.getpostman.com/view/664302/S1ENwy59#e338e5a6-919d-4603-a7db-6c690fa62371).
+taxonomicForms_
+  :: Text
+  -- ^ eBird API key
+  -> SpeciesCode
+  -- ^ Species to get the sub species of
+  -> ClientM SpeciesCodes
+
+-- | Get the supported locale codes and names for species common names, with the
+-- last time they were updated.
+--
+-- See the [eBird API documentation for the corresponding
+-- endpoint](https://documenter.getpostman.com/view/664302/S1ENwy59#3ea8ff71-c254-4811-9e80-b445a39302a6).
+taxaLocaleCodes_
+  :: Text
+  -- ^ eBird API key
+  -> Maybe SPPLocale
+  -- ^ Value for the "Accept-Language" header, for translated language names,
+  -- when available
+  --
+  -- /default: 'En'/
+  -> ClientM [SPPLocaleListEntry]
+
+-- | Get all versions of the taxonomy, with a flag indicating which is latest.
+--
+-- See the [eBird API documentation for the corresponding
+-- endpoint](https://documenter.getpostman.com/view/664302/S1ENwy59#9bba1ff5-6eb2-4f9a-91fd-e5ed34e51500).
+taxonomyVersions_ :: ClientM [TaxonomyVersionListEntry]
+
+-- | Get the list of species groups, in either Merlin or eBird grouping.
+--
+-- See the [eBird API documentation for the corresponding
+-- endpoint](https://documenter.getpostman.com/view/664302/S1ENwy59#aa9804aa-dbf9-4a53-bbf4-48e214e4677a).
+taxonomicGroups_
+  :: SPPGrouping
+  -- ^ 'MerlinGrouping' groups like birds together, with falcons next to hawks,
+  -- while 'EBirdGrouping' groups in taxonomy order
+  -> Maybe SPPLocale
+  -- ^ Locale to use for species group names. 'En' is used for any locale whose
+  -- translations are unavailable at this endpoint
+  --
+  -- /default: 'En'/
+  -> ClientM [TaxonomicGroupListEntry]
+
+-------------------------------------------------------------------------------
+-- Region APIs
+-------------------------------------------------------------------------------
+
+-- | Get a 'RegionInfo' for an eBird region.
+--
+-- See the [eBird API documentation for the corresponding
+-- endpoint](https://documenter.getpostman.com/view/664302/S1ENwy59#07c64240-6359-4688-9c4f-ff3d678a7248).
+regionInfo_
+  :: Text
+  -- ^ eBird API key
+  -> Region
+  -- ^ Region to get information for
+  -> Maybe RegionNameFormat
+  -- ^ How to format the region name in the response
+  --
+  -- /default: 'Full'/
+  -> ClientM RegionInfo
+
+-- | Get a list of sub-regions of a given region type within a given region.
+-- Keep in mind that many combinations of sub region and parent region are
+-- invalid, e.g. 'CountryType' regions within "US-WY".
+--
+-- See the [eBird API documentation for the corresponding
+-- endpoint](https://documenter.getpostman.com/view/664302/S1ENwy59#382da1c8-8bff-4926-936a-a1f8b065e7d5).
+subRegionList_
+  :: Text
+  -- ^ eBird API key
+  -> RegionType
+  -- ^ Type of subregions to fetch
+  -> RegionCode
+  -- ^ Parent 'RegionCode'
+  -> ClientM [RegionListEntry]
+
+-- | Get a list of regions adjacent to a given region. Only 'Subnational2'
+-- region codes in the United States, New Zealand, or Mexico are currently
+-- supported.
+--
+-- See the [eBird API documentation for the corresponding
+-- endpoint](https://documenter.getpostman.com/view/664302/S1ENwy59#3aca0519-3105-47fc-8611-a4dfd500a32f).
+adjacentRegions_
+  :: Text
+  -- ^ eBird API key
+  -> Region
+  -- ^ Region to fetch the adjacent regions of
+  -> ClientM [RegionListEntry]
+
+recentObservations_
+  :<|> recentNotableObservations_
+  :<|> recentSpeciesObservations_
+  :<|> recentNearbyObservations_
+  :<|> recentNearbySpeciesObservations_
+  :<|> recentNearestSpeciesObservations_
+  :<|> recentNearbyNotableObservations_
+  :<|> historicalObservations_
+  :<|> recentChecklists_
+  :<|> top100_
+  :<|> checklistFeed_
+  :<|> regionalStatistics_
+  :<|> speciesList_
+  :<|> viewChecklist_
+  :<|> regionHotspots_
+  :<|> nearbyHotspots_
+  :<|> hotspotInfo_
+  :<|> taxonomy_
+  :<|> taxonomicForms_
+  :<|> taxaLocaleCodes_
+  :<|> taxonomyVersions_
+  :<|> taxonomicGroups_
+  :<|> regionInfo_
+  :<|> subRegionList_
+  :<|> adjacentRegions_ = client (Proxy @EBirdAPI)
diff --git a/src/Data/EBird/Client/Hotspots.hs b/src/Data/EBird/Client/Hotspots.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/EBird/Client/Hotspots.hs
@@ -0,0 +1,205 @@
+{-# LANGUAGE DataKinds             #-}
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE TemplateHaskell       #-}
+{-# LANGUAGE TypeFamilies          #-}
+{-# LANGUAGE TypeOperators         #-}
+{-# LANGUAGE UndecidableInstances  #-}
+
+-- |
+-- Module      : Data.EBird.Client.Hotspots
+-- Copyright   : (c) 2023 Finley McIlwaine
+-- License     : MIT (see LICENSE)
+--
+-- Maintainer  : Finley McIlwaine <finleymcilwaine@gmail.com>
+--
+-- Types and functions for hotspot-related eBird API queries.
+
+module Data.EBird.Client.Hotspots where
+
+import Data.Default
+import Data.Text
+import Optics.TH
+import Servant.Client
+
+import Data.EBird.API
+import Data.EBird.Client.Generated
+
+-------------------------------------------------------------------------------
+-- * Region hotspots
+-------------------------------------------------------------------------------
+
+-- | Get all hotspots in a list of one or more regions ('RegionCode').
+--
+-- For example, get the hotspots in Albany County, Wyoming and Park County,
+-- Wyoming that have been visited in the last 5 days (using @-XOverloadedLabels@
+-- and @-XOverloadedStrings@):
+--
+-- @
+-- askEBird $ regionHotspots "US-WY-001,US-WY-029" (def & #back ?~ 5)
+-- @
+--
+-- See the [eBird API documentation for the corresponding
+-- endpoint](https://documenter.getpostman.com/view/664302/S1ENwy59#f4f59f90-854e-4ba6-8207-323a8cf0bfe0).
+regionHotspots
+  :: RegionCode
+  -- ^ Region(s) to get hotspots in
+  -> RegionHotspotsParams
+  -- ^ Optional parameters
+  --
+  -- /default: 'defaultRegionHotspotsParams'/
+  -> ClientM [Hotspot]
+regionHotspots r RegionHotspotsParams{..} =
+    regionHotspots_ r _regionHotspotsParamsBack
+      -- Hard coded to JSONFormat because it makes no difference and CSVFormat
+      -- does not work like it should. See the note on the generated function's
+      -- parameter documentation.
+      (Just JSONFormat)
+
+-- | Optional parameters accepted by the 'RegionHotspotsAPI'.
+--
+-- Note that 'defaultRegionHotspotsParams' (or the 'Default' instance's 'def'
+-- value) may be used to accept the defaults of the eBird API.
+--
+-- Additionally, note that there are optics available for manipulating this
+-- type. For example, if you would like to just set the
+-- '_regionHotspotsParamsBack' field to 10:
+--
+-- > def & regionHotspotsParamsBack ?~ 10
+--
+-- Or, using @-XOverloadedLabels@:
+--
+-- > def & #back ?~ 10
+newtype RegionHotspotsParams =
+    RegionHotspotsParams
+      { -- | Only fetch hotspots that have been visited within this many days
+        -- ago
+        --
+        -- /1 - 30, default: no limit/
+        _regionHotspotsParamsBack :: Maybe Integer
+      }
+  deriving (Show, Read, Eq)
+
+-- | Note that this value does not actually use the eBird API default values.
+-- It simply sets every option to 'Nothing', which means we just don't send any
+-- of these parameters to the eBird API and they will use /their own/ defaults.
+defaultRegionHotspotsParams :: RegionHotspotsParams
+defaultRegionHotspotsParams =
+    RegionHotspotsParams
+      { _regionHotspotsParamsBack = Nothing
+      }
+
+instance Default RegionHotspotsParams where
+  def = defaultRegionHotspotsParams
+
+-- ** Optics for 'RegionHotspotsParams'
+makeLenses ''RegionHotspotsParams
+makeFieldLabels ''RegionHotspotsParams
+
+-------------------------------------------------------------------------------
+-- * Nearby hotspots
+-------------------------------------------------------------------------------
+
+-- | Get all hotspots within a radius of some latitude/longitude.
+--
+-- For example, get the hotspots within 30km of Cody, Wyoming that have been
+-- visited in the last 5 days (using @-XOverloadedLabels@
+-- and @-XOverloadedStrings@):
+--
+-- @
+-- askEBird $
+--   nearbyHotspots
+--     44.526340 (-109.056534)
+--     (def & #radius ?~ 30 & #back ?~ 5)
+-- @
+--
+-- See the [eBird API documentation for the corresponding
+-- endpoint](https://documenter.getpostman.com/view/664302/S1ENwy59#674e81c1-6a0c-4836-8a7e-6ea1fe8e6677).
+nearbyHotspots
+  :: Double
+  -- ^ Latitude of the location to get hotspots near
+  -> Double
+  -- ^ Longitude of the location to get hotspots near
+  -> NearbyHotspotsParams
+  -- ^ Optional parameters
+  --
+  -- /default: 'defaultNearbyHotspotsParams'/
+  -> ClientM [Hotspot]
+nearbyHotspots lat lng NearbyHotspotsParams{..} =
+    nearbyHotspots_ lat lng
+      _nearbyHotspotsParamsBack
+      _nearbyHotspotsParamsRadius
+      -- Hard coded to JSONFormat because it makes no difference and CSVFormat
+      -- does not work like it should. See the note on the generated function's
+      -- parameter documentation.
+      (Just JSONFormat)
+
+-- | Optional parameters accepted by the 'NearbyHotspotsAPI'.
+--
+-- Note that 'defaultNearbyHotspotsParams' (or the 'Default' instance's 'def'
+-- value) may be used to accept the defaults of the eBird API.
+--
+-- Additionally, note that there are optics available for manipulating this
+-- type. For example, if you would like to just set the
+-- '_nearbyHotspotsParamsBack' field to 10:
+--
+-- > def & nearbyHotspotsParamsBack ?~ 10
+--
+-- Or, using @-XOverloadedLabels@:
+--
+-- > def & #back ?~ 10
+data NearbyHotspotsParams =
+    NearbyHotspotsParams
+      { -- | Only fetch hotspots that have been visited within this many days
+        -- ago
+        --
+        -- /1 - 30, default: no limit/
+        _nearbyHotspotsParamsBack :: Maybe Integer
+
+        -- ^ Search radius in kilometers
+        --
+        -- /0 - 50, default: 25/
+      , _nearbyHotspotsParamsRadius :: Maybe Integer
+      }
+  deriving (Show, Read, Eq)
+
+-- | Note that this value does not actually use the eBird API default values.
+-- It simply sets every option to 'Nothing', which means we just don't send any
+-- of these parameters to the eBird API and they will use /their own/ defaults.
+defaultNearbyHotspotsParams :: NearbyHotspotsParams
+defaultNearbyHotspotsParams =
+    NearbyHotspotsParams
+      { _nearbyHotspotsParamsBack = Nothing
+      , _nearbyHotspotsParamsRadius = Nothing
+      }
+
+instance Default NearbyHotspotsParams where
+  def = defaultNearbyHotspotsParams
+
+-- ** Optics for 'NearbyHotspotsParams'
+makeLenses ''NearbyHotspotsParams
+makeFieldLabels ''NearbyHotspotsParams
+
+-------------------------------------------------------------------------------
+-- * Hotspot info
+-------------------------------------------------------------------------------
+
+-- | Get information about a hotspot.
+--
+-- For example, get information for a hotspot with location ID
+-- \"L2373040\" (using @-XOverloadedStrings@):
+--
+-- @
+-- askEBird $ hotspotInfo "L2373040"
+-- @
+--
+-- Note that the endpoint for this query is simple enough that 'hotspotInfo'
+-- is equivalent to the generated 'hotspotInfo_'.
+--
+-- See the [eBird API documentation for the corresponding
+-- endpoint](https://documenter.getpostman.com/view/664302/S1ENwy59#e25218db-566b-4d8b-81ca-e79a8f68c599).
+hotspotInfo
+  :: Text
+  -- ^ Hotspot location ID, e.g. \"L2373040\"
+  -> ClientM LocationData
+hotspotInfo = hotspotInfo_
diff --git a/src/Data/EBird/Client/Observations.hs b/src/Data/EBird/Client/Observations.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/EBird/Client/Observations.hs
@@ -0,0 +1,958 @@
+{-# LANGUAGE DataKinds             #-}
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE TemplateHaskell       #-}
+{-# LANGUAGE TypeFamilies          #-}
+{-# LANGUAGE TypeOperators         #-}
+{-# LANGUAGE UndecidableInstances  #-}
+
+-- |
+-- Module      : Data.EBird.Client.Observations
+-- Copyright   : (c) 2023 Finley McIlwaine
+-- License     : MIT (see LICENSE)
+--
+-- Maintainer  : Finley McIlwaine <finleymcilwaine@gmail.com>
+--
+-- Types and functions for observation-related eBird API queries.
+
+module Data.EBird.Client.Observations where
+
+import Data.Default
+import Data.Text
+import Optics.TH
+import Servant.Client
+
+import Data.EBird.API
+import Data.EBird.Client.Generated
+
+-------------------------------------------------------------------------------
+-- * Recent observations
+-------------------------------------------------------------------------------
+
+-- | Get a list of recent observations within a region. Results only include the
+-- most recent observation for each species in the region.
+--
+-- For example, get up to 10 recent observations from the last 5 days in Park
+-- County, Wyoming (using @-XOverloadedLabels@ and @-XOverloadedStrings@):
+--
+-- @
+-- askEBird $
+--   recentObservations key
+--     "US-WY-029"
+--     (def & #maxResults ?~ 10 & #back ?~ 5)
+-- @
+--
+-- See the [eBird API documentation for the corresponding
+-- endpoint](https://documenter.getpostman.com/view/664302/S1ENwy59#3d2a17c1-2129-475c-b4c8-7d362d6000cd).
+recentObservations
+  :: Text
+  -- ^ eBird API key
+  -> RegionCode
+  -- ^ Region(s) to get observations from
+  -> RecentObservationsParams
+  -- ^ Optional parameters
+  --
+  -- /default: 'defaultRecentObservationsParams'/
+  -> ClientM [Observation 'Simple]
+recentObservations k r RecentObservationsParams{..} =
+    recentObservations_ k r
+      _recentObservationsParamsBack
+      _recentObservationsParamsCategories
+      _recentObservationsParamsHotspot
+      _recentObservationsParamsProvisional
+      _recentObservationsParamsMaxResults
+      _recentObservationsParamsExtraRegions
+      _recentObservationsParamsLocale
+
+-- | Optional parameters accepted by the 'RecentObservationsAPI'.
+--
+-- Note that 'defaultRecentObservationsParams' (or the 'Default' instance's
+-- 'def' value) may be used to accept the defaults of the eBird API.
+--
+-- Additionally, note that there are optics available for manipulating this
+-- type. For example, if you would like to just set the
+-- '_recentObservationsParamsBack' field to 30:
+--
+-- > def & recentObservationsParamsBack ?~ 30
+--
+-- Or, using @-XOverloadedLabels@:
+--
+-- > def & #back ?~ 30
+data RecentObservationsParams =
+    RecentObservationsParams
+      { -- | How many days back to look for observations
+        --
+        -- /1 - 30, default: 14/
+        _recentObservationsParamsBack :: Maybe Integer
+
+        -- | Only include observations in these taxonomy categories
+        --
+        -- /default: all categories/
+      , _recentObservationsParamsCategories :: Maybe TaxonomyCategories
+
+        -- | Only get observations from hotspots
+        --
+        -- /default: 'False'/
+      , _recentObservationsParamsHotspot :: Maybe Bool
+
+        -- | Include observations which have not been reviewed
+        --
+        -- /default: 'False'/
+      , _recentObservationsParamsProvisional :: Maybe Bool
+
+        -- | Maximum number of observations to get
+        --
+        -- /1 - 10000, default: all/
+      , _recentObservationsParamsMaxResults :: Maybe Integer
+
+        -- | Up to 10 extra regions to get observations from
+        --
+        -- /default: none/
+      , _recentObservationsParamsExtraRegions :: Maybe RegionCode
+
+        -- | Return observations with common names in this locale
+        --
+        -- /default: 'En'/
+      , _recentObservationsParamsLocale :: Maybe SPPLocale
+      }
+  deriving (Show, Read, Eq)
+
+-- | Note that this value does not actually use the eBird API default values.
+-- It simply sets every option to 'Nothing', which means we just don't send any
+-- of these parameters to the eBird API and they will use /their own/ defaults.
+defaultRecentObservationsParams :: RecentObservationsParams
+defaultRecentObservationsParams =
+    RecentObservationsParams
+      { _recentObservationsParamsBack = Nothing
+      , _recentObservationsParamsCategories = Nothing
+      , _recentObservationsParamsHotspot = Nothing
+      , _recentObservationsParamsProvisional = Nothing
+      , _recentObservationsParamsMaxResults = Nothing
+      , _recentObservationsParamsExtraRegions = Nothing
+      , _recentObservationsParamsLocale = Nothing
+      }
+
+instance Default RecentObservationsParams where
+  def = defaultRecentObservationsParams
+
+-- ** Optics for 'RecentObservationsParams'
+makeLenses ''RecentObservationsParams
+makeFieldLabels ''RecentObservationsParams
+
+-------------------------------------------------------------------------------
+-- * Recent notable observations
+-------------------------------------------------------------------------------
+
+-- | Get a list of recent notable observations within a region. Results only
+-- include the most recent observation for each species in the region.
+--
+-- For example, get up to 10 recent notable observations from the last 30 days
+-- in Park County, Wyoming (using @-XOverloadedLabels@ and
+-- @-XOverloadedStrings@):
+--
+-- @
+-- askEBird $
+--   recentNotableObservations key
+--     "US-WY-029"
+--     (def & #maxResults ?~ 10 & #back ?~ 30)
+-- @
+--
+-- See the [eBird API documentation for the corresponding
+-- endpoint](https://documenter.getpostman.com/view/664302/S1ENwy59#397b9b8c-4ab9-4136-baae-3ffa4e5b26e4).
+recentNotableObservations
+  :: Text
+  -- ^ eBird API key
+  -> RegionCode
+  -- ^ Region(s) to get observations from
+  -> RecentNotableObservationsParams
+  -- ^ Optional parameters
+  --
+  -- /default: 'defaultRecentNotableObservationsParams'/
+  -> ClientM [SomeObservation]
+recentNotableObservations k r RecentNotableObservationsParams{..} =
+    recentNotableObservations_ k r
+      _recentNotableObservationsParamsBack
+      _recentNotableObservationsParamsDetail
+      _recentNotableObservationsParamsHotspot
+      _recentNotableObservationsParamsMaxResults
+      _recentNotableObservationsParamsExtraRegions
+      _recentNotableObservationsParamsLocale
+
+-- | Optional parameters accepted by the 'RecentNotableObservationsAPI'.
+--
+-- Note that 'defaultRecentNotableObservationsParams' (or the 'Default'
+-- instance's 'def' value) may be used to accept the defaults of the eBird API.
+--
+-- Additionally, note that there are optics available for manipulating this
+-- type. For example, if you would like to just set the
+-- '_recentNotableObservationsParamsBack' field to 30:
+--
+-- > def & recentNotableObservationsParamsBack ?~ 30
+--
+-- Or, using @-XOverloadedLabels@:
+--
+-- > def & #back ?~ 30
+data RecentNotableObservationsParams =
+    RecentNotableObservationsParams
+      { -- | How many days back to look for observations
+        --
+        -- /1 - 30, default: 14/
+        _recentNotableObservationsParamsBack :: Maybe Integer
+
+        -- | Detail level for the resulting observations
+        --
+        -- /default: 'Simple'/
+      , _recentNotableObservationsParamsDetail :: Maybe DetailLevel
+
+        -- | Only get observations from hotspots
+        --
+        -- /default: 'False'/
+      , _recentNotableObservationsParamsHotspot :: Maybe Bool
+
+        -- | Maximum number of observations to get
+        --
+        -- /1 - 10000, default: all/
+      , _recentNotableObservationsParamsMaxResults :: Maybe Integer
+
+        -- | Up to 10 extra regions to get observations from
+        --
+        -- /default: none/
+      , _recentNotableObservationsParamsExtraRegions :: Maybe RegionCode
+
+        -- | Return observations with common names in this locale
+        --
+        -- /default: 'En'/
+      , _recentNotableObservationsParamsLocale :: Maybe SPPLocale
+      }
+  deriving (Show, Read, Eq)
+
+-- | Note that this value does not actually use the eBird API default values.
+-- It simply sets every option to 'Nothing', which means we just don't send any
+-- of these parameters to the eBird API and they will use /their own/ defaults.
+defaultRecentNotableObservationsParams :: RecentNotableObservationsParams
+defaultRecentNotableObservationsParams =
+    RecentNotableObservationsParams
+      { _recentNotableObservationsParamsBack = Nothing
+      , _recentNotableObservationsParamsDetail = Nothing
+      , _recentNotableObservationsParamsHotspot = Nothing
+      , _recentNotableObservationsParamsMaxResults = Nothing
+      , _recentNotableObservationsParamsExtraRegions = Nothing
+      , _recentNotableObservationsParamsLocale = Nothing
+      }
+
+instance Default RecentNotableObservationsParams where
+  def = defaultRecentNotableObservationsParams
+
+-- ** Optics for 'RecentNotableObservationsParams'
+makeLenses ''RecentNotableObservationsParams
+makeFieldLabels ''RecentNotableObservationsParams
+
+-------------------------------------------------------------------------------
+-- * Recent species observations
+-------------------------------------------------------------------------------
+
+-- | Get a list of recent observations of a specific species within a region.
+--
+-- For example, get observations of Peregrine Falcons from the last 30 days in
+-- Park County, Wyoming (using @-XOverloadedLabels@ and @-XOverloadedStrings@):
+--
+-- @
+-- askEBird $
+--   recentSpeciesObservations key
+--     "US-WY-029"
+--     "perfal"
+--     (def & #back ?~ 30)
+-- @
+--
+-- See the [eBird API documentation for the corresponding
+-- endpoint](https://documenter.getpostman.com/view/664302/S1ENwy59#755ce9ab-dc27-4cfc-953f-c69fb0f282d9).
+recentSpeciesObservations
+  :: Text
+  -- ^ eBird API key
+  -> RegionCode
+  -- ^ Region(s) to get observations from
+  -> SpeciesCode
+  -- ^ Species to get observations of (e.g. "barswa" for Barn Swallow)
+  -> RecentSpeciesObservationsParams
+  -- ^ Optional parameters
+  --
+  -- /default: 'defaultRecentSpeciesObservationsParams'/
+  -> ClientM [Observation 'Simple]
+recentSpeciesObservations k r sp RecentSpeciesObservationsParams{..} =
+    recentSpeciesObservations_ k r sp
+      _recentSpeciesObservationsParamsBack
+      _recentSpeciesObservationsParamsHotspot
+      _recentSpeciesObservationsParamsProvisional
+      _recentSpeciesObservationsParamsMaxResults
+      _recentSpeciesObservationsParamsExtraRegions
+      _recentSpeciesObservationsParamsLocale
+
+-- | Optional parameters accepted by the 'RecentSpeciesObservationsAPI'.
+--
+-- Note that 'defaultRecentSpeciesObservationsParams' (or the 'Default'
+-- instance's 'def' value) may be used to accept the defaults of the eBird API.
+--
+-- Additionally, note that there are optics available for manipulating this
+-- type. For example, if you would like to just set the
+-- '_recentSpeciesObservationsParamsBack' field to 30:
+--
+-- > def & recentSpeciesObservationsParamsBack ?~ 30
+--
+-- Or, using @-XOverloadedLabels@:
+--
+-- > def & #back ?~ 30
+data RecentSpeciesObservationsParams =
+    RecentSpeciesObservationsParams
+      { -- | How many days back to look for observations
+        --
+        -- /1 - 30, default: 14/
+        _recentSpeciesObservationsParamsBack :: Maybe Integer
+
+        -- | Only get observations from hotspots
+        --
+        -- /default: 'False'/
+      , _recentSpeciesObservationsParamsHotspot :: Maybe Bool
+
+        -- | Include observations which have not been reviewed
+        --
+        -- /default: 'False'/
+      , _recentSpeciesObservationsParamsProvisional :: Maybe Bool
+
+        -- | Maximum number of observations to get
+        --
+        -- /1 - 10000, default: all/
+      , _recentSpeciesObservationsParamsMaxResults :: Maybe Integer
+
+        -- | Up to 10 extra regions to get observations from
+        --
+        -- /default: none/
+      , _recentSpeciesObservationsParamsExtraRegions :: Maybe RegionCode
+
+        -- | Return observations with common names in this locale
+        --
+        -- /default: 'En'/
+      , _recentSpeciesObservationsParamsLocale :: Maybe SPPLocale
+      }
+  deriving (Show, Read, Eq)
+
+-- | Note that this value does not actually use the eBird API default values.
+-- It simply sets every option to 'Nothing', which means we just don't send any
+-- of these parameters to the eBird API and they will use /their own/ defaults.
+defaultRecentSpeciesObservationsParams :: RecentSpeciesObservationsParams
+defaultRecentSpeciesObservationsParams =
+    RecentSpeciesObservationsParams
+      { _recentSpeciesObservationsParamsBack = Nothing
+      , _recentSpeciesObservationsParamsHotspot = Nothing
+      , _recentSpeciesObservationsParamsProvisional = Nothing
+      , _recentSpeciesObservationsParamsMaxResults = Nothing
+      , _recentSpeciesObservationsParamsExtraRegions = Nothing
+      , _recentSpeciesObservationsParamsLocale = Nothing
+      }
+
+instance Default RecentSpeciesObservationsParams where
+  def = defaultRecentSpeciesObservationsParams
+
+-- ** Optics for 'RecentSpeciesObservationsParams'
+makeLenses ''RecentSpeciesObservationsParams
+makeFieldLabels ''RecentSpeciesObservationsParams
+
+-------------------------------------------------------------------------------
+-- * Recent nearby observations
+-------------------------------------------------------------------------------
+
+-- | Get a list of recent observations within some radius of some
+-- latitude/longitude.
+--
+-- For example, get up to 5 nearby observations within 10km of Cody, Wyoming
+-- (using @-XOverloadedLabels@ and @-XOverloadedStrings@):
+--
+-- @
+-- askEBird $
+--   recentNearbyObservations key
+--     44.526340 (-109.056534)
+--     (def & #maxResults ?~ 5 & #radius ?~ 10)
+-- @
+--
+-- See the [eBird API documentation for the corresponding
+-- endpoint](https://documenter.getpostman.com/view/664302/S1ENwy59#397b9b8c-4ab9-4136-baae-3ffa4e5b26e4).
+recentNearbyObservations
+  :: Text
+  -- ^ eBird API key
+  -> Double
+  -- ^ Latitude of the location to get observations near
+  -> Double
+  -- ^ Longitude of the location to get observations near
+  -> RecentNearbyObservationsParams
+  -- ^ Optional parameters
+  --
+  -- /default: 'defaultRecentNearbyObservationsParams'/
+  -> ClientM [Observation 'Simple]
+recentNearbyObservations k lat lng RecentNearbyObservationsParams{..} =
+    recentNearbyObservations_ k lat lng
+      _recentNearbyObservationsParamsRadius
+      _recentNearbyObservationsParamsBack
+      _recentNearbyObservationsParamsCategories
+      _recentNearbyObservationsParamsHotspot
+      _recentNearbyObservationsParamsProvisional
+      _recentNearbyObservationsParamsMaxResults
+      _recentNearbyObservationsParamsSortBy
+      _recentNearbyObservationsParamsLocale
+
+-- | Optional parameters accepted by the 'RecentNearbyObservationsAPI'.
+--
+-- Note that 'defaultRecentNearbyObservationsParams' (or the 'Default'
+-- instance's 'def' value) may be used to accept the defaults of the eBird API.
+--
+-- Additionally, note that there are optics available for manipulating this
+-- type. For example, if you would like to just set the
+-- '_recentNearbyObservationsParamsRadius' field to 10km:
+--
+-- > def & recentNearbyObservationsParamsRadius ?~ 10
+--
+-- Or, using @-XOverloadedLabels@:
+--
+-- > def & #radius ?~ 10
+data RecentNearbyObservationsParams =
+    RecentNearbyObservationsParams
+      { -- | Search radius from the given latitude/longitude in kilometers
+        --
+        -- /0 - 50, default: 25/
+        _recentNearbyObservationsParamsRadius :: Maybe Integer
+
+        -- | How many days back to look for observations
+        --
+        -- /1 - 30, default: 14/
+      , _recentNearbyObservationsParamsBack :: Maybe Integer
+
+        -- | Only include observations in these taxonomy categories
+        --
+        -- /default: all/
+      , _recentNearbyObservationsParamsCategories :: Maybe TaxonomyCategories
+
+        -- | Only get observations from hotspots
+        --
+        -- /default: 'False'/
+      , _recentNearbyObservationsParamsHotspot :: Maybe Bool
+
+        -- | Include observations which have not been reviewed
+        --
+        -- /default: 'False'/
+      , _recentNearbyObservationsParamsProvisional :: Maybe Bool
+
+        -- | Maximum number of observations to get
+        --
+        -- /1 - 10000, default: all/
+      , _recentNearbyObservationsParamsMaxResults :: Maybe Integer
+
+        -- | Sort observations by taxonomy ('SortObservationsBySpecies') or by
+        -- date ('SortObservationsByDate', most recent first)
+        --
+        -- /default: 'SortObservationsByDate'/
+      , _recentNearbyObservationsParamsSortBy :: Maybe SortObservationsBy
+
+        -- | Return observations with common names in this locale
+        --
+        -- /default: 'En'/
+      , _recentNearbyObservationsParamsLocale :: Maybe SPPLocale
+      }
+  deriving (Show, Read, Eq)
+
+-- | Note that this value does not actually use the eBird API default values.
+-- It simply sets every option to 'Nothing', which means we just don't send any
+-- of these parameters to the eBird API and they will use /their own/ defaults.
+defaultRecentNearbyObservationsParams :: RecentNearbyObservationsParams
+defaultRecentNearbyObservationsParams =
+    RecentNearbyObservationsParams
+      { _recentNearbyObservationsParamsRadius = Nothing
+      , _recentNearbyObservationsParamsBack = Nothing
+      , _recentNearbyObservationsParamsCategories = Nothing
+      , _recentNearbyObservationsParamsHotspot = Nothing
+      , _recentNearbyObservationsParamsProvisional = Nothing
+      , _recentNearbyObservationsParamsMaxResults = Nothing
+      , _recentNearbyObservationsParamsSortBy = Nothing
+      , _recentNearbyObservationsParamsLocale = Nothing
+      }
+
+instance Default RecentNearbyObservationsParams where
+  def = defaultRecentNearbyObservationsParams
+
+-- ** Optics for 'RecentNearbyObservationsParams'
+makeLenses ''RecentNearbyObservationsParams
+makeFieldLabels ''RecentNearbyObservationsParams
+
+-------------------------------------------------------------------------------
+-- * Recent nearby species observations
+-------------------------------------------------------------------------------
+
+-- | Get a list of recent observations of a species within some radius of some
+-- latitude/longitude.
+--
+-- For example, get up to 5 nearby observations of Peregrine Falcons within 50km
+-- of Cody, Wyoming (using @-XOverloadedLabels@ and @-XOverloadedStrings@):
+--
+-- @
+-- askEBird $
+--   recentNearbySpeciesObservations key
+--     "perfal"
+--     44.526340 (-109.056534)
+--     (def & #radius ?~ 50 & #maxResults ?~ 5)
+-- @
+--
+-- See the [eBird API documentation for the corresponding
+-- endpoint](https://documenter.getpostman.com/view/664302/S1ENwy59#20fb2c3b-ee7f-49ae-a912-9c3f16a40397).
+recentNearbySpeciesObservations
+  :: Text
+  -- ^ eBird API key
+  -> SpeciesCode
+  -- ^ Species to get observations of (e.g. "bohwax" for Bohemian Waxwing)
+  -> Double
+  -- ^ Latitude of the location to get observations near
+  -> Double
+  -- ^ Longitude of the location to get observations near
+  -> RecentNearbySpeciesObservationsParams
+  -- ^ Optional parameters
+  --
+  -- /default: 'defaultRecentNearbySpeciesObservationsParams'/
+  -> ClientM [Observation 'Simple]
+recentNearbySpeciesObservations k sp lat lng RecentNearbySpeciesObservationsParams{..} =
+    recentNearbySpeciesObservations_ k sp lat lng
+      _recentNearbySpeciesObservationsParamsRadius
+      _recentNearbySpeciesObservationsParamsBack
+      _recentNearbySpeciesObservationsParamsCategories
+      _recentNearbySpeciesObservationsParamsHotspot
+      _recentNearbySpeciesObservationsParamsProvisional
+      _recentNearbySpeciesObservationsParamsMaxResults
+      _recentNearbySpeciesObservationsParamsSortBy
+      _recentNearbySpeciesObservationsParamsLocale
+
+-- | Optional parameters accepted by the 'RecentNearbySpeciesObservationsAPI'.
+--
+-- Note that 'defaultRecentNearbySpeciesObservationsParams' (or the 'Default'
+-- instance's 'def' value) may be used to accept the defaults of the eBird API.
+--
+-- Additionally, note that there are optics available for manipulating this
+-- type. For example, if you would like to just set the
+-- '_recentNearbySpeciesObservationsParamsRadius' field to 10km:
+--
+-- > def & recentNearbySpeciesObservationsParamsRadius ?~ 10
+--
+-- Or, using @-XOverloadedLabels@:
+--
+-- > def & #radius ?~ 10
+data RecentNearbySpeciesObservationsParams =
+    RecentNearbySpeciesObservationsParams
+      { -- | Search radius from the given latitude/longitude in kilometers
+        --
+        -- /0 - 50, default: 25/
+        _recentNearbySpeciesObservationsParamsRadius :: Maybe Integer
+
+        -- | How many days back to look for observations
+        --
+        -- /1 - 30, default: 14/
+      , _recentNearbySpeciesObservationsParamsBack :: Maybe Integer
+
+        -- | Only include observations in these taxonomy categories
+        --
+        -- /default: all/
+      , _recentNearbySpeciesObservationsParamsCategories :: Maybe TaxonomyCategories
+
+        -- | Only get observations from hotspots
+        --
+        -- /default: 'False'/
+      , _recentNearbySpeciesObservationsParamsHotspot :: Maybe Bool
+
+        -- | Include observations which have not been reviewed
+        --
+        -- /default: 'False'/
+      , _recentNearbySpeciesObservationsParamsProvisional :: Maybe Bool
+
+        -- | Maximum number of observations to get
+        --
+        -- /1 - 10000, default: all/
+      , _recentNearbySpeciesObservationsParamsMaxResults :: Maybe Integer
+
+        -- | Sort observations by taxonomy ('SortObservationsBySpecies') or by
+        -- date ('SortObservationsByDate', most recent first)
+        --
+        -- /default: 'SortObservationsByDate'/
+      , _recentNearbySpeciesObservationsParamsSortBy :: Maybe SortObservationsBy
+
+        -- | Return observations with common names in this locale
+        --
+        -- /default: 'En'/
+      , _recentNearbySpeciesObservationsParamsLocale :: Maybe SPPLocale
+      }
+  deriving (Show, Read, Eq)
+
+-- | Note that this value does not actually use the eBird API default values.
+-- It simply sets every option to 'Nothing', which means we just don't send any
+-- of these parameters to the eBird API and they will use /their own/ defaults.
+defaultRecentNearbySpeciesObservationsParams :: RecentNearbySpeciesObservationsParams
+defaultRecentNearbySpeciesObservationsParams =
+    RecentNearbySpeciesObservationsParams
+      { _recentNearbySpeciesObservationsParamsRadius = Nothing
+      , _recentNearbySpeciesObservationsParamsBack = Nothing
+      , _recentNearbySpeciesObservationsParamsCategories = Nothing
+      , _recentNearbySpeciesObservationsParamsHotspot = Nothing
+      , _recentNearbySpeciesObservationsParamsProvisional = Nothing
+      , _recentNearbySpeciesObservationsParamsMaxResults = Nothing
+      , _recentNearbySpeciesObservationsParamsSortBy = Nothing
+      , _recentNearbySpeciesObservationsParamsLocale = Nothing
+      }
+
+instance Default RecentNearbySpeciesObservationsParams where
+  def = defaultRecentNearbySpeciesObservationsParams
+
+-- ** Optics for 'RecentNearbySpeciesObservationsParams'
+makeLenses ''RecentNearbySpeciesObservationsParams
+makeFieldLabels ''RecentNearbySpeciesObservationsParams
+
+-------------------------------------------------------------------------------
+-- * Recent nearest species observations
+-------------------------------------------------------------------------------
+
+-- | Get a list of recent observations of some species nearest to some
+-- latitude/longitude.
+--
+-- For example, get the 5 nearest observations of Black-throated Gray Warblers
+-- within 50km of Capitol Reef National Park (using @-XOverloadedLabels@ and
+-- @-XOverloadedStrings@):
+--
+-- @
+-- askEBird $
+--   recentNearestSpeciesObservations key
+--     "btywar"
+--     38.366970 (-111.261504)
+--     (def & #radius ?~ 50 & #maxResults ?~ 5)
+-- @
+--
+-- See the [eBird API documentation for the corresponding
+-- endpoint](https://documenter.getpostman.com/view/664302/S1ENwy59#6bded97f-9997-477f-ab2f-94f254954ccb).
+recentNearestSpeciesObservations
+  :: Text
+  -- ^ eBird API key
+  -> SpeciesCode
+  -- ^ Species to get observations of (e.g. "bohwax" for Bohemian Waxwing)
+  -> Double
+  -- ^ Latitude of the location to get observations near
+  -> Double
+  -- ^ Longitude of the location to get observations near
+  -> RecentNearestSpeciesObservationsParams
+  -- ^ Optional parameters
+  --
+  -- /default: 'defaultRecentNearestSpeciesObservationsParams'/
+  -> ClientM [Observation 'Simple]
+recentNearestSpeciesObservations k sp lat lng RecentNearestSpeciesObservationsParams{..} =
+    recentNearestSpeciesObservations_ k sp lat lng
+      _recentNearestSpeciesObservationsParamsRadius
+      _recentNearestSpeciesObservationsParamsBack
+      _recentNearestSpeciesObservationsParamsHotspot
+      _recentNearestSpeciesObservationsParamsProvisional
+      _recentNearestSpeciesObservationsParamsMaxResults
+      _recentNearestSpeciesObservationsParamsLocale
+
+-- | Optional parameters accepted by the 'RecentNearestSpeciesObservationsAPI'.
+--
+-- Note that 'defaultRecentNearestSpeciesObservationsParams' (or the 'Default'
+-- instance's 'def' value) may be used to accept the defaults of the eBird API.
+--
+-- Additionally, note that there are optics available for manipulating this
+-- type. For example, if you would like to just set the
+-- '_recentNearestSpeciesObservationsParamsRadius' field to 10km:
+--
+-- > def & recentNearestSpeciesObservationsParamsRadius ?~ 10
+--
+-- Or, using @-XOverloadedLabels@:
+--
+-- > def & #radius ?~ 10
+data RecentNearestSpeciesObservationsParams =
+    RecentNearestSpeciesObservationsParams
+      { -- | Search radius from the given latitude/longitude in kilometers
+        --
+        -- /0 - 50, default: 25/
+        _recentNearestSpeciesObservationsParamsRadius :: Maybe Integer
+
+        -- | How many days back to look for observations
+        --
+        -- /1 - 30, default: 14/
+      , _recentNearestSpeciesObservationsParamsBack :: Maybe Integer
+
+        -- | Only get observations from hotspots
+        --
+        -- /default: 'False'/
+      , _recentNearestSpeciesObservationsParamsHotspot :: Maybe Bool
+
+        -- | Include observations which have not been reviewed
+        --
+        -- /default: 'False'/
+      , _recentNearestSpeciesObservationsParamsProvisional :: Maybe Bool
+
+        -- | Maximum number of observations to get
+        --
+        -- /1 - 10000, default: all/
+      , _recentNearestSpeciesObservationsParamsMaxResults :: Maybe Integer
+
+        -- | Return observations with common names in this locale
+        --
+        -- /default: 'En'/
+      , _recentNearestSpeciesObservationsParamsLocale :: Maybe SPPLocale
+      }
+  deriving (Show, Read, Eq)
+
+-- | Note that this value does not actually use the eBird API default values.
+-- It simply sets every option to 'Nothing', which means we just don't send any
+-- of these parameters to the eBird API and they will use /their own/ defaults.
+defaultRecentNearestSpeciesObservationsParams :: RecentNearestSpeciesObservationsParams
+defaultRecentNearestSpeciesObservationsParams =
+    RecentNearestSpeciesObservationsParams
+      { _recentNearestSpeciesObservationsParamsRadius = Nothing
+      , _recentNearestSpeciesObservationsParamsBack = Nothing
+      , _recentNearestSpeciesObservationsParamsHotspot = Nothing
+      , _recentNearestSpeciesObservationsParamsProvisional = Nothing
+      , _recentNearestSpeciesObservationsParamsMaxResults = Nothing
+      , _recentNearestSpeciesObservationsParamsLocale = Nothing
+      }
+
+instance Default RecentNearestSpeciesObservationsParams where
+  def = defaultRecentNearestSpeciesObservationsParams
+
+-- ** Optics for 'RecentNearestSpeciesObservationsParams'
+makeLenses ''RecentNearestSpeciesObservationsParams
+makeFieldLabels ''RecentNearestSpeciesObservationsParams
+
+-------------------------------------------------------------------------------
+-- * Recent nearby notable observations
+-------------------------------------------------------------------------------
+
+-- | Get a list of recent /notable/ observations of some near some
+-- latitude/longitude.
+--
+-- For example, get 5 notable observations within 25km of Capitol Reef National
+-- Park (using @-XOverloadedLabels@ and @-XOverloadedStrings@):
+--
+-- @
+-- askEBird $
+--   recentNearbyNotableObservations key
+--     38.366970 (-111.261504)
+--     (def & #radius ?~ 25 & #maxResults ?~ 5)
+-- @
+--
+-- See the [eBird API documentation for the corresponding
+-- endpoint](https://documenter.getpostman.com/view/664302/S1ENwy59#caa348bb-71f6-471c-b203-9e1643377cbc).
+recentNearbyNotableObservations
+  :: Text
+  -- ^ eBird API key
+  -> Double
+  -- ^ Latitude of the location to get observations near
+  -> Double
+  -- ^ Longitude of the location to get observations near
+  -> RecentNearbyNotableObservationsParams
+  -- ^ Optional parameters
+  --
+  -- /default: 'defaultRecentNearbyNotableObservationsParams'/
+  -> ClientM [SomeObservation]
+recentNearbyNotableObservations k lat lng RecentNearbyNotableObservationsParams{..} =
+    recentNearbyNotableObservations_ k lat lng
+      _recentNearbyNotableObservationsParamsRadius
+      _recentNearbyNotableObservationsParamsDetail
+      _recentNearbyNotableObservationsParamsBack
+      _recentNearbyNotableObservationsParamsHotspot
+      _recentNearbyNotableObservationsParamsMaxResults
+      _recentNearbyNotableObservationsParamsLocale
+
+-- | Optional parameters accepted by the 'RecentNearbyNotableObservationsAPI'.
+--
+-- Note that 'defaultRecentNearbyNotableObservationsParams' (or the 'Default'
+-- instance's 'def' value) may be used to accept the defaults of the eBird API.
+--
+-- Additionally, note that there are optics available for manipulating this
+-- type. For example, if you would like to just set the
+-- '_recentNearbyNotableObservationsParamsRadius' field to 10km:
+--
+-- > def & recentNearbyNotableObservationsParamsRadius ?~ 10
+--
+-- Or, using @-XOverloadedLabels@:
+--
+-- > def & #radius ?~ 10
+data RecentNearbyNotableObservationsParams =
+    RecentNearbyNotableObservationsParams
+      { -- | Search radius from the given latitude/longitude in kilometers
+        --
+        -- /0 - 50, default: 25/
+        _recentNearbyNotableObservationsParamsRadius :: Maybe Integer
+
+        -- | Detail level for the resulting observations
+        --
+        -- /default: 'Simple'/
+      , _recentNearbyNotableObservationsParamsDetail :: Maybe DetailLevel
+
+        -- | How many days back to look for observations
+        --
+        -- /1 - 30, default: 14/
+      , _recentNearbyNotableObservationsParamsBack :: Maybe Integer
+
+        -- | Only get observations from hotspots
+        --
+        -- /default: 'False'/
+      , _recentNearbyNotableObservationsParamsHotspot :: Maybe Bool
+
+        -- | Maximum number of observations to get
+        --
+        -- /1 - 10000, default: all/
+      , _recentNearbyNotableObservationsParamsMaxResults :: Maybe Integer
+
+        -- | Return observations with common names in this locale
+        --
+        -- /default: 'En'/
+      , _recentNearbyNotableObservationsParamsLocale :: Maybe SPPLocale
+      }
+  deriving (Show, Read, Eq)
+
+-- | Note that this value does not actually use the eBird API default values.
+-- It simply sets every option to 'Nothing', which means we just don't send any
+-- of these parameters to the eBird API and they will use /their own/ defaults.
+defaultRecentNearbyNotableObservationsParams :: RecentNearbyNotableObservationsParams
+defaultRecentNearbyNotableObservationsParams =
+    RecentNearbyNotableObservationsParams
+      { _recentNearbyNotableObservationsParamsRadius = Nothing
+      , _recentNearbyNotableObservationsParamsDetail = Nothing
+      , _recentNearbyNotableObservationsParamsBack = Nothing
+      , _recentNearbyNotableObservationsParamsHotspot = Nothing
+      , _recentNearbyNotableObservationsParamsMaxResults = Nothing
+      , _recentNearbyNotableObservationsParamsLocale = Nothing
+      }
+
+instance Default RecentNearbyNotableObservationsParams where
+  def = defaultRecentNearbyNotableObservationsParams
+
+-- ** Optics for 'RecentNearbyNotableObservationsParams'
+makeLenses ''RecentNearbyNotableObservationsParams
+makeFieldLabels ''RecentNearbyNotableObservationsParams
+
+-------------------------------------------------------------------------------
+-- * Historical observations
+-------------------------------------------------------------------------------
+
+-- | Get a list of observations for each species seen on a specific date.
+--
+-- For example, get a list of 10 fully detailed observations for each species
+-- seen on July 11th, 2023 in Park County, Wyoming (using @-XOverloadedLabels@
+-- and @-XOverloadedStrings@):
+--
+-- @
+-- askEBird $
+--   historicalObservations key
+--     "US-WY-029"
+--     "2023-07-11"
+--     (def & #maxResults ?~ 10 & #detail ?~ Full)
+-- @
+--
+-- See the [eBird API documentation for the corresponding
+-- endpoint](https://documenter.getpostman.com/view/664302/S1ENwy59#2d8c6ee8-c435-4e91-9f66-6d3eeb09edd2).
+historicalObservations
+  :: Text
+  -- ^ eBird API key
+  -> RegionCode
+  -- ^ Region(s) to get observations from
+  -> EBirdDate
+  -- ^ Date to get observations on, from year 1800 to present
+  -> HistoricalObservationsParams
+  -- ^ Optional parameters
+  --
+  -- /default: 'defaultHistoricalObservationsParams'/
+  -> ClientM [SomeObservation]
+historicalObservations k r date HistoricalObservationsParams{..} =
+    historicalObservations_ k r y m d
+      _historicalObservationsParamsCategories
+      _historicalObservationsParamsDetail
+      _historicalObservationsParamsHotspot
+      _historicalObservationsParamsProvisional
+      _historicalObservationsParamsMaxResults
+      _historicalObservationsParamsSelect
+      _historicalObservationsParamsExtraRegions
+      _historicalObservationsParamsLocale
+  where
+    (y,m,d) = eBirdDateToGregorian date
+
+-- | Optional parameters accepted by the 'HistoricalObservationsAPI'.
+--
+-- Note that 'defaultHistoricalObservationsParams' (or the 'Default'
+-- instance's 'def' value) may be used to accept the defaults of the eBird API.
+--
+-- Additionally, note that there are optics available for manipulating this
+-- type. For example, if you would like to just set the
+-- '_historicalObservationsParamsDetail' field to 'Full':
+--
+-- > def & historicalObservationsParamsDetail ?~ Full
+--
+-- Or, using @-XOverloadedLabels@:
+--
+-- > def & #detail ?~ Full
+data HistoricalObservationsParams =
+    HistoricalObservationsParams
+      { -- | Only include observations in these taxonomy categories
+        --
+        -- /default: all/
+        _historicalObservationsParamsCategories :: Maybe TaxonomyCategories
+
+        -- | Detail level for the resulting observations
+        --
+        -- /default: 'Simple'/
+      , _historicalObservationsParamsDetail :: Maybe DetailLevel
+
+        -- | Only get observations from hotspots
+        --
+        -- /default: 'False'/
+      , _historicalObservationsParamsHotspot :: Maybe Bool
+
+        -- | Include observations which have not been reviewed
+        --
+        -- /default: 'False'/
+      , _historicalObservationsParamsProvisional :: Maybe Bool
+
+        -- | Maximum number of observations to get
+        --
+        -- /1 - 10000, default: all/
+      , _historicalObservationsParamsMaxResults :: Maybe Integer
+
+        -- | Whether to display the first or last observation of a species on
+        -- the date, in the case that there are multiple observations of the
+        -- same species on the date
+        --
+        -- /default: 'SelectLastObservation'/
+      , _historicalObservationsParamsSelect :: Maybe SelectObservation
+
+        -- | Up to 50 extra regions to get observations from
+        --
+        -- /default: none/
+      , _historicalObservationsParamsExtraRegions :: Maybe RegionCode
+
+        -- | Return observations with common names in this locale
+        --
+        -- /default: 'En'/
+      , _historicalObservationsParamsLocale :: Maybe SPPLocale
+      }
+  deriving (Show, Read, Eq)
+
+-- | Note that this value does not actually use the eBird API default values.
+-- It simply sets every option to 'Nothing', which means we just don't send any
+-- of these parameters to the eBird API and they will use /their own/ defaults.
+defaultHistoricalObservationsParams :: HistoricalObservationsParams
+defaultHistoricalObservationsParams =
+    HistoricalObservationsParams
+      { _historicalObservationsParamsCategories = Nothing
+      , _historicalObservationsParamsDetail = Nothing
+      , _historicalObservationsParamsHotspot = Nothing
+      , _historicalObservationsParamsProvisional = Nothing
+      , _historicalObservationsParamsMaxResults = Nothing
+      , _historicalObservationsParamsSelect = Nothing
+      , _historicalObservationsParamsExtraRegions = Nothing
+      , _historicalObservationsParamsLocale = Nothing
+      }
+
+instance Default HistoricalObservationsParams where
+  def = defaultHistoricalObservationsParams
+
+-- ** Optics for 'HistoricalObservationsParams'
+makeLenses ''HistoricalObservationsParams
+makeFieldLabels ''HistoricalObservationsParams
diff --git a/src/Data/EBird/Client/Product.hs b/src/Data/EBird/Client/Product.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/EBird/Client/Product.hs
@@ -0,0 +1,350 @@
+{-# LANGUAGE DataKinds             #-}
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE TemplateHaskell       #-}
+{-# LANGUAGE TypeFamilies          #-}
+{-# LANGUAGE TypeOperators         #-}
+{-# LANGUAGE UndecidableInstances  #-}
+
+-- |
+-- Module      : Data.EBird.Client.Product
+-- Copyright   : (c) 2023 Finley McIlwaine
+-- License     : MIT (see LICENSE)
+--
+-- Maintainer  : Finley McIlwaine <finleymcilwaine@gmail.com>
+--
+-- Types and functions for product-related eBird API queries.
+
+module Data.EBird.Client.Product where
+
+import Data.Default
+import Data.Text
+import Optics.TH
+import Servant.Client
+
+import Data.EBird.API
+import Data.EBird.Client.Generated
+
+-------------------------------------------------------------------------------
+-- * Recent checklists
+-------------------------------------------------------------------------------
+
+-- | Get a list recently submitted checklists within a region.
+--
+-- For example, get up to 3 recent checklists submitted in Park County, Wyoming
+-- (using @-XOverloadedLabels@ and @-XOverloadedStrings@):
+--
+-- @
+-- askEBird $
+--   recentChecklists key
+--     "US-WY-029"
+--     (def & #maxResults ?~ 3)
+-- @
+--
+-- See the [eBird API documentation for the corresponding
+-- endpoint](https://documenter.getpostman.com/view/664302/S1ENwy59#95a206d1-a20d-44e0-8c27-acb09ccbea1a).
+recentChecklists
+  :: Text
+  -- ^ eBird API key
+  -> RegionCode
+  -- ^ Region(s) to get Checklists from
+  -> RecentChecklistsParams
+  -- ^ Optional parameters
+  --
+  -- /default: 'defaultRecentChecklistsParams'/
+  -> ClientM [ChecklistFeedEntry]
+recentChecklists k r RecentChecklistsParams{..} =
+    recentChecklists_ k r _recentChecklistsParamsMaxResults
+
+-- | Optional parameters accepted by the 'RecentChecklistsAPI'.
+--
+-- Note that 'defaultRecentChecklistsParams' (or the 'Default' instance's
+-- 'def' value) may be used to accept the defaults of the eBird API.
+--
+-- Additionally, note that there are optics available for manipulating this
+-- type. For example, if you would like to just set the
+-- '_recentChecklistsParamsMaxResults' field to 3:
+--
+-- > def & recentChecklistsParamsMaxResults ?~ 3
+--
+-- Or, using @-XOverloadedLabels@:
+--
+-- > def & #maxResults ?~ 3
+newtype RecentChecklistsParams =
+    RecentChecklistsParams
+      { -- | Maximum number of checklists to get
+        --
+        -- /1 - 200, default: 10/
+        _recentChecklistsParamsMaxResults :: Maybe Integer
+      }
+  deriving (Show, Read, Eq)
+
+-- | Note that this value does not actually use the eBird API default values.
+-- It simply sets every option to 'Nothing', which means we just don't send any
+-- of these parameters to the eBird API and they will use /their own/ defaults.
+defaultRecentChecklistsParams :: RecentChecklistsParams
+defaultRecentChecklistsParams =
+    RecentChecklistsParams
+      { _recentChecklistsParamsMaxResults = Nothing
+      }
+
+instance Default RecentChecklistsParams where
+  def = defaultRecentChecklistsParams
+
+-- ** Optics for 'RecentChecklistsParams'
+makeLenses ''RecentChecklistsParams
+makeFieldLabels ''RecentChecklistsParams
+
+-------------------------------------------------------------------------------
+-- * Top 100
+-------------------------------------------------------------------------------
+
+-- | Get a list of top contributors for a region on a specific date, ranked by
+-- number of species observed or number of checklists submitted.
+--
+-- For example, get the top 10 contributors by number of species observed on
+-- July 11th, 2023 in Wyoming (using @-XOverloadedLabels@ and
+-- @-XOverloadedStrings@):
+--
+-- @
+-- askEBird $
+--   top100 key
+--     "US-WY"
+--     "2023-07-11"
+--     (def & #maxResults ?~ 10)
+-- @
+--
+-- See the [eBird API documentation for the corresponding
+-- endpoint](https://documenter.getpostman.com/view/664302/S1ENwy59#2d8d3f94-c4b0-42bd-9c8e-71edfa6347ba).
+top100
+  :: Text
+  -- ^ eBird API key
+  -> Region
+  -- ^ Region to fetch the ranking for
+  --
+  -- __Note:__ Only country, subnational1, or location regions are supported for
+  -- this endpoint of the eBird API.
+  -> EBirdDate
+  -- ^ Date to get the top 100 on
+  -> Top100Params
+  -- ^ Optional parameters
+  --
+  -- /default: 'defaultTop100Params'/
+  -> ClientM [Top100ListEntry]
+top100 k r date Top100Params{..} =
+    top100_ k r y m d _top100ParamsRankBy _top100ParamsMaxResults
+  where
+    (y,m,d) = eBirdDateToGregorian date
+
+-- | Optional parameters accepted by the 'Top100API'.
+--
+-- Note that 'defaultTop100Params' (or the 'Default' instance's 'def' value) may
+-- be used to accept the defaults of the eBird API.
+--
+-- Additionally, note that there are optics available for manipulating this
+-- type. For example, if you would like to just set the
+-- '_top100ParamsMaxResults' field to 50:
+--
+-- > def & top100ParamsMaxResults ?~ 50
+--
+-- Or, using @-XOverloadedLabels@:
+--
+-- > def & #maxResults ?~ 50
+data Top100Params =
+    Top100Params
+      { -- | Rank the resulting list by number of species observed or by number of
+        -- checklists completed
+        --
+        -- /default: 'RankTop100BySpecies'/
+        _top100ParamsRankBy :: Maybe RankTop100By
+
+        -- | Maximum number of entries to fetch
+        --
+        -- /1 - 100, default: 100/
+      , _top100ParamsMaxResults :: Maybe Integer
+      }
+  deriving (Show, Read, Eq)
+
+-- | Note that this value does not actually use the eBird API default values.
+-- It simply sets every option to 'Nothing', which means we just don't send any
+-- of these parameters to the eBird API and they will use /their own/ defaults.
+defaultTop100Params :: Top100Params
+defaultTop100Params =
+    Top100Params
+      { _top100ParamsRankBy = Nothing
+      , _top100ParamsMaxResults = Nothing
+      }
+
+instance Default Top100Params where
+  def = defaultTop100Params
+
+-- ** Optics for 'Top100Params'
+makeLenses ''Top100Params
+makeFieldLabels ''Top100Params
+
+-------------------------------------------------------------------------------
+-- * Checklist feed
+-------------------------------------------------------------------------------
+
+-- | Get a list of checklists submitted within a region on a specific date.
+--
+-- For example, get a feed of 10 checklists submitted in Park County, Wyoming on
+-- July 11th, 2023 (using @-XOverloadedLabels@ and @-XOverloadedStrings@):
+--
+-- @
+-- askEBird $
+--   checklistFeed key
+--     "US-WY-029"
+--     "2023-07-11"
+--     (def & #maxResults ?~ 10)
+-- @
+--
+-- See the [eBird API documentation for the corresponding
+-- endpoint](https://documenter.getpostman.com/view/664302/S1ENwy59#4416a7cc-623b-4340-ab01-80c599ede73e).
+checklistFeed
+  :: Text
+  -- ^ eBird API key
+  -> Region
+  -- ^ Region to fetch the checklist feed for
+  -> EBirdDate
+  -- ^ Date to get the checklist feed on
+  -> ChecklistFeedParams
+  -- ^ Optional parameters
+  --
+  -- /default: 'defaultChecklistFeedParams'/
+  -> ClientM [ChecklistFeedEntry]
+checklistFeed k r date ChecklistFeedParams{..} =
+    checklistFeed_ k r y m d
+      _checklistFeedParamsSortBy
+      _checklistFeedParamsMaxResults
+  where
+    (y,m,d) = eBirdDateToGregorian date
+
+-- | Optional parameters accepted by the 'ChecklistFeedAPI'.
+--
+-- Note that 'defaultChecklistFeedParams' (or the 'Default' instance's 'def' value) may
+-- be used to accept the defaults of the eBird API.
+--
+-- Additionally, note that there are optics available for manipulating this
+-- type. For example, if you would like to just set the
+-- '_checklistFeedParamsMaxResults' field to 50:
+--
+-- > def & checklistFeedParamsMaxResults ?~ 50
+--
+-- Or, using @-XOverloadedLabels@:
+--
+-- > def & #maxResults ?~ 50
+data ChecklistFeedParams =
+    ChecklistFeedParams
+      { -- | Sort the resulting list by date of checklist submission or date of
+        -- checklist creation
+        --
+        -- /default: 'SortChecklistsByDateCreated'/
+        _checklistFeedParamsSortBy :: Maybe SortChecklistsBy
+
+        -- | Maximum number of checklists to get
+        --
+        -- /1 - 200, default: 10/
+      , _checklistFeedParamsMaxResults :: Maybe Integer
+      }
+  deriving (Show, Read, Eq)
+
+-- | Note that this value does not actually use the eBird API default values.
+-- It simply sets every option to 'Nothing', which means we just don't send any
+-- of these parameters to the eBird API and they will use /their own/ defaults.
+defaultChecklistFeedParams :: ChecklistFeedParams
+defaultChecklistFeedParams =
+    ChecklistFeedParams
+      { _checklistFeedParamsSortBy = Nothing
+      , _checklistFeedParamsMaxResults = Nothing
+      }
+
+instance Default ChecklistFeedParams where
+  def = defaultChecklistFeedParams
+
+-- ** Optics for 'ChecklistFeedParams'
+makeLenses ''ChecklistFeedParams
+makeFieldLabels ''ChecklistFeedParams
+
+-------------------------------------------------------------------------------
+-- * Regional statistics
+-------------------------------------------------------------------------------
+
+-- | Get the 'RegionalStatistics' for a region on a specific date.
+--
+-- For example, get the statistics for Wyoming on July 11th, 2023 (using
+-- @-XOverloadedStrings@):
+--
+-- @
+-- askEBird $
+--   regionalStatistics key
+--     "US-WY"
+--     "2023-07-11"
+-- @
+--
+-- See the [eBird API documentation for the corresponding
+-- endpoint](https://documenter.getpostman.com/view/664302/S1ENwy59#506e63ab-abc0-4256-b74c-cd9e77968329).
+regionalStatistics
+  :: Text
+  -- ^ eBird API key
+  -> Region
+  -- ^ Region to fetch the statistics for
+  -> EBirdDate
+  -- ^ Date to get the statistics on
+  -> ClientM RegionalStatistics
+regionalStatistics k r date =
+    regionalStatistics_ k r y m d
+  where
+    (y,m,d) = eBirdDateToGregorian date
+
+-------------------------------------------------------------------------------
+-- * Species list
+-------------------------------------------------------------------------------
+
+-- | Get a list of all species ever seen in a 'Region'.
+--
+-- For example, get all species ever seen in Park County, Wyoming (using
+-- @-XOverloadedStrings@):
+--
+-- @
+-- askEBird $ speciesList key "US-WY-029"
+-- @
+--
+-- Note that the endpoint for this query is simple enough that 'speciesList' is
+-- equivalent to the generated 'speciesList_'.
+--
+-- See the [eBird API documentation for the corresponding
+-- endpoint](https://documenter.getpostman.com/view/664302/S1ENwy59#55bd1b26-6951-4a88-943a-d3a8aa1157dd).
+speciesList
+  :: Text
+  -- ^ eBird API key
+  -> Region
+  -- ^ Region to fetch the species list for
+  -> ClientM [SpeciesCode]
+speciesList = speciesList_
+
+-------------------------------------------------------------------------------
+-- * View checklist
+-------------------------------------------------------------------------------
+
+-- | Get information about a checklist.
+--
+-- For example, get information for a checklist with submission ID
+-- \"S144646447\" (using @-XOverloadedStrings@):
+--
+-- @
+-- askEBird $ viewChecklist key "S144646447"
+-- @
+--
+-- Note that the endpoint for this query is simple enough that 'viewChecklist'
+-- is equivalent to the generated 'viewChecklist_'.
+--
+-- See the [eBird API documentation for the corresponding
+-- endpoint](https://documenter.getpostman.com/view/664302/S1ENwy59#2ee89672-4211-4fc1-8493-5df884fbb386).
+viewChecklist
+  :: Text
+  -- ^ eBird API key
+  -> Text
+  -- ^ Checklist submission ID, e.g. \"S144646447\"
+  -> ClientM Checklist
+viewChecklist = viewChecklist_
diff --git a/src/Data/EBird/Client/Regions.hs b/src/Data/EBird/Client/Regions.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/EBird/Client/Regions.hs
@@ -0,0 +1,149 @@
+{-# LANGUAGE DataKinds             #-}
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE TemplateHaskell       #-}
+{-# LANGUAGE TypeFamilies          #-}
+{-# LANGUAGE TypeOperators         #-}
+{-# LANGUAGE UndecidableInstances  #-}
+
+-- |
+-- Module      : Data.EBird.Client.Regions
+-- Copyright   : (c) 2023 Finley McIlwaine
+-- License     : MIT (see LICENSE)
+--
+-- Maintainer  : Finley McIlwaine <finleymcilwaine@gmail.com>
+--
+-- Types and functions for region-related eBird API queries.
+
+module Data.EBird.Client.Regions where
+
+import Data.Default
+import Data.Text
+import Optics.TH
+import Servant.Client
+
+import Data.EBird.API
+import Data.EBird.Client.Generated
+
+-------------------------------------------------------------------------------
+-- * Region info
+-------------------------------------------------------------------------------
+
+-- | Get a 'RegionInfo' for an eBird region.
+--
+-- For example, get information about the Park County, Wyoming region (using
+-- @-XOverloadedLabels@ and @-XOverloadedStrings@):
+--
+-- @
+-- askEBird $ regionInfo key "US-WY-029" def
+-- @
+--
+-- See the [eBird API documentation for the corresponding
+-- endpoint](https://documenter.getpostman.com/view/664302/S1ENwy59#07c64240-6359-4688-9c4f-ff3d678a7248).
+regionInfo
+  :: Text
+  -- ^ eBird API key
+  -> Region
+  -- ^ Region to get information for
+  -> RegionInfoParams
+  -- ^ Optional parameters
+  --
+  -- /default: 'defaultRegionInfoParams'/
+  -> ClientM RegionInfo
+regionInfo k r RegionInfoParams{..} = regionInfo_ k r _regionInfoParamsFormat
+
+-- | Optional parameters accepted by the 'RegionInfoAPI'.
+--
+-- Note that 'defaultRegionInfoParams' (or the 'Default' instance's 'def' value)
+-- may be used to accept the defaults of the eBird API.
+--
+-- Additionally, note that there are optics available for manipulating this
+-- type. For example, if you would like to just set the
+-- '_regionInfoParamsFormat' field to 'NameOnlyNameFormat' (using
+-- @-XOverloadedString@):
+--
+-- > def & regionInfoParamsFormat ?~ "nameonly"
+--
+-- Or, using @-XOverloadedLabels@:
+--
+-- > def & #format ?~ "nameonly"
+newtype RegionInfoParams =
+    RegionInfoParams
+      { -- | How to format the region name in the response
+        --
+        -- /default: 'Full'/
+        _regionInfoParamsFormat :: Maybe RegionNameFormat
+      }
+  deriving (Show, Read, Eq)
+
+-- | Note that this value does not actually use the eBird API default values.
+-- It simply sets every option to 'Nothing', which means we just don't send any
+-- of these parameters to the eBird API and they will use /their own/ defaults.
+defaultRegionInfoParams :: RegionInfoParams
+defaultRegionInfoParams =
+    RegionInfoParams
+      { _regionInfoParamsFormat = Nothing
+      }
+
+instance Default RegionInfoParams where
+  def = defaultRegionInfoParams
+
+-- ** Optics for 'RegionInfoParams'
+makeLenses ''RegionInfoParams
+makeFieldLabels ''RegionInfoParams
+
+-------------------------------------------------------------------------------
+-- * Sub region list
+-------------------------------------------------------------------------------
+
+-- | Get a list of sub-regions of a given region type within a given region.
+-- Keep in mind that many combinations of sub-region and parent region are
+-- invalid, e.g. 'CountryType' regions within \"US-WY\".
+--
+-- For example, get county sub regions of Wyoming (using @-XOverloadedStrings@):
+--
+-- @
+-- askEBird $ subRegionList key Subnational2Type "US-WY"
+-- @
+--
+-- Note that the endpoint for this query is simple enough that 'subRegionList'
+-- is equivalent to the generated 'subRegionList_'.
+--
+-- See the [eBird API documentation for the corresponding
+-- endpoint](https://documenter.getpostman.com/view/664302/S1ENwy59#382da1c8-8bff-4926-936a-a1f8b065e7d5).
+subRegionList
+  :: Text
+  -- ^ eBird API key
+  -> RegionType
+  -- ^ Type of subregions to fetch
+  -> RegionCode
+  -- ^ Parent 'RegionCode'
+  -> ClientM [RegionListEntry]
+subRegionList = subRegionList_
+
+-------------------------------------------------------------------------------
+-- * Adjacent regions
+-------------------------------------------------------------------------------
+
+-- | Get a list of regions adjacent to a given region. 'Subnational2' region
+-- codes are only currently supported in the United States, New Zealand, or
+-- Mexico.
+--
+-- For example, get regions adjacent to Wyoming (using @-XOverloadedStrings@):
+--
+-- @
+-- askEBird $ adjacentRegions key "US-WY"
+-- @
+--
+-- Note that the endpoint for this query is simple enough that 'adjacentRegions'
+-- is equivalent to the generated 'adjacentRegions_'.
+--
+-- See the [eBird API documentation for the corresponding
+-- endpoint](https://documenter.getpostman.com/view/664302/S1ENwy59#3aca0519-3105-47fc-8611-a4dfd500a32f).
+adjacentRegions
+  :: Text
+  -- ^ eBird API key
+  -> Region
+  -- ^ Region to fetch the adjacent regions of
+  -> ClientM [RegionListEntry]
+adjacentRegions = adjacentRegions_
diff --git a/src/Data/EBird/Client/Taxonomy.hs b/src/Data/EBird/Client/Taxonomy.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/EBird/Client/Taxonomy.hs
@@ -0,0 +1,295 @@
+{-# LANGUAGE DataKinds             #-}
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE TemplateHaskell       #-}
+{-# LANGUAGE TypeFamilies          #-}
+{-# LANGUAGE TypeOperators         #-}
+{-# LANGUAGE UndecidableInstances  #-}
+
+-- |
+-- Module      : Data.EBird.Client.Taxonomy
+-- Copyright   : (c) 2023 Finley McIlwaine
+-- License     : MIT (see LICENSE)
+--
+-- Maintainer  : Finley McIlwaine <finleymcilwaine@gmail.com>
+--
+-- Types and functions for taxonomy-related eBird API queries.
+
+module Data.EBird.Client.Taxonomy where
+
+import Data.Default
+import Data.Text
+import Optics.TH
+import Servant.Client
+
+import Data.EBird.API
+import Data.EBird.Client.Generated
+
+-------------------------------------------------------------------------------
+-- Taxonomy
+-------------------------------------------------------------------------------
+
+-- | Get any version of the eBird taxonomy, with optional filtering based on
+-- taxonomy categories and species.
+--
+-- For example, get the taxa for species in the "hybrid" category:
+--
+-- @
+-- askEBird $ taxonomy (def & #categories ?~ "hybrid")
+-- @
+--
+-- See the [eBird API documentation for the corresponding
+-- endpoint](https://documenter.getpostman.com/view/664302/S1ENwy59#952a4310-536d-4ad1-8f3e-77cfb624d1bc).
+taxonomy
+  :: TaxonomyParams
+  -- ^ Optional parameters
+  --
+  -- /default: 'defaultTaxonomyParams'/
+  -> ClientM [Taxon]
+taxonomy TaxonomyParams{..} =
+    taxonomy_
+      _taxonomyParamsCategories
+      -- Hard coded to JSONFormat because it makes no difference and CSVFormat
+      -- does not work like it should. See the note on the generated function's
+      -- parameter documentation.
+      (Just JSONFormat)
+      _taxonomyParamsLocale
+      _taxonomyParamsSpecies
+      _taxonomyParamsVersion
+
+-- | Optional parameters accepted by the 'TaxonomyAPI'.
+--
+-- Note that 'defaultTaxonomyParams' (or the 'Default' instance's 'def' value)
+-- may be used to accept the defaults of the eBird API.
+--
+-- Additionally, note that there are optics available for manipulating this
+-- type. For example, if you would like to just set the
+-- '_taxonomyParamsSpecies' field to "bohwax":
+--
+-- > def & taxonomyParamsSpecies ?~ "bohwax"
+--
+-- Or, using @-XOverloadedLabels@:
+--
+-- > def & #species ?~ "bohwax"
+data TaxonomyParams =
+    TaxonomyParams
+      { -- | Only include species of these 'TaxonomyCategory's in the taxonomy
+        --
+        -- /default: all categories/
+        _taxonomyParamsCategories :: Maybe TaxonomyCategories
+
+        -- | Use this locale for common names
+        --
+        -- /default: 'En'/
+      , _taxonomyParamsLocale :: Maybe SPPLocale
+
+        -- | Only fetch records for these species
+        --
+        -- /default: all/
+      , _taxonomyParamsSpecies :: Maybe SpeciesCodes
+
+        -- | Fetch this version of the eBird taxonomy
+        --
+        -- /default: latest/
+      , _taxonomyParamsVersion :: Maybe Text
+      }
+  deriving (Show, Read, Eq)
+
+-- | Note that this value does not actually use the eBird API default values.
+-- It simply sets every option to 'Nothing', which means we just don't send any
+-- of these parameters to the eBird API and they will use /their own/ defaults.
+defaultTaxonomyParams :: TaxonomyParams
+defaultTaxonomyParams =
+    TaxonomyParams
+      { _taxonomyParamsCategories = Nothing
+      , _taxonomyParamsLocale = Nothing
+      , _taxonomyParamsSpecies = Nothing
+      , _taxonomyParamsVersion = Nothing
+      }
+
+instance Default TaxonomyParams where
+  def = defaultTaxonomyParams
+
+-- ** Optics for 'TaxonomyParams'
+makeLenses ''TaxonomyParams
+makeFieldLabels ''TaxonomyParams
+
+-------------------------------------------------------------------------------
+-- Taxonomic forms
+-------------------------------------------------------------------------------
+
+-- | Get the list of subspecies of a given species recognized in the eBird
+-- taxonomy.
+--
+-- For example, get subspecies of Canada Goose (using
+-- @-XOverloadedStrings@):
+--
+-- @
+-- askEBird $ taxonomicForms key "cangoo"
+-- @
+--
+-- Note that the endpoint for this query is simple enough that 'taxonomicForms'
+-- is equivalent to the generated 'taxonomicForms_'.
+--
+-- See the [eBird API documentation for the corresponding
+-- endpoint](https://documenter.getpostman.com/view/664302/S1ENwy59#e338e5a6-919d-4603-a7db-6c690fa62371).
+taxonomicForms
+  :: Text
+  -- ^ eBird API key
+  -> SpeciesCode
+  -- ^ The species to get subspecies of
+  -> ClientM SpeciesCodes
+taxonomicForms = taxonomicForms_
+
+-------------------------------------------------------------------------------
+-- Taxa locale codes
+-------------------------------------------------------------------------------
+
+-- | Get the supported locale codes and names for species common names, with the
+-- last time they were updated.
+--
+-- For example:
+--
+-- @
+-- askEBird $ taxaLocaleCodes key def
+-- @
+--
+-- See the [eBird API documentation for the corresponding
+-- endpoint](https://documenter.getpostman.com/view/664302/S1ENwy59#3ea8ff71-c254-4811-9e80-b445a39302a6).
+taxaLocaleCodes
+  :: Text
+  -- ^ eBird API key
+  -> TaxaLocaleCodesParams
+  -- ^ Optional parameters
+  --
+  -- /default: 'defaultTaxaLocaleCodesParams'/
+  -> ClientM [SPPLocaleListEntry]
+taxaLocaleCodes k TaxaLocaleCodesParams{..} =
+    taxaLocaleCodes_ k _taxaLocaleCodesParamsLocale
+
+-- | Optional parameters accepted by the 'TaxaLocaleCodesAPI'.
+--
+-- Note that 'defaultTaxaLocaleCodesParams' (or the 'Default' instance's 'def'
+-- value) may be used to accept the defaults of the eBird API.
+--
+-- Additionally, note that there are optics available for manipulating this
+-- type. For example, if you would like to just set the
+-- '_taxaLocaleCodesParamsLocale' field to 'Es':
+--
+-- > def & taxaLocaleCodesParamsLocale ?~ Es
+--
+-- Or, using @-XOverloadedLabels@:
+--
+-- > def & #locale ?~ Es
+newtype TaxaLocaleCodesParams =
+    TaxaLocaleCodesParams
+      { -- | Value for the "Accept-Language" header, for translated language
+        -- names, when available
+        --
+        -- /default: 'En'/
+        _taxaLocaleCodesParamsLocale :: Maybe SPPLocale
+      }
+  deriving (Show, Read, Eq)
+
+-- | Note that this value does not actually use the eBird API default values.
+-- It simply sets every option to 'Nothing', which means we just don't send any
+-- of these parameters to the eBird API and they will use /their own/ defaults.
+defaultTaxaLocaleCodesParams :: TaxaLocaleCodesParams
+defaultTaxaLocaleCodesParams =
+    TaxaLocaleCodesParams
+      { _taxaLocaleCodesParamsLocale = Nothing
+      }
+
+instance Default TaxaLocaleCodesParams where
+  def = defaultTaxaLocaleCodesParams
+
+-- ** Optics for 'TaxaLocaleCodesParams'
+makeLenses ''TaxaLocaleCodesParams
+makeFieldLabels ''TaxaLocaleCodesParams
+
+-------------------------------------------------------------------------------
+-- * Taxonomy versions
+-------------------------------------------------------------------------------
+
+-- | Get all versions of the taxonomy, with a flag indicating which is latest.
+--
+-- For example:
+--
+-- @
+-- askEBird taxonomyVersions
+-- @
+--
+-- Note that the endpoint for this query is simple enough that 'taxonomyVersions'
+-- is equivalent to the generated 'taxonomyVersions_'.
+--
+-- See the [eBird API documentation for the corresponding
+-- endpoint](https://documenter.getpostman.com/view/664302/S1ENwy59#9bba1ff5-6eb2-4f9a-91fd-e5ed34e51500).
+taxonomyVersions :: ClientM [TaxonomyVersionListEntry]
+taxonomyVersions = taxonomyVersions_
+
+-------------------------------------------------------------------------------
+-- * Taxonomic groups
+-------------------------------------------------------------------------------
+
+-- | Get the list of species groups, in either Merlin or eBird grouping.
+--
+-- For example, get the taxonomic groups using eBird grouping order (using
+-- @-XOverloadedStrings@):
+--
+-- @
+-- askEBird $ taxonomicGroups "ebird" def
+-- @
+--
+-- See the [eBird API documentation for the corresponding
+-- endpoint](https://documenter.getpostman.com/view/664302/S1ENwy59#aa9804aa-dbf9-4a53-bbf4-48e214e4677a).
+taxonomicGroups
+  :: SPPGrouping
+  -- ^ 'MerlinGrouping' groups like birds together, with falcons next to hawks,
+  -- while 'EBirdGrouping' groups in taxonomy order
+  -> TaxonomicGroupsParams
+  -- ^ Optional parameters
+  --
+  -- /default: 'defaultTaxonomicGroupsParams'/
+  -> ClientM [TaxonomicGroupListEntry]
+taxonomicGroups r TaxonomicGroupsParams{..} =
+    taxonomicGroups_ r _taxonomicGroupsParamsLocale
+
+-- | Optional parameters accepted by the 'TaxonomicGroupsAPI'.
+--
+-- Note that 'defaultTaxonomicGroupsParams' (or the 'Default' instance's 'def'
+-- value) may be used to accept the defaults of the eBird API.
+--
+-- Additionally, note that there are optics available for manipulating this
+-- type. For example, if you would like to just set the
+-- '_taxonomicGroupsParamsLocale' field to 'Es':
+--
+-- > def & taxonomicGroupsParamsLocale ?~ Es
+--
+-- Or, using @-XOverloadedLabels@:
+--
+-- > def & #locale ?~ Es
+newtype TaxonomicGroupsParams =
+    TaxonomicGroupsParams
+      { -- | Locale to use for species group names. 'En' is used for any locale
+        -- whose translations are unavailable at this endpoint
+        --
+        -- /default: 'En'/
+        _taxonomicGroupsParamsLocale :: Maybe SPPLocale
+      }
+  deriving (Show, Read, Eq)
+
+-- | Note that this value does not actually use the eBird API default values.
+-- It simply sets every option to 'Nothing', which means we just don't send any
+-- of these parameters to the eBird API and they will use /their own/ defaults.
+defaultTaxonomicGroupsParams :: TaxonomicGroupsParams
+defaultTaxonomicGroupsParams =
+    TaxonomicGroupsParams
+      { _taxonomicGroupsParamsLocale = Nothing
+      }
+
+instance Default TaxonomicGroupsParams where
+  def = defaultTaxonomicGroupsParams
+
+-- ** Optics for 'TaxonomicGroupsParams'
+makeLenses ''TaxonomicGroupsParams
+makeFieldLabels ''TaxonomicGroupsParams
