diff --git a/CHANGELOG b/CHANGELOG
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,10 @@
 # Changelog
 
+- 0.2.0 (2025-02-27)
+  * 'seed' now validates the words in the mnemonic supplied to it;
+    'seed_unsafe' has been added as a function that works for any
+    wordlist.
+
 - 0.1.1 (2025-02-27)
   * Include wordlists in generated Haddocks.
 
diff --git a/lib/Crypto/KDF/BIP39.hs b/lib/Crypto/KDF/BIP39.hs
--- a/lib/Crypto/KDF/BIP39.hs
+++ b/lib/Crypto/KDF/BIP39.hs
@@ -22,6 +22,7 @@
   -- * Seed derivation
   , seed
   , _seed
+  , seed_unsafe
 
   -- * Wordlists
   , Wordlist(..)
@@ -65,15 +66,17 @@
 -- | Generate a BIP39 mnemonic from some entropy, using the default English
 --   wordlist.
 --
---   The entropy must be at least 128 bits long, at most 256 bits long,
---   and its length must be a multiple of 32 bits. Providing invalid
---   entropy will result in an 'ErrorCall' exception.
+--   The entropy must be at least 128 bits long and at most 256 bits
+--   long. Providing invalid entropy will result in an 'ErrorCall'
+--   exception.
 --
 --   >>> import qualified System.Entropy as E
 --   >>> trop <- E.getEntropy 16
 --   >>> mnemonic trop
 --   "coral maze mimic half fat breeze thought club give brass bone snake"
-mnemonic :: BS.ByteString -> T.Text
+mnemonic
+  :: BS.ByteString -- ^ 128-256 bits of entropy
+  -> T.Text
 mnemonic = _mnemonic english
 
 -- | Generate a BIP39 mnemonic from some entropy, using the provided
@@ -87,7 +90,10 @@
 --   >>> trop <- E.getEntropy 16
 --   >>> _mnemonic czech trop
 --   "naslepo lysina dikobraz slupka beseda rorejs ostraha kobliha napevno blahobyt kazivost jiskra"
-_mnemonic :: Wordlist -> BS.ByteString -> T.Text
+_mnemonic
+  :: Wordlist
+  -> BS.ByteString -- ^ 128-256 bits of entropy
+  -> T.Text
 _mnemonic (Wordlist wlist) entropy@(BI.PS _ _ l)
   | l < 16 = error "ppad-bip39 (mnemonic): invalid entropy length"
   | l > 32 = error "ppad-bip39 (mnemonic): invalid entropy length"
@@ -124,6 +130,69 @@
         Nothing
 {-# INLINE words #-}
 
+-- | Derive a master seed from a provided mnemonic and passphrase, where the
+--   mnemonic has been generated from the default English wordlist.
+--
+--   The mnemonic's length and words are validated. If you want to
+--   validate the mnemonic's words against a non-English wordlist, use
+--   '_seed'.
+--
+--   >>> let mnem = "coral maze mimic half fat breeze thought club give brass bone snake"
+--   >>  let pass = "hunter2"
+--   >>> seed mnem pass
+--   <512-bit long seed>
+seed
+  :: T.Text        -- ^ mnemonic
+  -> T.Text        -- ^ passphrase (use e.g. "" or 'mempty' if not required)
+  -> BS.ByteString -- ^ seed
+seed = _seed english
+
+-- | Derive a master seed from a provided mnemonic and passphrase, where the
+--   mnemonic has been generated from an arbitrary wordlist.
+--
+--   The provided mnemonic is checked for validity using '_valid'.
+--   Providing an invalid mnemonic will result in an 'ErrorCall'
+--   exception.
+--
+--   >>> let mnem = "coral maze mimic half fat breeze thought club give brass bone snake"
+--   >>  let pass = "hunter2"
+--   >>> _seed english mnem pass
+--   <512-bit long seed>
+_seed
+  :: Wordlist      -- ^ wordlist
+  -> T.Text        -- ^ mnemonic
+  -> T.Text        -- ^ passphrase (use e.g. "" or 'mempty' if not required)
+  -> BS.ByteString -- ^ seed
+_seed wlist mnem pass
+  | not (_valid wlist mnem) =
+      error "ppad-bip39 (seed): invalid mnemonic"
+  | otherwise =
+      let salt = TE.encodeUtf8 ("mnemonic" <> ICU.nfkd pass)
+          norm = TE.encodeUtf8 (ICU.nfkd mnem)
+      in  PBKDF.derive SHA512.hmac norm salt 2048 64 where
+{-# INLINE _seed #-}
+
+-- | Derive a master seed from a provided mnemonic and passphrase.
+--
+--   The mnemonic's length is validated, but its individual words are
+--   /not/. This function thus works for every wordlist.
+--
+--   >>> let mnem = "coral maze mimic half fat breeze thought club give brass bone snake"
+--   >>  let pass = "hunter2"
+--   >>> seed_unsafe mnem pass
+--   <512-bit long seed>
+seed_unsafe
+  :: T.Text        -- ^ mnemonic
+  -> T.Text        -- ^ passphrase (use e.g. "" or 'mempty' if not required)
+  -> BS.ByteString -- ^ seed
+seed_unsafe mnem pass
+  | length (T.words mnem) `notElem` [12, 15, 18, 21, 24] =
+      error "ppad-bip39 (seed_unsafe): invalid mnemonic"
+  | otherwise =
+      let salt = TE.encodeUtf8 ("mnemonic" <> ICU.nfkd pass)
+          norm = TE.encodeUtf8 (ICU.nfkd mnem)
+      in  PBKDF.derive SHA512.hmac norm salt 2048 64 where
+
 -- | Validate a mnemonic against the default English wordlist.
 --
 --   Verifies that the mnemonic has a valid length, and that every word
@@ -133,7 +202,9 @@
 --   True
 --   >>> valid "coral maze mimic half fat breeze thought club give brass bone"
 --   False
-valid :: T.Text -> Bool
+valid
+  :: T.Text -- ^ mnemonic
+  -> Bool   -- ^ 'True' if valid
 valid mnem =
        length ws `elem` [12, 15, 18, 21, 24]
     && all M.isJust (fmap (\word -> F.find (== word) wlist) ws)
@@ -151,51 +222,15 @@
 --   True
 --   >>> _valid chinese_simplified mnem
 --   False
-_valid :: Wordlist -> T.Text -> Bool
+_valid
+  :: Wordlist
+  -> T.Text   -- ^ mnemonic
+  -> Bool     -- ^ 'True' if valid
 _valid (Wordlist wlist) mnem =
        length ws `elem` [12, 15, 18, 21, 24]
     && all M.isJust (fmap (\word -> F.find (== word) wlist) ws)
   where
     ws = T.words mnem
-
--- | Derive a master seed from a provided mnemonic and passphrase.
---
---   The mnemonic's length is validated, but its individual words are
---   /not/. If you want to validate the mnemonic's words against a
---   wordlist, use '_seed'.
---
---   >>> let mnem = "coral maze mimic half fat breeze thought club give brass bone snake"
---   >>  let pass = "hunter2"
---   >>> seed mnem pass
---   <512-bit long seed>
-seed :: T.Text -> T.Text -> BS.ByteString
-seed mnem pass
-  | length (T.words mnem) `notElem` [12, 15, 18, 21, 24] =
-      error "ppad-bip39 (seed): invalid mnemonic"
-  | otherwise =
-      let salt = TE.encodeUtf8 ("mnemonic" <> ICU.nfkd pass)
-          norm = TE.encodeUtf8 (ICU.nfkd mnem)
-      in  PBKDF.derive SHA512.hmac norm salt 2048 64 where
-
--- | Derive a master seed from a provided mnemonic and passphrase, where the
---   mnemonic has been generated from an arbitrary wordlist.
---
---   The provided mnemonic is checked for validity using '_valid'.
---   Providing an invalid mnemonic will result in an 'ErrorCall'
---   exception.
---
---   >>> let mnem = "coral maze mimic half fat breeze thought club give brass bone snake"
---   >>  let pass = "hunter2"
---   >>> _seed english mnem pass
---   <512-bit long seed>
-_seed :: Wordlist -> T.Text -> T.Text -> BS.ByteString
-_seed wlist mnem pass
-  | not (_valid wlist mnem) =
-      error "ppad-bip39 (seed): invalid mnemonic"
-  | otherwise =
-      let salt = TE.encodeUtf8 ("mnemonic" <> ICU.nfkd pass)
-          norm = TE.encodeUtf8 (ICU.nfkd mnem)
-      in  PBKDF.derive SHA512.hmac norm salt 2048 64 where
 
 -- wordlists ------------------------------------------------------------------
 
diff --git a/ppad-bip39.cabal b/ppad-bip39.cabal
--- a/ppad-bip39.cabal
+++ b/ppad-bip39.cabal
@@ -1,6 +1,6 @@
 cabal-version:      3.0
 name:               ppad-bip39
-version:            0.1.1
+version:            0.2.0
 synopsis:           BIP39 mnemonic codes.
 license:            MIT
 license-file:       LICENSE
diff --git a/test/Main.hs b/test/Main.hs
--- a/test/Main.hs
+++ b/test/Main.hs
@@ -76,8 +76,8 @@
         seed = bt_seed
         xprv = bt_xprv
         out_mnem = BIP39._mnemonic wl entr
-        giv_seed = BIP39.seed mnem "TREZOR"
-        out_seed = BIP39.seed out_mnem "TREZOR"
+        giv_seed = seed_fn mnem "TREZOR"
+        out_seed = seed_fn out_mnem "TREZOR"
         out_xprv = case BIP32.master out_seed of
           Just hd -> BIP32.xprv hd
           Nothing -> error "bang (bip32)"
@@ -93,6 +93,9 @@
       , testCase "xprv" $ assertEqual mempty xprv out_xprv
       ]
   where
+    seed_fn = case wlist of
+      English -> BIP39.seed
+      _ -> BIP39.seed_unsafe
     wl = case wlist of
       English -> BIP39.english
       ChineseTraditional -> BIP39.chinese_traditional
@@ -113,8 +116,8 @@
       seed = jp_seed
       xprv = jp_xprv
       out_mnem = BIP39._mnemonic BIP39.japanese entr
-      giv_seed = BIP39.seed mnem pass
-      out_seed = BIP39.seed out_mnem pass
+      giv_seed = BIP39.seed_unsafe mnem pass
+      out_seed = BIP39.seed_unsafe out_mnem pass
       out_xprv = case BIP32.master out_seed of
         Just hd -> BIP32.xprv hd
         Nothing -> error "bang (bip32, jp)"
