diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,12 @@
 # Changelog
 
+## 0.39
+
+* Add support for versionless APIs, thanks to Tenor Biel. This is a
+  breaking change. Old API users will have to add `Versioned` before
+  their list of api versions, so it becomes `Versioned [ (mkVersion
+  ...) ]`.
+
 ## 0.38
 
 * Add `RawJsonO`, `RawJsonI`, `RawJsonAndXmlI`, and `RawJsonAndXmlO`.
diff --git a/rest-core.cabal b/rest-core.cabal
--- a/rest-core.cabal
+++ b/rest-core.cabal
@@ -1,5 +1,5 @@
 name:                rest-core
-version:             0.38
+version:             0.39
 description:         Rest API library.
 synopsis:            Rest API library.
 maintainer:          code@silk.co
@@ -40,8 +40,8 @@
     Rest.Schema
     Rest.ShowUrl
   build-depends:
-      base >= 4.5 && < 4.9
-    , aeson >= 0.7 && < 0.11
+      base >= 4.5 && < 4.10
+    , aeson >= 0.7 && < 0.12
     , aeson-utils >= 0.2 && < 0.4
     , base-compat >= 0.8 && < 0.10
     , bytestring >= 0.9 && < 0.11
@@ -73,7 +73,7 @@
   main-is:           Runner.hs
   type:              exitcode-stdio-1.0
   build-depends:
-      base >= 4.5 && < 4.9
+      base >= 4.5 && < 4.10
     , HUnit >= 1.2 && < 1.4
     , bytestring >= 0.9 && < 0.11
     , mtl >= 2.0 && < 2.3
diff --git a/src/Rest/Api.hs b/src/Rest/Api.hs
--- a/src/Rest/Api.hs
+++ b/src/Rest/Api.hs
@@ -8,7 +8,8 @@
 -- to generate clients or documentation using 'rest-gen'.
 module Rest.Api
   ( -- * Api data types.
-    Api
+    Api (..)
+  , VersionSet
   , Router (..)
   , Some1 (..)
 
@@ -113,13 +114,21 @@
 instance Show Version where
   show v = show (full v) ++ "." ++ show (major v) ++ maybe "" (\x -> "." ++ show x) (minor v)
 
--- | An API is a list of versioned routers.
+-- | A version set is a list of versioned routers.
 
-type Api m = [(Version, Some1 (Router m))]
+type VersionSet m = [(Version, Some1 (Router m))]
 
+-- | An API can be versioned or unversioned.
+-- A versioned API is a set of versioned routers.
+-- An unversioned API is just a single router.
+
+data Api m where
+    Unversioned :: Some1 (Router m) -> Api m
+    Versioned   :: VersionSet m -> Api m
+
 -- | Get the latest version of an API.
 
-latest :: Api m -> Maybe (Version, Some1 (Router m))
+latest :: VersionSet m -> Maybe (Version, Some1 (Router m))
 latest = headMay . reverse . sortBy (compare `on` fst)
 
 -- | Parse a 'String' as a 'Version'. The string should contain two or
@@ -135,13 +144,13 @@
 -- | Look up a version in an API. The string can either be a valid
 -- version according to 'parseVersion', or "latest".
 
-lookupVersion :: String -> Api m -> Maybe (Some1 (Router m))
+lookupVersion :: String -> VersionSet m -> Maybe (Some1 (Router m))
 lookupVersion "latest" = fmap snd . latest
 lookupVersion str      = (parseVersion str >>=) . flip lookupVersion'
 
 -- | Look up a version in the API.
 
-lookupVersion' :: Version -> Api m -> Maybe (Some1 (Router m))
+lookupVersion' :: Version -> VersionSet m -> Maybe (Some1 (Router m))
 lookupVersion' v versions = best (filter (matches v . fst) versions)
   where best = fmap snd . headMay . sortBy (flip (comparing fst))
         matches :: Version -> Version -> Bool
@@ -160,10 +169,15 @@
 -- * If not parsed or found, return the fallback.
 
 withVersion :: String -> Api m -> r -> (Version -> Some1 (Router m) -> r) -> r
-withVersion ver api err ok =
+withVersion ver (Versioned vrs) err ok =
   maybe err (uncurry ok) $
     case ver of
-      "latest" -> latest api
+      "latest" -> latest vrs
       _        -> do pv <- parseVersion ver
-                     r <- lookupVersion' pv api
+                     r <- lookupVersion' pv vrs
                      return (pv, r)
+withVersion ver (Unversioned r) err ok =
+  maybe err (uncurry ok) $
+    case ver of
+      "latest" -> return (mkVersion 1 0 0, r)
+      _        -> Nothing
diff --git a/src/Rest/Driver/Routing/Internal.hs b/src/Rest/Driver/Routing/Internal.hs
--- a/src/Rest/Driver/Routing/Internal.hs
+++ b/src/Rest/Driver/Routing/Internal.hs
@@ -80,9 +80,12 @@
 
 routeWith :: Config m -> Maybe Method -> UriParts -> Rest.Api m -> Either Reason_ (RunnableHandler m)
 routeWith _    Nothing   _   _   = apiError UnsupportedMethod
-routeWith cfg (Just mtd) uri api = runRouter cfg mtd uri $
-  do versionStr <- popSegment
-     case versionStr `Rest.lookupVersion` api of
+routeWith cfg (Just mtd) uri api = runRouter cfg mtd uri $ do
+  case api of
+    Rest.Unversioned (Some1 router) -> routeRoot router
+    Rest.Versioned   vrs            -> do
+      versionStr <- popSegment
+      case versionStr `Rest.lookupVersion` vrs of
           Just (Some1 router) -> routeRoot router
           _                   -> apiError UnsupportedVersion
 
diff --git a/tests/Runner.hs b/tests/Runner.hs
--- a/tests/Runner.hs
+++ b/tests/Runner.hs
@@ -191,13 +191,13 @@
 
 checkRouteFailure :: (Applicative m, Monad m) => Method -> Uri -> Rest.Router m s -> Assertion
 checkRouteFailure method uri router =
-  case route (Just method) (splitUriString $ "v1.0/" <> uri) [(Version 1 0 Nothing, Some1 router)] of
+  case route (Just method) (splitUriString $ "v1.0/" <> uri) (Versioned [(Version 1 0 Nothing, Some1 router)]) of
     Left _  -> return ()
     Right _ -> assertFailure ("Should be no route to " ++ show method ++ " " ++ uri ++ ".")
 
 checkRouteSuccess :: (Applicative m, Monad m) => Method -> Uri -> Rest.Router m s -> Assertion
 checkRouteSuccess method uri router =
-  case route (Just method) (splitUriString $ "v1.0/" <> uri) [(Version 1 0 Nothing, Some1 router)] of
+  case route (Just method) (splitUriString $ "v1.0/" <> uri) (Versioned [(Version 1 0 Nothing, Some1 router)]) of
     Left e  -> assertFailure ("No route to " ++ show method ++ " " ++ uri ++ ": " ++ show e)
     Right _ -> return ()
 
