diff --git a/COPYING b/COPYING
new file mode 100644
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,13 @@
+Copyright © 2011, Stephen Paul Weber <singpolyma.net>
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/Currency/OpenExchangeRates.hs b/Currency/OpenExchangeRates.hs
new file mode 100644
--- /dev/null
+++ b/Currency/OpenExchangeRates.hs
@@ -0,0 +1,42 @@
+module Currency.OpenExchangeRates (fetchRates) where
+
+import Control.Error (readZ, syncIO, fmapLT, hoistEither, throwT, EitherT)
+import Data.String (fromString)
+import qualified Data.Map as Map
+import qualified Data.Text as T
+
+import Data.Aeson ((.:))
+import qualified Data.Aeson as Aeson
+
+import qualified Network.HTTP as HTTP
+import qualified Network.Stream as HTTP
+import qualified Network.URI as URI
+
+import Currency
+import Currency.Rates
+
+newtype OERs = OERs (Rates Currency Double)
+
+instance Aeson.FromJSON OERs where
+	parseJSON (Aeson.Object o) = do
+		ref <- readZ =<< (o .: (T.pack "base"))
+		rs <- fmap Map.toList (o .: (T.pack "rates"))
+		let rs' = map (\(k,v) -> (fromString k, v)) rs
+		return $ OERs $ Rates ref (Map.fromList rs')
+	parseJSON _ = fail "OpenExchangeRates data is an object."
+
+-- | Fetch exchange rates from OpenExchangeRates.org
+fetchRates ::
+	String -- ^ AppID
+	-> EitherT HTTP.ConnError IO (Rates Currency Double)
+fetchRates appid = do
+	resp <- hoistEither =<< (tryHTTP $ HTTP.simpleHTTP req)
+	case resp of
+		(HTTP.Response { HTTP.rspCode = (2,0,0), HTTP.rspBody = body }) -> do
+			OERs rs <- fmapLT HTTP.ErrorMisc $ hoistEither (Aeson.eitherDecode body)
+			return rs
+		_ -> throwT (HTTP.ErrorMisc "Bad HTTP response code.")
+	where
+	tryHTTP = fmapLT (HTTP.ErrorMisc . show) . syncIO
+	req = HTTP.mkRequest HTTP.GET uri
+	Just uri = URI.parseURI $ "http://openexchangerates.org/api/latest.json?app_id=" ++ appid
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/openexchangerates.cabal b/openexchangerates.cabal
new file mode 100644
--- /dev/null
+++ b/openexchangerates.cabal
@@ -0,0 +1,35 @@
+name:            openexchangerates
+version:         0.1.0.0
+cabal-version:   >=1.8
+license:         OtherLicense
+license-file:    COPYING
+copyright:       © 2013 Stephen Paul Weber
+category:        Data
+author:          Stephen Paul Weber <singpolyma@singpolyma.net>
+maintainer:      Stephen Paul Weber <singpolyma@singpolyma.net>
+stability:       experimental
+build-type:      Simple
+homepage:        https://github.com/singpolyma/openexchangerates-haskell
+bug-reports:     http://github.com/singpolyma/openexchangerates-haskell/issues
+synopsis:        Fetch exchange rates from OpenExchangeRates.org
+description:
+        This package wraps up the process of fetching exchange rates from
+        OpenExchangeRates.org.  You will need an AppID.
+
+library
+        exposed-modules:
+                Currency.OpenExchangeRates
+
+        build-depends:
+                base == 4.*,
+                containers,
+                currency,
+                text,
+                aeson >= 0.6.1.0,
+                network,
+                HTTP,
+                errors >= 1.4.2
+
+source-repository head
+        type:     git
+        location: git://github.com/singpolyma/openexchangerates-haskell.git
