diff --git a/Database/HSparql/Connection.hs b/Database/HSparql/Connection.hs
--- a/Database/HSparql/Connection.hs
+++ b/Database/HSparql/Connection.hs
@@ -4,6 +4,7 @@
     , selectQuery
     , constructQuery
     , askQuery
+    , updateQuery
     , describeQuery
     )
 where
@@ -73,6 +74,12 @@
   | s == "false" = False
   | otherwise = error $ "Unexpected Ask response: " ++ s
 
+-- |Parses the response from a SPARQL UPDATE query.  An empty body is expected
+parseUpdate :: String -> Bool
+parseUpdate s
+  | s == "" = True
+  | otherwise = error $ "Unexpected Update response: " ++ s
+
 -- |Connect to remote 'EndPoint' and find all possible bindings for the
 --  'Variable's in the 'SelectQuery' action.
 selectQuery :: Database.HSparql.Connection.EndPoint -> Query SelectQuery -> IO (Maybe [[BindingValue]])
@@ -96,6 +103,25 @@
         request  = replaceHeader HdrUserAgent "hsparql-client" (getRequest uri)
     response <- simpleHTTP request >>= getResponseBody
     return $ parseAsk response
+
+
+-- |Connect to remote 'EndPoint' and find all possible bindings for the
+--  'Variable's in the 'SelectQuery' action.
+updateQuery :: Database.HSparql.Connection.EndPoint -> Query UpdateQuery -> IO Bool
+updateQuery ep q = do
+    let uri = ep
+        body = createUpdateQuery q
+        h1 = mkHeader HdrContentLength $ show (length body)
+        h2 = mkHeader HdrContentType "application/sparql-update"
+        h3 = mkHeader HdrUserAgent "hsparql-client"
+        request = Request { rqURI = fromJust $ parseURI uri
+                          , rqHeaders = [h1,h2,h3]
+                          , rqMethod = POST
+                          , rqBody = body
+                          }
+    response <- simpleHTTP request >>= getResponseBody
+--    return $ structureContent response
+    return $ parseUpdate response
 
 
 -- |Connect to remote 'EndPoint' and construct 'TriplesGraph' from given
diff --git a/Database/HSparql/QueryGenerator.hs b/Database/HSparql/QueryGenerator.hs
--- a/Database/HSparql/QueryGenerator.hs
+++ b/Database/HSparql/QueryGenerator.hs
@@ -6,6 +6,7 @@
       createSelectQuery
     , createConstructQuery
     , createAskQuery
+    , createUpdateQuery
     , createDescribeQuery
     -- * Query Actions
     , prefix
@@ -13,6 +14,7 @@
     , Database.HSparql.QueryGenerator.triple
     , constructTriple
     , askTriple
+    , updateTriple
     , describeIRI
     , optional
     , union
@@ -65,6 +67,7 @@
     , SelectQuery(..)
     , ConstructQuery(..)
     , AskQuery(..)
+    , UpdateQuery(..)
     , DescribeQuery(..)
     )
 where
@@ -108,6 +111,14 @@
            query <- q
            modify $ \s -> s { askTriples = queryAsk query, queryType = AskType }
 
+-- |Execute a 'Update Query' action, returning the 'String' representation of the query.
+createUpdateQuery :: Query UpdateQuery -> String
+createUpdateQuery q = execQuery specifyType qshow
+    where specifyType :: Query ()
+          specifyType = do
+           query <- q
+           modify $ \s -> s { updateTriples = queryUpdate query, queryType = UpdateType }
+
 -- |Execute a 'Describe Query' action, returning the 'String' representation of the query.
 createDescribeQuery :: Query DescribeQuery -> String
 createDescribeQuery q = execQuery specifyType qshow
@@ -152,6 +163,12 @@
     modify $ \s -> s { askTriples = appendTriple t (askTriples s) }
     return t
 
+updateTriple :: (TermLike a, TermLike b, TermLike c) => a -> b -> c -> Query Pattern
+updateTriple a b c = do
+    let t = QTriple (varOrTerm a) (varOrTerm b) (varOrTerm c) -- TODO: should only allow terms
+    modify $ \s -> s { updateTriples = appendTriple t (updateTriples s) }
+    return t
+
 describeIRI :: IRIRef -> Query IRIRef
 describeIRI newIri = do
     modify $ \s -> s { describeURI = Just newIri }
@@ -192,6 +209,7 @@
 (.:.) :: Prefix -> T.Text -> IRIRef
 (.:.) = PrefixedName
 
+
 -- Duplicate handling
 
 -- |Set duplicate handling to 'Distinct'. By default, there are no reductions.
@@ -366,6 +384,7 @@
     , pattern    = GroupGraphPattern []
     , constructTriples = []
     , askTriples = []
+    , updateTriples = []
     , describeURI = Nothing
     , duplicates = NoLimits
     , ordering   = []
@@ -448,15 +467,16 @@
     , pattern    :: GroupGraphPattern
     , constructTriples :: [Pattern] -- QTriple
     , askTriples :: [Pattern]
+    , updateTriples :: [Pattern]
     , describeURI :: Maybe IRIRef
     , duplicates :: Duplicates
     , ordering   :: [OrderBy]
     }
 
 
-data QueryType = SelectType | ConstructType | AskType | DescribeType | TypeNotSet
+data QueryType = SelectType | ConstructType | AskType | UpdateType | DescribeType | TypeNotSet
 
-data QueryForm = SelectForm QueryData | ConstructForm QueryData | AskForm QueryData | DescribeForm QueryData
+data QueryForm = SelectForm QueryData | ConstructForm QueryData | AskForm QueryData | UpdateForm QueryData | DescribeForm QueryData
 
 data ConstructQuery = ConstructQuery
     { queryConstructs :: [Pattern] }
@@ -464,6 +484,9 @@
 data AskQuery = AskQuery
     { queryAsk :: [Pattern] }
 
+data UpdateQuery = UpdateQuery
+    { queryUpdate :: [Pattern] }
+
 data SelectQuery = SelectQuery
     { queryVars :: [Variable] }
 
@@ -580,6 +603,8 @@
 
   qshow (AskForm qd) = "ASK { " ++ qshow (askTriples qd) ++ " }"
 
+  qshow (UpdateForm qd) = "INSERT DATA { " ++ qshow (updateTriples qd) ++ " }"
+
   qshow (DescribeForm qd) = "DESCRIBE " ++ qshow (describeURI qd)
 
 instance QueryShow QueryData where
@@ -609,6 +634,10 @@
                   AskType -> 
                    unwords [ qshow (prefixes qd)
                            , qshow (AskForm qd)
+                           ]
+                  UpdateType -> 
+                   unwords [ qshow (prefixes qd)
+                           , qshow (UpdateForm qd)
                            ]
              in query
 
diff --git a/hsparql.cabal b/hsparql.cabal
--- a/hsparql.cabal
+++ b/hsparql.cabal
@@ -1,12 +1,12 @@
 Name:          hsparql
 Homepage:      https://github.com/robstewart57/hsparql
-Version:       0.2.3
+Version:       0.2.4
 Synopsis:      A SPARQL query generator and DSL, and a client to query a SPARQL server.
 Category:      Database
 Description:
     hsparql includes a DSL to easily create queries, as well as methods to
     submit those queries to a SPARQL server, returning the results as simple
-    Haskell data structures.
+    Haskell data structures. Supports SELECT, CONSTRUCT, ASK and UPDATE queries.
 
     Example queries are included in the tests:
       <https://github.com/robstewart57/hsparql/blob/master/tests/DBPedia.hs>.
@@ -46,7 +46,7 @@
                  , HUnit
                  , test-framework
                  , test-framework-hunit
-                 , wai
+                 , wai >= 2.0.0
                  , warp
   hs-source-dirs: Database, tests
   extensions:  OverloadedStrings, FlexibleInstances
diff --git a/tests/AllTests.hs b/tests/AllTests.hs
--- a/tests/AllTests.hs
+++ b/tests/AllTests.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE OverloadedStrings #-}
 
 module Main where
 
@@ -31,7 +32,7 @@
                                                 -> describeResponse
                                         otherwise
                                                 -> error "Unexpected URI"
-                    selectResponse = ResponseFile status200 [("Content-Type", "application/sparql-results+xml")] "tests/fixtures/sparql_select_response.xml" Nothing
-                    askResponse = ResponseFile status200 [("Content-Type", "text/plain")] "tests/fixtures/sparql_ask_response.text" Nothing
-                    constructResponse = ResponseFile status200 [("Content-Type", "text/turtle")] "tests/fixtures/sparql_construct_response.ttl" Nothing
-                    describeResponse = ResponseFile status200 [("Content-Type", "text/turtle")] "tests/fixtures/sparql_describe_response.ttl" Nothing
+                    selectResponse = responseFile status200 [("Content-Type", "application/sparql-results+xml")] "tests/fixtures/sparql_select_response.xml" Nothing
+                    askResponse = responseFile status200 [("Content-Type", "text/plain")] "tests/fixtures/sparql_ask_response.text" Nothing
+                    constructResponse = responseFile status200 [("Content-Type", "text/turtle")] "tests/fixtures/sparql_construct_response.ttl" Nothing
+                    describeResponse = responseFile status200 [("Content-Type", "text/turtle")] "tests/fixtures/sparql_describe_response.ttl" Nothing
