diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,10 +5,14 @@
 The format is based on Keep a Changelog and this project adheres to
 Semantic Versioning.
 
+## [0.1.0.1] - 2025-11-17
+### Added
+- `ScheduleKind`, `scheduleKind`, and `isRecurring` helpers for classifying parsed schedules without re-parsing downstream.
+- QuickCheck properties covering the new helpers to ensure they align with parsed expression variants.
+- README documentation demonstrating schedule introspection and clarifying the helper API.
+
 ## [0.1.0.0] - 2025-11-16
 ### Added
 - Initial `AWS.EventBridge.Cron` module for parsing and scheduling AWS Scheduler cron expressions.
 - Support for `rate(...)` and `at(...)` expressions with validation, evaluation, and round-trip tests.
 - Property-based and unit tests across all cron fields plus helper utilities.
-- Project metadata, README, LICENSE, and Haddock documentation suitable for Hackage distribution.
-- GitHub Actions workflows for CI and release automation, including Hackage candidate/publish steps.
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -13,6 +13,9 @@
   weekday ranges, and nth-weekday modifiers (`2#1`).
 - `rate(...)` and `at(...)` expressions share the same API, so callers do not
   need to branch on expression variants.
+- Schedule introspection helpers: `scheduleKind` returns a `ScheduleKind`, and
+  `isRecurring` distinguishes recurring (`cron`/`rate`) expressions from
+  `at(...)` one-time schedules.
 - Extensive property-based test suite that mirrors the behaviour documented by
   AWS.
 
@@ -58,6 +61,15 @@
 atExample = do
   expr <- parseCronText "at(2025-11-16T09:30:00)"
   nextRunTimes expr base 5
+
+-- Introspect the parsed expression without re-parsing downstream.
+kindExample :: Either String ScheduleKind
+kindExample = scheduleKind <$> parseCronText "rate(5 minutes)"
+-- Right RateSchedule
+
+isRecurringExample :: Either String Bool
+isRecurringExample = isRecurring <$> parseCronText "at(2025-11-16T09:30:00)"
+-- Right False
 ```
 
 ### Error Reporting
diff --git a/aws-eventbridge-cron.cabal b/aws-eventbridge-cron.cabal
--- a/aws-eventbridge-cron.cabal
+++ b/aws-eventbridge-cron.cabal
@@ -1,7 +1,7 @@
 cabal-version:      3.0
 
 name:               aws-eventbridge-cron
-version:            0.1.0.0
+version:            0.1.0.1
 synopsis:           AWS EventBridge cron, rate, and one-time parser with scheduler
 description:
   Parse AWS EventBridge cron, rate, and one-time expressions and compute
diff --git a/src/AWS/EventBridge/Cron.hs b/src/AWS/EventBridge/Cron.hs
--- a/src/AWS/EventBridge/Cron.hs
+++ b/src/AWS/EventBridge/Cron.hs
@@ -6,6 +6,9 @@
 -- support for cron, rate, and one-time ("at") expressions.
 module AWS.EventBridge.Cron
   ( CronExprT
+  , ScheduleKind(..)
+  , scheduleKind
+  , isRecurring
   , parseCronText
   , nextRunTimes
   ) where
@@ -29,9 +32,8 @@
 
 -- | EventBridge scheduling expression.
 --
--- Constructors mirror the three families of EventBridge schedules. The structure is
--- exposed to allow pattern matching by advanced users, but most callers should rely on
--- the parser and evaluator helpers provided by this module.
+-- The concrete representation is intentionally opaque; use 'scheduleKind' to detect the
+-- backing schedule family and 'nextRunTimes' to evaluate upcoming occurrences.
 data CronExprT
   = CronExpr
       { minutes    :: MinutesExprT
@@ -44,6 +46,26 @@
   | RateExpr RateExprT
   | OneTimeExpr OneTimeExprT
   deriving (Eq, Show)
+
+-- | Classification of an EventBridge scheduling expression.
+data ScheduleKind
+  = CronSchedule
+  | RateSchedule
+  | OneTimeSchedule
+  deriving (Eq, Ord, Show)
+
+-- | Determine which family of expression a parsed value belongs to.
+scheduleKind :: CronExprT -> ScheduleKind
+scheduleKind CronExpr{}    = CronSchedule
+scheduleKind RateExpr{}    = RateSchedule
+scheduleKind OneTimeExpr{} = OneTimeSchedule
+
+-- | True when the schedule produces multiple occurrences (cron or rate).
+isRecurring :: CronExprT -> Bool
+isRecurring expr =
+  case scheduleKind expr of
+    OneTimeSchedule -> False
+    _               -> True
 
 type Parser = Parsec Void Text
 
diff --git a/test/AWS/EventBridge/CronSpec.hs b/test/AWS/EventBridge/CronSpec.hs
--- a/test/AWS/EventBridge/CronSpec.hs
+++ b/test/AWS/EventBridge/CronSpec.hs
@@ -90,11 +90,60 @@
 propertyTests :: TestTree
 propertyTests = testGroup "properties"
   [ QC.testProperty "rate schedule monotonic" propRateMonotonic
+  , QC.testProperty "schedule kind round-trips for cron" propScheduleKindCron
+  , QC.testProperty "schedule kind round-trips for rate" propScheduleKindRate
+  , QC.testProperty "schedule kind identifies one-time" propScheduleKindOneTime
+  , QC.testProperty "isRecurring agrees with schedule kind" propIsRecurring
   , QC.testProperty "cron returns at most requested" propCronLimit
   , QC.testProperty "cron schedule monotonic and >= base" propCronMonotonic
   , QC.testProperty "cron with '?' dom relies on day-of-week" propCronDomQuestionUsesDow
   , QC.testProperty "cron with '?' dow relies on day-of-month" propCronDowQuestionUsesDom
   ]
+
+propScheduleKindCron :: QC.Property
+propScheduleKindCron =
+  let exprText = "cron(0 0 ? NOV MON 2025)"
+  in case parseCronText exprText of
+      Left err -> QC.counterexample ("cron parse failed: " <> err) False
+      Right expr ->
+        QC.counterexample (show (scheduleKind expr)) (scheduleKind expr QC.=== CronSchedule)
+
+propScheduleKindRate :: QC.Property
+propScheduleKindRate =
+  let exprText = "rate(15 minutes)"
+  in case parseCronText exprText of
+      Left err -> QC.counterexample ("rate parse failed: " <> err) False
+      Right expr ->
+        QC.counterexample (show (scheduleKind expr)) (scheduleKind expr QC.=== RateSchedule)
+
+propScheduleKindOneTime :: QC.Property
+propScheduleKindOneTime =
+  let exprText = "at(2025-11-16T09:30:00)"
+  in case parseCronText exprText of
+      Left err -> QC.counterexample ("at parse failed: " <> err) False
+      Right expr ->
+        QC.counterexample (show (scheduleKind expr)) (scheduleKind expr QC.=== OneTimeSchedule)
+
+propIsRecurring :: QC.Property
+propIsRecurring =
+  QC.conjoin
+    [ QC.counterexample "cron should be recurring" cronRecurring
+    , QC.counterexample "rate should be recurring" rateRecurring
+    , QC.counterexample "one-time should not be recurring" oneTimeNonRecurring
+    ]
+  where
+    cronRecurring =
+      case parseCronText "cron(0 12 ? JAN MON 2025)" of
+        Right expr -> isRecurring expr
+        Left _ -> False
+    rateRecurring =
+      case parseCronText "rate(1 hour)" of
+        Right expr -> isRecurring expr
+        Left _ -> False
+    oneTimeNonRecurring =
+      case parseCronText "at(2025-11-16T09:30:00)" of
+        Right expr -> not (isRecurring expr)
+        Left _ -> False
 
 propRateMonotonic :: QC.Property
 propRateMonotonic =
