diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,12 @@
 
 ## Unreleased
 
+## 0.3.0.1
+
+### Added
+
+- Add `pathEndpoints`, `pathEndpoints2D` and `pathEndpoints3D`
+
 ## 0.3.0.0
 
 ### Changed
diff --git a/src/Waterfall/Path.hs b/src/Waterfall/Path.hs
--- a/src/Waterfall/Path.hs
+++ b/src/Waterfall/Path.hs
@@ -17,6 +17,7 @@
 , bezierRelative3D
 , pathFrom3D
 , pathFromTo3D
+, pathEndpoints3D
 ) where
 
 import Waterfall.Internal.Path (Path(..))
@@ -78,5 +79,8 @@
 pathFromTo3D :: [V3 Double -> (V3 Double, Path)] -> V3 Double -> (V3 Double, Path)
 pathFromTo3D = pathFromTo
 
+-- | `pathEndpoints`, with the type fixed to `Path` 
+pathEndpoints3D :: Path -> (V3 Double, V3 Double)
+pathEndpoints3D = pathEndpoints
 
 
diff --git a/src/Waterfall/Path/Common.hs b/src/Waterfall/Path/Common.hs
--- a/src/Waterfall/Path/Common.hs
+++ b/src/Waterfall/Path/Common.hs
@@ -21,6 +21,7 @@
 , bezierRelative
 , pathFrom
 , pathFromTo
+, pathEndpoints
 ) where
 import Data.Acquire
 import qualified OpenCascade.TopoDS as TopoDS
@@ -28,7 +29,7 @@
 import Foreign.Ptr
 import Waterfall.Internal.Path (Path (..))
 import Waterfall.TwoD.Internal.Path2D (Path2D (..))
-import Waterfall.Internal.Finalizers (unsafeFromAcquire)
+import Waterfall.Internal.Finalizers (unsafeFromAcquire, toAcquire)
 import Control.Arrow (second)
 import Data.Foldable (foldl', traverse_)
 import qualified OpenCascade.BRepBuilderAPI.MakeWire as MakeWire
@@ -39,8 +40,10 @@
 import qualified OpenCascade.NCollection.Array1 as NCollection.Array1
 import qualified OpenCascade.Geom.BezierCurve as BezierCurve
 import Data.Proxy (Proxy (..))
-import Linear (V3 (..), V2 (..))
+import Linear (V3 (..), V2 (..), _xy)
 import qualified OpenCascade.GP.Pnt as GP.Pnt
+import Control.Lens ((^.))
+import Waterfall.Internal.Edges (wireEndpoints)
 
 -- | Class used to abstract over constructing `Path` and `Path2D` 
 -- 
@@ -48,7 +51,9 @@
 -- and for @AnyPath (V2 Double) Path2D@
 class AnyPath point path | path -> point where
     fromWire :: Acquire (Ptr TopoDS.Wire) -> path
+    toWire :: path -> Acquire (Ptr TopoDS.Wire)
     pointToGPPnt :: Proxy path -> point -> Acquire (Ptr GP.Pnt)
+    v3ToPoint :: Proxy path -> V3 Double -> point 
 
 edgesToPath :: (AnyPath point path) => Acquire [Ptr TopoDS.Edge] -> path
 edgesToPath es = fromWire $ do
@@ -161,14 +166,29 @@
         (end, allPaths) = foldl' go (start, []) commands
      in (end, mconcat allPaths)
 
+-- | Returns the start and end of a `Path`
+pathEndpoints :: forall point path. (AnyPath point path) => path -> (point, point)
+pathEndpoints path = unsafeFromAcquire $ do
+    wire <- toWire path
+    (s, e) <- liftIO $ wireEndpoints wire
+    return (v3ToPoint (Proxy :: Proxy path) s, v3ToPoint (Proxy :: Proxy path) e)
+
 instance AnyPath (V3 Double) Path where
     fromWire :: Acquire (Ptr TopoDS.Wire) -> Path
     fromWire = Path . unsafeFromAcquire
     pointToGPPnt :: Proxy Path -> V3 Double -> Acquire (Ptr GP.Pnt)
     pointToGPPnt _ (V3 x y z) = GP.Pnt.new x y z 
+    toWire :: Path -> Acquire (Ptr TopoDS.Wire)
+    toWire (Path ptr) = toAcquire ptr
+    v3ToPoint :: Proxy Path -> V3 Double -> V3 Double
+    v3ToPoint _ = id
 
 instance AnyPath (V2 Double) Path2D where
     fromWire :: Acquire (Ptr TopoDS.Wire) -> Path2D
     fromWire = Path2D . unsafeFromAcquire
     pointToGPPnt :: Proxy Path2D -> V2 Double -> Acquire (Ptr GP.Pnt)
     pointToGPPnt _ (V2 x y) = GP.Pnt.new x y 0
+    toWire :: Path2D -> Acquire (Ptr TopoDS.Wire)
+    toWire (Path2D ptr) = toAcquire ptr
+    v3ToPoint :: Proxy Path2D -> V3 Double -> V2 Double
+    v3ToPoint _  = (^. _xy)
diff --git a/src/Waterfall/TwoD/Path2D.hs b/src/Waterfall/TwoD/Path2D.hs
--- a/src/Waterfall/TwoD/Path2D.hs
+++ b/src/Waterfall/TwoD/Path2D.hs
@@ -23,6 +23,7 @@
 , bezierRelative2D
 , pathFrom2D
 , pathFromTo2D
+, pathEndpoints2D
 ) where 
 
 import Waterfall.TwoD.Internal.Path2D (Path2D(..))
@@ -140,3 +141,7 @@
 -- | `pathFromTo`, with the type fixed to `Path2D`
 pathFromTo2D :: [V2 Double -> (V2 Double, Path2D)] -> V2 Double -> (V2 Double, Path2D)
 pathFromTo2D = pathFromTo
+
+-- | `pathEndpoints`, with the type fixed to `Path2D` 
+pathEndpoints2D :: Path2D -> (V2 Double, V2 Double)
+pathEndpoints2D = pathEndpoints
diff --git a/waterfall-cad.cabal b/waterfall-cad.cabal
--- a/waterfall-cad.cabal
+++ b/waterfall-cad.cabal
@@ -5,7 +5,7 @@
 -- see: https://github.com/sol/hpack
 
 name:           waterfall-cad
-version:        0.3.0.0
+version:        0.3.0.1
 synopsis:       Declarative CAD/Solid Modeling Library
 description:    Please see the README on GitHub at <https://github.com/joe-warren/opencascade-hs#readme>
 category:       Graphics
@@ -65,7 +65,7 @@
     , lattices >=2.0 && <3
     , lens ==5.*
     , linear >=1.21 && <2
-    , opencascade-hs >=0.3.0.0 && <0.4
+    , opencascade-hs >=0.3.0.1 && <0.4
     , primitive >=0.7 && <0.10
     , resourcet >=1.2 && <1.4
   default-language: Haskell2010
