diff --git a/app/Application.hs b/app/Application.hs
--- a/app/Application.hs
+++ b/app/Application.hs
@@ -19,6 +19,7 @@
 import Network.Wai.Logger (clockDateCacher)
 import Data.Default (def)
 import Yesod.Core.Types (loggerSet, Logger (Logger))
+import Network.Wai.Middleware.MethodOverride (methodOverride)
 
 -- Import all relevant handler modules here.
 -- Don't forget to add new modules to your cabal file!
@@ -58,7 +59,7 @@
                 else Apache FromSocket
         , destination = RequestLogger.Logger $ loggerSet $ appLogger foundation
         }
-    
+
     -- register all notification callbacks
     -- we need a handler to resolve the Route URL
     -- so we use runFakeHandler, because all the caveats the doc outlines don't apply to us
@@ -66,10 +67,12 @@
     err<-runFakeHandler M.empty appLogger foundation (registerAllMPCallbacks MPHookR)
     print err
     hFlush stdout
-    
+
     -- Create the WAI application and apply middlewares
+    -- Using MethodOverride middleware to allow PUT forms see:
+    -- http://stackoverflow.com/questions/22902419
     app <- toWaiAppPlain foundation
-    return $ logWare app
+    return $ logWare $ methodOverride app
 
 -- | Loads up any necessary settings, creates your foundation datatype, and
 -- performs some initialization.
@@ -79,7 +82,7 @@
     s <- staticSite
     loggerSet' <- newStdoutLoggerSet defaultBufSize
     (getter, updater) <- clockDateCacher
-    iorToken<-newIORef Nothing 
+    iorToken<-newIORef Nothing
     iorEvents<-newIORef []
     -- If the Yesod logger (as opposed to the request logger middleware) is
     -- used less than once a second on average, you may prefer to omit this
diff --git a/app/Base/Util.hs b/app/Base/Util.hs
--- a/app/Base/Util.hs
+++ b/app/Base/Util.hs
@@ -16,29 +16,20 @@
 import Web.MangoPay
 
 
-
-
 -- | localized field
 localizedFS :: forall master msg.
             RenderMessage master msg =>
             msg -> FieldSettings master
-localizedFS n=FieldSettings (SomeMessage n) Nothing Nothing Nothing []    
+localizedFS n=FieldSettings (SomeMessage n) Nothing Nothing Nothing []
 
 -- | disabled field
 disabled :: forall master.
               FieldSettings master -> FieldSettings master
 disabled fs= fs{fsAttrs= ("disabled",""):fsAttrs fs}
 
-
--- | disable field if the maybe is just (for fields you can set when creating but not when editing)
-disabledIfJust :: forall t master.
-                    Maybe t -> FieldSettings master -> FieldSettings master
-disabledIfJust (Just _)=disabled
-disabledIfJust _=id
-
--- | show text and identifier for all values of an enum    
+-- | show text and identifier for all values of an enum
 ranges :: forall a. (Bounded a, Enum a, Show a) => [(Text, a)]
-ranges=map (pack . show &&& id) [minBound..maxBound] 
+ranges=map (pack . show &&& id) [minBound..maxBound]
 
 -- | the type of an html form
 type HtmlForm a= Maybe a -> Html -> MForm Handler (FormResult a, Widget)
@@ -56,7 +47,7 @@
     pg<-liftM (fromMaybe "1") $ lookupGetParam "page"
     let Right (i,_)=decimal pg
     return $ Just $ Pagination i 10
-    
+
 -- | previous and next page number
 getPaginationNav :: forall a.
                       Maybe Pagination -> PagedList a -> (Maybe Integer, Maybe Integer)
@@ -68,9 +59,9 @@
               then Just (i-1)
               else Nothing
     in (previous,next)
-getPaginationNav _ _= (Nothing,Nothing)             
+getPaginationNav _ _= (Nothing,Nothing)
 
-    
+
 -- | country field
 countryField :: RenderMessage site FormMessage =>
                   Field (HandlerT site IO) CountryCode
diff --git a/app/Foundation.hs b/app/Foundation.hs
--- a/app/Foundation.hs
+++ b/app/Foundation.hs
@@ -66,7 +66,7 @@
 approotRequest :: App -> Request -> Text
 approotRequest master request
         | pathInfo request==["runFakeHandler", "pathInfo"] = appRoot $ settings master
-        | (not $ null $ pathInfo request) && (head (pathInfo request) == "card") = appRoot $ settings master 
+        | (not $ null $ pathInfo request) && (head (pathInfo request) == "card") = appRoot $ settings master
         | otherwise= ""
 
 -- Please see the documentation for the Yesod typeclass. There are a number
@@ -161,4 +161,4 @@
           let exception=show e
           setTitleI MsgRequestFail
           $(widgetFile "request_fail"))
-        
+
diff --git a/app/Handler/Account.hs b/app/Handler/Account.hs
--- a/app/Handler/Account.hs
+++ b/app/Handler/Account.hs
@@ -12,7 +12,6 @@
   -- no paging, should be reasonable
   accounts<-runYesodMPTToken $ getAll $ listAccounts uid
   defaultLayout $ do
-        aDomId <- newIdent
         setTitleI MsgTitleAccounts
         $(widgetFile "accounts")
 
@@ -21,7 +20,6 @@
 getAccountR uid=do
     (widget, enctype) <- generateFormPost accountForm
     defaultLayout $ do
-        aDomId <- newIdent
         setTitleI MsgTitleAccount
         $(widgetFile "account")
 
@@ -32,21 +30,19 @@
   case result of
     FormSuccess bap->
             catchMP (do
-              _<-runYesodMPTToken $ storeAccount (toBankAccount uid bap)
+              _<-runYesodMPTToken $ createAccount (toBankAccount uid bap)
               setMessageI MsgAccountDone
               redirect $ AccountsR uid
               )
                (\e->do
                 setMessage $ toHtml $ show e
                 defaultLayout $ do
-                  aDomId <- newIdent
                   setTitleI MsgTitleAccount
                   $(widgetFile "account")
                   )
     _ -> do
             setMessageI MsgErrorData
             defaultLayout $ do
-                  aDomId <- newIdent
                   setTitleI MsgTitleAccount
                   $(widgetFile "account")
 
@@ -58,11 +54,11 @@
   ,bapOwnerName :: Text
   ,bapOwnerAddress :: Maybe Text
   }
-  
+
 -- | get the proper BankAccount structure
 toBankAccount :: AnyUserID -> BankAccountPartial -> BankAccount
 toBankAccount uid bap=BankAccount Nothing Nothing (Just uid) (bapTag bap) (IBAN (bapIBAN bap) (bapBIC bap))
-  (bapOwnerName bap) (bapOwnerAddress bap) 
+  (bapOwnerName bap) (bapOwnerAddress bap)
 
 -- | form for bank account
 accountForm :: Html -> MForm Handler (FormResult BankAccountPartial, Widget)
@@ -70,5 +66,5 @@
   <$> aopt textField (localizedFS MsgAccountCustomData) Nothing
   <*> areq textField (localizedFS MsgAccountIBAN) Nothing
   <*> areq textField (localizedFS MsgAccountBIC) Nothing
-  <*> areq textField (localizedFS MsgAccountOwnerName) Nothing          
-  <*> aopt textField (localizedFS MsgAccountOwnerAddress) Nothing            
+  <*> areq textField (localizedFS MsgAccountOwnerName) Nothing
+  <*> aopt textField (localizedFS MsgAccountOwnerAddress) Nothing
diff --git a/app/Handler/Card.hs b/app/Handler/Card.hs
--- a/app/Handler/Card.hs
+++ b/app/Handler/Card.hs
@@ -22,10 +22,9 @@
   cards<-runYesodMPTToken $ getAll $ listCards uid
   ((_,widget), enctype) <- generateFormGet currencyForm
   defaultLayout $ do
-        aDomId <- newIdent
         setTitleI MsgTitleCards
         $(widgetFile "cards")
-        
+
 -- | get card registration form
 -- this form will not be sent to this server, but to the validation server!
 -- we have an iframe in that page
@@ -46,8 +45,8 @@
     case result of
       FormSuccess curr->catchW $ do
         let cr1=mkCardRegistration uid curr
-        -- step 1: store pending registration
-        cr2<-runYesodMPTToken $ storeCardRegistration cr1
+        -- step 1: create pending registration
+        cr2<-runYesodMPTToken $ createCardRegistration cr1
         let Just url = crCardRegistrationURL cr2 -- the url of the validation server
             Just pre = crPreregistrationData cr2
             Just ak = crAccessKey cr2
@@ -55,9 +54,8 @@
         setSession "cardReg" $ toStrict $ toLazyText $ encodeToTextBuilder $ toJSON cr2
         -- generate hidden form
         (widget, enctype) <- generateFormPost cardTokenForm
-       
+
         defaultLayout $ do
-            aDomId <- newIdent
             -- JQuery is useful!
             addScriptRemote "https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"
             setTitleI MsgTitleCard
@@ -75,8 +73,8 @@
 getCard2R =do
   qs<-liftM rawQueryString waiRequest
   respond typePlain qs
-  
--- | this gets the token via JavaScript submission  
+
+-- | this gets the token via JavaScript submission
 postCardR :: AnyUserID -> Handler Html
 postCardR uid=do
   ((result, _), _) <- runFormPost cardTokenForm
@@ -93,7 +91,7 @@
           let ecr=eitherDecode $ fromChunks [TE.encodeUtf8 jcr]
           case ecr of
             Right cr->do
-              _<-runYesodMPTToken $ storeCardRegistration cr{crRegistrationData=Just dat}
+              _<-runYesodMPTToken $ modifyCardRegistration cr{crRegistrationData=Just dat}
               setMessageI MsgCardDone
               redirect $ CardsR uid
             Left err->do
@@ -108,7 +106,7 @@
 -- | token for card registration
 data Token=Token Text
     deriving Show
-        
+
 -- | simple form for card registration
 -- the field is hidden and populated via JavaScript (card.julius)
 cardTokenForm ::   Html -> MForm Handler (FormResult Token, Widget)
@@ -119,4 +117,4 @@
 currencyForm :: Html -> MForm Handler (FormResult Currency, Widget)
 currencyForm = renderDivs $ id
   <$> areq (selectFieldList (map (id &&& id) supportedCurrencies)) (localizedFS MsgCardCurrency) (Just "EUR")
-  
+
diff --git a/app/Handler/Doc.hs b/app/Handler/Doc.hs
--- a/app/Handler/Doc.hs
+++ b/app/Handler/Doc.hs
@@ -16,25 +16,23 @@
 getDocR uid= do
   (widget, enctype) <- generateFormPost uploadForm
   defaultLayout $ do
-        aDomId <- newIdent
         setTitleI MsgTitleDocument
         $(widgetFile "docupload")
 
 -- | upload doc and file and show result
 postDocR :: AnyUserID -> Handler Html
 postDocR uid=do
-   ((result, widget), enctype) <- runFormPost uploadForm
+   ((result, _), _) <- runFormPost uploadForm
    case result of
      FormSuccess (DocUpload fi tag typ)->
         catchMP (do
           let doc=Document Nothing Nothing tag typ (Just CREATED) Nothing Nothing
-          docWritten0<-runYesodMPTToken $ storeDocument uid doc
+          docWritten0<-runYesodMPTToken $ createDocument uid doc
           bs<-liftIO $ runResourceT $ fileSourceRaw fi $$ sinkLbs
-          runYesodMPTToken $ storePage uid (fromJust $ dId docWritten0) $ toStrict bs
+          runYesodMPTToken $ createPage uid (fromJust $ dId docWritten0) $ toStrict bs
           -- setting to validated causes internal server error...
-          docWritten<-runYesodMPTToken $ storeDocument uid (docWritten0{dStatus=Just VALIDATION_ASKED})
+          docWritten<-runYesodMPTToken $ modifyDocument uid (docWritten0{dStatus=Just VALIDATION_ASKED})
           defaultLayout $ do
-            aDomId <- newIdent
             setTitleI MsgDocDone
             $(widgetFile "doc")
           )
diff --git a/app/Handler/Home.hs b/app/Handler/Home.hs
--- a/app/Handler/Home.hs
+++ b/app/Handler/Home.hs
@@ -18,7 +18,6 @@
     let (previous,next)=getPaginationNav pg usersL
     let users=plData usersL
     defaultLayout $ do
-        aDomId <- newIdent
         setTitleI MsgHello
         $(widgetFile "homepage")
 
@@ -28,7 +27,7 @@
   evt<-parseMPNotification
   site <- getYesod
   ok <- runYesodMPTToken $ checkEvent evt
-  when ok $ 
+  when ok $
       -- prepend event to list
       liftIO $ modifyIORef (appEvents site) (evt :)
   -- send simple response
@@ -40,6 +39,5 @@
   site <- getYesod
   events<-liftIO $ readIORef  (appEvents site)
   defaultLayout $ do
-      aDomId <- newIdent
       setTitleI MsgTitleEvents
       $(widgetFile "events")
diff --git a/app/Handler/Transaction.hs b/app/Handler/Transaction.hs
--- a/app/Handler/Transaction.hs
+++ b/app/Handler/Transaction.hs
@@ -18,11 +18,10 @@
     let (previous,next)=getPaginationNav pg txsL
     let txs=plData txsL
     defaultLayout $ do
-        aDomId <- newIdent
         setTitleI MsgTitleTransactions
         $(widgetFile "transactions")
-        
 
+
 -- | get payin form
 getPayinR :: AnyUserID -> Handler Html
 getPayinR uid=do
@@ -30,7 +29,6 @@
     wallets<-runYesodMPTToken $ getAll $ listWallets uid
     (widget, enctype) <- generateFormPost $ payinInForm cards wallets
     defaultLayout $ do
-        aDomId <- newIdent
         setTitleI MsgTitlePayIn
         $(widgetFile "payin")
 
@@ -39,27 +37,25 @@
 postPayinR uid=do
   cards<-runYesodMPTToken $ getAll $ listCards uid
   wallets<-runYesodMPTToken $ getAll $ listWallets uid
-    
+
   ((result, widget), enctype) <- runFormPost $ payinInForm cards wallets
   case result of
     FormSuccess (PayIn cid wid am cur)->do
             let cpi=mkCardPayin uid uid wid (Amount cur am) (Amount cur 0) "http://dummy" cid
             catchMP (do
-              _<-runYesodMPTToken $ storeCardPayin cpi
+              _<-runYesodMPTToken $ createCardPayin cpi
               setMessageI MsgPayInDone
               redirect $ TransactionsR uid
               )
               (\e->do
                 setMessage $ toHtml $ show e
                 defaultLayout $ do
-                  aDomId <- newIdent
                   setTitleI MsgTitlePayIn
                   $(widgetFile "payin")
-              )    
+              )
     _ -> do
             setMessageI MsgErrorData
             defaultLayout $ do
-                  aDomId <- newIdent
                   setTitleI MsgTitlePayIn
                   $(widgetFile "payin")
 
@@ -68,7 +64,6 @@
 getTransfer1R uid=do
   users<-runYesodMPTToken $ getAll listUsers
   defaultLayout $ do
-        aDomId <- newIdent
         setTitleI MsgTitleTransfer
         $(widgetFile "transfer1")
 
@@ -79,7 +74,6 @@
     toWallets<-runYesodMPTToken $ getAll $ listWallets touid
     (widget, enctype) <- generateFormPost $ transferForm fromWallets toWallets
     defaultLayout $ do
-        aDomId <- newIdent
         setTitleI MsgTitleTransfer
         $(widgetFile "transfer2")
 
@@ -88,7 +82,7 @@
 postTransfer2R uid touid=do
   fromWallets<-runYesodMPTToken $ getAll $ listWallets uid
   toWallets<-runYesodMPTToken $ getAll $ listWallets touid
-    
+
   ((result, widget), enctype) <- runFormPost $ transferForm fromWallets toWallets
   case result of
     FormSuccess (MPTransfer from to am cur)->do
@@ -102,14 +96,12 @@
               (\e->do
                 setMessage $ toHtml $ show e
                 defaultLayout $ do
-                  aDomId <- newIdent
                   setTitleI MsgTitleTransfer
                   $(widgetFile "transfer2")
-              )    
+              )
     _ -> do
             setMessageI MsgErrorData
             defaultLayout $ do
-                  aDomId <- newIdent
                   setTitleI MsgTitleTransfer
                   $(widgetFile "transfer2")
 
@@ -118,10 +110,9 @@
 getPayoutR uid=do
     wallets<-runYesodMPTToken $ getAll $ listWallets uid
     accounts<-runYesodMPTToken $ getAll $ listAccounts uid
-    
+
     (widget, enctype) <- generateFormPost $ payoutForm wallets accounts
     defaultLayout $ do
-        aDomId <- newIdent
         setTitleI MsgTitlePayOut
         $(widgetFile "payout")
 
@@ -130,27 +121,25 @@
 postPayoutR uid=do
   wallets<-runYesodMPTToken $ getAll $ listWallets uid
   accounts<-runYesodMPTToken $ getAll $ listAccounts uid
-    
+
   ((result, widget), enctype) <- runFormPost $ payoutForm wallets accounts
   case result of
     FormSuccess (PayOut wid aid am cur)->do
             let po=mkPayout uid wid (Amount cur am) (Amount cur 0) aid
             catchMP (do
-              _<-runYesodMPTToken $ storePayout po
+              _<-runYesodMPTToken $ createPayout po
               setMessageI MsgPayOutDone
               redirect $ TransactionsR uid
               )
               (\e->do
                 setMessage $ toHtml $ show e
                 defaultLayout $ do
-                  aDomId <- newIdent
                   setTitleI MsgTitlePayOut
                   $(widgetFile "payout")
-              )    
+              )
     _ -> do
             setMessageI MsgErrorData
             defaultLayout $ do
-                  aDomId <- newIdent
                   setTitleI MsgTitlePayOut
                   $(widgetFile "payout")
 
@@ -169,7 +158,7 @@
 
 -- | data necessary for transfer
 data MPTransfer= MPTransfer WalletID WalletID Integer Currency
-  
+
 -- | transfer form
 transferForm :: [Wallet] -> [Wallet] -> Html -> MForm Handler (FormResult MPTransfer, Widget)
 transferForm fromWallets toWallets=renderDivs $ MPTransfer
@@ -188,4 +177,4 @@
   <*> areq (selectFieldList (map ((pack . show . baDetails) &&& (fromJust . baId)) accounts)) (localizedFS MsgPayOutAccount) Nothing
   <*> areq intField (localizedFS MsgPayOutAmount) Nothing
   <*> areq (selectFieldList (map (id &&& id) supportedCurrencies)) (localizedFS MsgPayOutCurrency) Nothing
-  
+
diff --git a/app/Handler/User.hs b/app/Handler/User.hs
--- a/app/Handler/User.hs
+++ b/app/Handler/User.hs
@@ -18,54 +18,73 @@
       let muser=Just nu
       (widget, enctype) <- generateFormPost $ naturalUserForm muser
       defaultLayout $ do
-            aDomId <- newIdent
             setTitleI MsgTitleNUser
-            $(widgetFile "nuser")      
+            let (formMethod, msgFormTitle) = formVariables $ Left muser
+            $(widgetFile "nuser")
     (Right lu)->do
       let muser=Just lu
       (widget, enctype) <- generateFormPost $ legalUserForm muser
       defaultLayout $ do
-            aDomId <- newIdent
+            let (formMethod, msgFormTitle) = formVariables $ Right muser
             setTitleI MsgTitleLUser
-            $(widgetFile "luser")  
+            $(widgetFile "luser")
 
 -- | get a natural user form
 getNUserR :: Handler Html
 getNUserR =do
-  (muser,widget,enctype)<- userGet naturalUserForm fetchNaturalUser 
+  (muser,widget,enctype)<- userGet naturalUserForm fetchNaturalUser
   defaultLayout $ do
-        aDomId <- newIdent
+        let (formMethod, msgFormTitle) = formVariables $ Left muser
         setTitleI MsgTitleNUser
         $(widgetFile "nuser")
 
 -- | post a natural user form
 postNUserR :: Handler Html
 postNUserR = do
-  (muser,widget,enctype)<- userPost naturalUserForm storeNaturalUser 
+  (muser,widget,enctype)<- userPost naturalUserForm createNaturalUser
   defaultLayout $ do
-        aDomId <- newIdent
+        let (formMethod, msgFormTitle) = formVariables $ Left muser
         setTitleI MsgTitleNUser
         $(widgetFile "nuser")
 
+-- | put a natural user form, to modify an existing natural user
+putNUserR :: Handler Html
+putNUserR = do
+  (muser,widget,enctype)<- userPost naturalUserForm modifyNaturalUser
+  defaultLayout $ do
+        setTitleI MsgTitleNUser
+        let (formMethod, msgFormTitle) = formVariables $ Left muser
+        $(widgetFile "nuser")
+
 -- | get a legal user form
 getLUserR :: Handler Html
 getLUserR = do
-  (muser,widget,enctype)<- userGet legalUserForm fetchLegalUser 
+  (muser,widget,enctype)<- userGet legalUserForm fetchLegalUser
   defaultLayout $ do
-        aDomId <- newIdent
+        let (formMethod, msgFormTitle) = formVariables $ Right muser
         setTitleI MsgTitleLUser
         $(widgetFile "luser")
 
 -- | post a legal user form
 postLUserR :: Handler Html
 postLUserR = do
-  (muser,widget,enctype)<- userPost legalUserForm storeLegalUser
+  (muser,widget,enctype)<- userPost legalUserForm createLegalUser
   defaultLayout $ do
-        aDomId <- newIdent
+        let (formMethod, msgFormTitle) = formVariables $ Right muser
         setTitleI MsgTitleLUser
         $(widgetFile "luser")
 
--- | common code for retrieval and form building 
+
+-- | post a legal user form
+putLUserR :: Handler Html
+putLUserR = do
+  (muser,widget,enctype)<- userPost legalUserForm modifyLegalUser
+  defaultLayout $ do
+        let (formMethod, msgFormTitle) = formVariables $ Right muser
+        setTitleI MsgTitleLUser
+        $(widgetFile "luser")
+
+-- | common code for retrieval and form building
 userGet :: HtmlForm a
                  -> (Text -> AccessToken -> MangoPayT Handler a)
                  -> Handler (Maybe a, Widget, Enctype)
@@ -93,7 +112,7 @@
                   (\e->do
                     setMessage $ toHtml $ show e
                     return (Just u)
-                  )    
+                  )
               _ -> do
                 setMessageI MsgErrorData
                 return Nothing
@@ -101,15 +120,15 @@
     return (muser,widget,enctype)
 
 
--- | form for natural user        
+-- | form for natural user
 naturalUserForm ::  HtmlForm NaturalUser
-naturalUserForm muser= renderDivs $ NaturalUser 
+naturalUserForm muser= renderDivs $ NaturalUser
     <$> aopt hiddenField "" (uId <$> muser)
     <*> pure (join $ uCreationDate <$> muser)
     <*> areq textField (localizedFS MsgUserEmail) (uEmail <$> muser)
-    <*> areq textField (localizedFS MsgUserFirst) (uFirstName <$> muser) 
+    <*> areq textField (localizedFS MsgUserFirst) (uFirstName <$> muser)
     <*> areq textField (localizedFS MsgUserLast) (uLastName <$> muser)
-    <*> aopt textField (localizedFS MsgUserAddress) (uAddress <$> muser) 
+    <*> aopt textField (localizedFS MsgUserAddress) (uAddress <$> muser)
     <*> (day2Posix <$> areq (jqueryDayField def
         { jdsChangeYear = True -- give a year dropdown
         , jdsYearRange = "1900:-5" -- 1900 till five years ago
@@ -121,30 +140,36 @@
     <*> aopt textField (localizedFS MsgUserCustomData) (uTag <$> muser)
     <*> aopt textField (disabled $ localizedFS MsgUserProofIdentity) (uProofOfIdentity <$> muser) -- value comes from Documents uploaded
     <*> aopt textField (disabled $ localizedFS MsgUserProofAddress) (uProofOfAddress <$> muser) -- value comes from Documents uploaded
-  where 
+  where
 
 -- | form for legal user
 legalUserForm :: HtmlForm LegalUser
-legalUserForm muser= renderDivs $ LegalUser 
+legalUserForm muser= renderDivs $ LegalUser
     <$> aopt hiddenField "" (lId <$> muser)
     <*> pure (join $ lCreationDate <$> muser)
     <*> areq textField (localizedFS MsgUserEmail) (lEmail <$> muser)
-    <*> areq textField (localizedFS MsgUserName) (lName <$> muser) 
+    <*> areq textField (localizedFS MsgUserName) (lName <$> muser)
     <*> areq (selectFieldList ranges) (localizedFS MsgUserPersonType) (lLegalPersonType <$> muser)
     <*> aopt textField (localizedFS MsgUserHQAddress) (lHeadquartersAddress <$> muser)
     <*> areq textField (localizedFS MsgUserRepFirst) (lLegalRepresentativeFirstName <$> muser)
     <*> areq textField (localizedFS MsgUserRepLast) (lLegalRepresentativeLastName <$> muser)
-    <*> aopt textField (localizedFS MsgUserRepAddress) (lLegalRepresentativeAddress <$> muser)     
-    <*> aopt textField (localizedFS MsgUserRepEmail) (lLegalRepresentativeEmail <$> muser)  
+    <*> aopt textField (localizedFS MsgUserRepAddress) (lLegalRepresentativeAddress <$> muser)
+    <*> aopt textField (localizedFS MsgUserRepEmail) (lLegalRepresentativeEmail <$> muser)
     <*> (day2Posix <$> areq (jqueryDayField def
         { jdsChangeYear = True -- give a year dropdown
         , jdsYearRange = "1900:-5" -- 1900 till five years ago
-        }) (localizedFS MsgUserRepBirthday) (posix2Day <$> lLegalRepresentativeBirthday <$> muser))   
-    <*> areq countryField (localizedFS MsgUserRepNationality) (lLegalRepresentativeNationality <$> muser)  
+        }) (localizedFS MsgUserRepBirthday) (posix2Day <$> lLegalRepresentativeBirthday <$> muser))
+    <*> areq countryField (localizedFS MsgUserRepNationality) (lLegalRepresentativeNationality <$> muser)
     <*> areq countryField (localizedFS MsgUserRepCountry) (lLegalRepresentativeCountryOfResidence <$> muser)
     <*> pure Nothing  -- value comes from Documents uploaded (I think)
-    <*> aopt textField (localizedFS MsgUserCustomData) (lTag <$> muser)  
+    <*> aopt textField (localizedFS MsgUserCustomData) (lTag <$> muser)
     <*> pure Nothing  -- value comes from Documents uploaded
     <*> pure Nothing -- value comes from Documents uploaded
 
-        
+
+formVariables :: Either (Maybe NaturalUser) (Maybe LegalUser) -> (Text, AppMessage)
+formVariables = either (\n -> process $ mid uId n) (\l -> process $ mid lId l)
+  where mid getId mu = do
+              u  <- mu
+              getId u
+        process = maybe ("", MsgUserCreate) (\i -> ("?_method=PUT", MsgUserModify $ i))
diff --git a/app/Handler/Wallet.hs b/app/Handler/Wallet.hs
--- a/app/Handler/Wallet.hs
+++ b/app/Handler/Wallet.hs
@@ -1,10 +1,12 @@
+{-# LANGUAGE ConstraintKinds #-}
 module Handler.Wallet where
 
 import Import
 import Web.MangoPay
 import Yesod.MangoPay
-import Control.Monad (join, liftM)
+import Control.Monad (join)
 import Control.Arrow ((&&&))
+import Data.Text (pack)
 
 -- | get wallet list
 getWalletsR :: AnyUserID -> Handler Html
@@ -12,56 +14,75 @@
   -- no paging, should be reasonable
   wallets<-runYesodMPTToken $ getAll $ listWallets uid
   defaultLayout $ do
-        aDomId <- newIdent
         setTitleI MsgTitleWallets
         $(widgetFile "wallets")
 
--- | get wallet creation/edition form
+-- | get wallet creation form
 getWalletR :: AnyUserID -> Handler Html
-getWalletR uid=do
-    mwid<-lookupGetParam "id"
-    mwallet<-case mwid of
-          Just wid->liftM Just $ runYesodMPTToken $ fetchWallet wid
-          _->return Nothing
-    (widget, enctype) <- generateFormPost $ walletForm mwallet
-    defaultLayout $ do
-        aDomId <- newIdent
+getWalletR uid = readerWallet uid Nothing
+
+-- | get wallet edition form
+getWalletEditR :: AnyUserID -> WalletID -> Handler Html
+getWalletEditR uid wid = do
+  wallet <- runYesodMPTToken $ fetchWallet wid
+  readerWallet uid $ Just wallet
+
+
+-- | helper to generate the proper form given maybe an existing wallet
+readerWallet :: AnyUserID -> Maybe Wallet -> Handler Html
+readerWallet uid mwallet = do
+  (widget, enctype) <- generateFormPost $ walletForm mwallet
+  let mwid = join $ wId <$> mwallet
+  defaultLayout $ do
         setTitleI MsgTitleWallet
         $(widgetFile "wallet")
 
--- | edit/create wallet
-postWalletR :: AnyUserID -> Handler Html
-postWalletR uid=do
-  ((result, widget), enctype) <- runFormPost $ walletForm Nothing
+
+-- | helper to create or modify a wallet
+helperWallet :: (Wallet -> AccessToken -> MangoPayT Handler Wallet) ->
+  Maybe Wallet -> AnyUserID -> Handler Html
+helperWallet fn mw uid=do
+  ((result, _), _) <- runFormPost $ walletForm mw
   mwallet<-case result of
     FormSuccess w->do
             -- set the owner to current user
             let wo= w{wOwners=[uid]}
             catchMP (do
-              wallet<-runYesodMPTToken $ storeWallet wo
+              wallet<-runYesodMPTToken $ fn wo
               setMessageI MsgWalletDone
               return (Just wallet)
               )
               (\e->do
+                $(logError) $ pack $ show e
                 setMessage $ toHtml $ show e
                 return (Just wo)
-              )    
+              )
     _ -> do
             setMessageI MsgErrorData
             return Nothing
-  defaultLayout $ do
-        aDomId <- newIdent
-        setTitleI MsgTitleWallet
-        $(widgetFile "wallet")
-        
--- | form for wallet  
+  readerWallet uid mwallet
+
+
+postWalletR :: AnyUserID -> Handler Html
+postWalletR = helperWallet createWallet Nothing
+
+
+putWalletEditR :: AnyUserID -> WalletID -> Handler Html
+putWalletEditR uid wid = do
+  wallet <- runYesodMPTToken $ fetchWallet wid
+  helperWallet modifyWallet (Just wallet) uid
+
+
+-- | form for wallet
 walletForm ::  HtmlForm Wallet
 walletForm mwallet= renderDivs $ Wallet
     <$> aopt hiddenField "" (wId <$> mwallet)
-    <*> pure (join $ wCreationDate <$> mwallet)        
+    <*> pure (join $ wCreationDate <$> mwallet)
     <*> aopt textField (localizedFS MsgWalletCustomData) (wTag <$> mwallet)
     <*> pure []
     <*> areq textField (localizedFS MsgWalletDescription) (wDescription <$> mwallet)
-    <*> areq (selectFieldList (map (id &&& id) supportedCurrencies)) (disabledIfJust mwallet $ localizedFS MsgWalletCurrency) (wCurrency <$> mwallet)
+    <*> areq (selectFieldList (map (id &&& id) $ maybe supportedCurrencies (\mw -> [wCurrency mw]) mwallet))
+        (localizedFS MsgWalletCurrency) (wCurrency <$> mwallet)
     -- we can't edit the amount anyway, so we show it as disabled and return a const 0 value
     <*> (fmap (const $ Amount "EUR" 0) <$> aopt intField (disabled $ localizedFS MsgWalletBalance) (fmap aAmount <$> wBalance <$> mwallet))
+
diff --git a/app/Import.hs b/app/Import.hs
--- a/app/Import.hs
+++ b/app/Import.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP         #-}
 module Import
     ( module Import
     ) where
diff --git a/src/Yesod/MangoPay.hs b/src/Yesod/MangoPay.hs
--- a/src/Yesod/MangoPay.hs
+++ b/src/Yesod/MangoPay.hs
@@ -7,17 +7,19 @@
 import qualified Yesod.Core as Y
 import qualified Network.HTTP.Conduit as HTTP
 import Data.Time.Clock (UTCTime, getCurrentTime, diffUTCTime, addUTCTime)
-import Data.Text (Text)
+import Data.Text (Text, pack)
 import Data.IORef (IORef, readIORef, writeIORef)
 
 import qualified Data.Map as M
-import Control.Monad (void)
+import Control.Monad (void, forM, liftM)
 import qualified Control.Exception.Lifted as L
 import Database.Persist.TH (derivePersistField)
+import Data.Monoid ((<>))
+import Data.Maybe (catMaybes)
 
 -- | The 'YesodMangoPay' class for foundation datatypes that
 -- support running 'MangoPayT' actions.
-class Y.Yesod site => YesodMangoPay site where
+class YesodMangoPay site where
   -- | The credentials of your app.
   mpCredentials :: site -> Credentials
 
@@ -28,34 +30,40 @@
   -- | Use MangoPay's sandbox if @True@.  The default is @True@ for safety.
   mpUseSandbox :: site -> Bool
   mpUseSandbox _ = True
-  
+
   -- | store the saved access token if we have one
   mpToken :: site -> IORef (Maybe MangoPayToken)
 
-  
+
 -- | Run a 'MangoPayT' action inside a 'Y.GHandler' using your credentials.
 runYesodMPT ::
   (Y.MonadHandler m,MPUsableMonad m, Y.HandlerSite m ~ site, YesodMangoPay site) =>
   MangoPayT m a -> m a
-runYesodMPT act = do
-  site <- Y.getYesod
+runYesodMPT act = Y.getYesod >>= (`runMPT` act)
+
+
+-- | Run a 'MangoPayT', given any instance of YesodMangoPay.
+runMPT :: (MPUsableMonad m, YesodMangoPay site) => site ->
+  MangoPayT m a -> m a
+runMPT site act = do
   let creds   = mpCredentials site
       manager = mpHttpManager site
       apoint  = if mpUseSandbox site then Sandbox else Production
   runMangoPayT creds manager apoint act
 
+
 -- | the MangoPay access token, valid for a certain time only
 data MangoPayToken=MangoPayToken {
   mptToken :: AccessToken -- ^ opaque token
   ,mptExpires :: UTCTime -- ^ expiration date
   }
 
--- | is the given token still valid (True) or has it expired (False)?  
+-- | is the given token still valid (True) or has it expired (False)?
 isTokenValid :: (Y.MonadResource m) =>  MangoPayToken -> m Bool
 isTokenValid mpt=do
   ct<-Y.liftIO getCurrentTime
   return $ diffUTCTime (mptExpires mpt) ct > 0
- 
+
 -- | get the currently stored token if we have one and it's valid, or Nothing otherwise
 getTokenIfValid ::   (YesodMangoPay site,Y.MonadResource m) => site -> m (Maybe MangoPayToken)
 getTokenIfValid site=do
@@ -81,15 +89,16 @@
         Nothing -> fail "getValidToken: You need to provide the cClientSecret on the mpCredentials."
         Just secret-> do
           oat<-runMangoPayT creds manager apoint $
-                  oauthLogin (cClientID creds) secret   
+                  oauthLogin (cClientID creds) secret
           ct<-Y.liftIO getCurrentTime
           -- oaExpires is in second, remove one minute for safety
           let expires=addUTCTime (fromIntegral (oaExpires oat - 60)) ct
           let at=toAccessToken oat
           Y.liftIO $ writeIORef (mpToken site) (Just $ MangoPayToken at expires)
           return $ Just at
-          
--- | same as 'runYesodMPT': runs a MangoPayT computation, but tries to reuse the current token if valid
+
+
+-- | Same as 'runYesodMPT': runs a MangoPayT computation, but tries to reuse the current token if valid.
 runYesodMPTToken ::
   (Y.MonadHandler m,MPUsableMonad m, Y.HandlerSite m ~ site, YesodMangoPay site) =>
   (AccessToken -> MangoPayT m a) -> m a
@@ -98,9 +107,20 @@
   vt<-getValidToken site
   case vt of
     Nothing -> fail "runYesodMPTToken: Could not obtain access token."
-    Just ac-> runYesodMPT $ act ac
+    Just ac-> runMPT site $ act ac
 
 
+-- | Same as 'runMPT': runs a MangoPayT computation, but tries to reuse the current token if valid.
+runMPTToken ::
+  (MPUsableMonad m, YesodMangoPay site) => site ->
+  (AccessToken -> MangoPayT m a) -> m a
+runMPTToken site act = do
+  vt<-getValidToken site
+  case vt of
+    Nothing -> fail "runYesodMPTToken: Could not obtain access token."
+    Just ac-> runMPT site $ act ac
+
+
 -- | register callbacks for each event type on the same url
 -- mango pay does not let register two hooks for the same event, so we replace existing ones
 registerAllMPCallbacks ::  (Y.MonadHandler m,MPUsableMonad m, Y.HandlerSite m ~ site, YesodMangoPay site) =>
@@ -108,40 +128,52 @@
 registerAllMPCallbacks rt=do
   render<-Y.getUrlRender
   let url=render rt
-  $(Y.logInfo) url
-  runYesodMPTToken $ \at-> do
+  $(Y.logInfo) $ "Hooks to url:" <> url
+  site <- Y.getYesod
+  hs <- registerAllMPCallbacksToURL site url
+  void $ forM hs ($(Y.logInfo) . ("Hook: " <>) . pack . show)
+
+
+-- | register callbacks for each event type on the same url
+-- mango pay does not let register two hooks for the same event, so we replace existing ones
+registerAllMPCallbacksToURL ::  (MPUsableMonad m,  YesodMangoPay site) =>
+  site -> Text -> m [Hook]
+registerAllMPCallbacksToURL site url =
+  runMPTToken site $ \at-> do
     -- get all hooks at once
     hooks<-getAll listHooks at
     let existing=foldr (\h s->M.insert (hEventType h) h s) M.empty hooks
-    mapM_ (registerIfAbsent url at existing) [minBound..maxBound]
+    liftM catMaybes $ mapM (registerIfAbsent at existing) [minBound..maxBound]
   where
-    registerIfAbsent url at existing evt=do
-        let mh=case M.lookup evt existing of
-                Nothing->Just $ Hook Nothing Nothing Nothing url Enabled Nothing evt 
-                Just h2->if hUrl h2 /= url then Just h2{hUrl = url} else Nothing
-        case mh of 
-          Just h->do                           
-            Y.liftIO $ print h
-            void $ storeHook h at
-          _-> return ()
+    registerIfAbsent at existing evt =
+        case M.lookup evt existing of
+          Nothing -> do
+            let h' = Hook Nothing Nothing Nothing url Enabled Nothing evt
+            liftM Just $ createHook h' at
+          Just h | (hUrl h /= url) -> do
+            let h' = h{hUrl = url}
+            liftM Just $ modifyHook h' at
+          _ -> return Nothing
 
 -- | register a call back using the given route
 registerMPCallback :: (Y.MonadHandler m,MPUsableMonad m, Y.HandlerSite m ~ site, YesodMangoPay site) =>
   Y.Route (Y.HandlerSite m)-> EventType -> Maybe Text -> m (AccessToken -> MangoPayT m Hook)
 registerMPCallback rt et mtag=do
   render<-Y.getUrlRender
-  let h=Hook Nothing Nothing mtag (render rt) Enabled Nothing et 
-  return $ storeHook h
-    
--- | parse a event from a notification callback    
-parseMPNotification :: (Y.MonadHandler m, Y.HandlerSite m ~ site, YesodMangoPay site) => m Event
+  let h=Hook Nothing Nothing mtag (render rt) Enabled Nothing et
+  return $ createHook h
+
+
+-- | parse a event from a notification callback
+parseMPNotification :: (Y.MonadHandler m, Y.HandlerSite m ~ site) => m Event
 parseMPNotification = do
   req<-Y.getRequest
   let mevt=eventFromQueryStringT $ Y.reqGetParams req
   case mevt of
     Just evt->return evt
     Nothing->fail "parseMPNotification: could not parse Event"
-  
+
+
 -- | catches any exception that the MangoPay library may throw and deals with it in a error handler
 catchMP :: forall (m :: * -> *) a.
              Y.MonadBaseControl IO m =>
diff --git a/yesod-mangopay.cabal b/yesod-mangopay.cabal
--- a/yesod-mangopay.cabal
+++ b/yesod-mangopay.cabal
@@ -1,5 +1,5 @@
 name:           yesod-mangopay
-version:        1.6
+version:        1.7.0
 cabal-version:  >= 1.8
 build-type:     Simple
 author:         JP Moresmau <jpmoresmau@gmail.com>
@@ -37,7 +37,7 @@
     hs-source-dirs:    src
     build-depends:
                    base         >= 4      && < 5
-                 , mangopay     == 1.6.*
+                 , mangopay     == 1.8.*
                  , containers   >= 0.5    && < 0.6
                  , http-conduit >= 2.0    && < 2.2
                  , http-types   >= 0.8.2  && < 0.9
@@ -113,10 +113,10 @@
                  , shakespeare-js
                  , shakespeare-text
                  , template-haskell
-                 , wai
+                 , wai                           >= 2.1        && < 3.1
                  , wai-extra
                  , wai-logger                    >= 2.1        && < 2.2
-                 , warp
+                 , warp                          >= 2.1        && < 3.1
                  , yaml                          >= 0.8        && < 0.9
                  , yesod-auth                    >= 1.2.6
                  , yesod-form                    >= 1.3.0      && < 1.4
