diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2013 Daniel Torok
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/Plotserver/Api.hs b/Plotserver/Api.hs
new file mode 100644
--- /dev/null
+++ b/Plotserver/Api.hs
@@ -0,0 +1,50 @@
+{-# LANGUAGE NamedFieldPuns  #-}
+
+module Plotserver.Api (
+	plotUrl, plotCat, plotUpdate, plotDelete
+	) where
+
+import Network.Curl
+import Control.Applicative ((<$>))
+
+import Plotserver.Types
+
+------ API ------
+
+plotUrl :: PlotConfig -> String -> String
+plotUrl (PlotConfig {server}) dataset = server ++ "/" ++ dataset
+
+plotCat :: PlotConfig -> String -> IO (Either String PlotData)
+plotCat config dataset = response2either <$> curlGetResponse_ url_ opts where
+	url_ = actionUrl config dataset "download"
+	opts = defaultOpts config
+
+plotUpdate :: PlotConfig -> String -> PlotDataRow -> IO (Either String PlotData)
+plotUpdate config dataset row = response2either <$> curlGetResponse_ url_ opts where
+	postData = show $ PlotData [row]
+	url_ = actionUrl config dataset "update"
+	opts = defaultOpts config ++ [
+		CurlPost True,
+		CurlPostFields [postData]
+		]
+
+plotDelete :: PlotConfig -> String -> IO (Either String PlotData)
+plotDelete config dataset = response2either <$> curlGetResponse_ url_ opts where
+	url_ = actionUrl config dataset "delete"
+	opts = defaultOpts config
+
+------ helpers ------
+
+defaultOpts :: PlotConfig -> [CurlOption]
+defaultOpts PlotConfig {username, password} = [
+		CurlUserPwd (username ++ ":" ++ password)
+	]
+
+actionUrl :: PlotConfig -> String -> String -> String
+actionUrl config dataset action = plotUrl config dataset ++ "?" ++ action
+
+response2either :: CurlResponse_ [(String, String)] String -> Either String PlotData
+response2either response 
+	| respStatus response == 200 = Right $ (read (respBody response) :: PlotData)
+	| otherwise = Left err where
+		err = "Error: " ++ show (respStatus response)
diff --git a/Plotserver/Types.hs b/Plotserver/Types.hs
new file mode 100644
--- /dev/null
+++ b/Plotserver/Types.hs
@@ -0,0 +1,35 @@
+module Plotserver.Types where
+
+import Data.List (intercalate)
+import Data.List.Split (splitOn)
+import Data.Traversable
+
+-- TODO what if there isn't any password?
+data PlotConfig = PlotConfig {
+	server :: String,
+	username :: String,
+	password :: String
+}
+
+data PlotData = PlotData [PlotDataRow]
+type PlotDataRow = (String, [Int])
+
+instance Show PlotData where
+	show (PlotData rows) = intercalate "\n" $ map showRow rows where
+				showRow :: (String, [Int]) -> String
+				showRow (key, values) = key ++ ", " ++ showValues values
+
+				showValues :: [Int] -> String
+				showValues values = intercalate ", " (map show values)
+
+instance Read PlotData where
+	readsPrec _ s = case dataRows of
+							Just dataRows' -> [(PlotData dataRows', "")]
+							Nothing -> []
+	 where
+		rows = filter (not.null) $ splitOn "\n" s
+		dataRows = traverse createDataRow rows :: Maybe [PlotDataRow]
+		createDataRow row = createDataTuple $ splitOn "," row :: Maybe PlotDataRow
+
+		createDataTuple [] = Nothing
+		createDataTuple (key:sValues) = Just (key, map read sValues) :: Maybe PlotDataRow -- just for the readibility
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/plotserver-api.cabal b/plotserver-api.cabal
new file mode 100644
--- /dev/null
+++ b/plotserver-api.cabal
@@ -0,0 +1,23 @@
+Name:              plotserver-api
+Version:           0.1
+Synopsis:          Plotserver API
+Description:       A lightweight API for Prezi's opensourced Plotserver (https://github.com/prezi/plotserver)
+License:           MIT
+License-file:      LICENSE
+Author:            Daniel Torok
+Maintainer:        daniel.torok@prezi.com
+Category:          API
+Build-Type:        Simple
+Cabal-Version:     >= 1.6
+
+Source-repository head
+  Type:            git
+  Location:        https://github.com/dtorok/plotserver-hsapi
+
+Library
+  Build-Depends:   base >= 3 && < 5,
+                   curl,
+                   split
+  Exposed-modules: Plotserver.Api, Plotserver.Types
+  extensions:      OverloadedStrings
+  ghc-options:     -Wall
