diff --git a/.gitignore b/.gitignore
index 457f290..a43d8c6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -41,3 +41,5 @@ resources/sql/youyesyet\.postgres\.sql
 
 \.rebel_readline_history
 /dumps/
+
+youyesyet\.canonical\.adl\.xml
diff --git a/src/clj/youyesyet/routes/rest.clj b/src/clj/youyesyet/routes/rest.clj
index c9c4e84..e5255c5 100644
--- a/src/clj/youyesyet/routes/rest.clj
+++ b/src/clj/youyesyet/routes/rest.clj
@@ -116,56 +116,6 @@
           :date (jt/to-sql-timestamp (jt/local-date-time)))))))
 
 
-;; (current-visit-id {:session {:user {:email "simon@journeyman.cc",
-;;                                               :phone "07768 130255",
-;;                                               :roles #{"analysts" "canvassers" "admin" "teamorganisers" "issueexperts" "issueeditors"},
-;;                                               :username "simon_brooke",
-;;                                               :fullname "Simon Brooke",
-;;                                               :bio "Sinister pagan",
-;;                                               :elector_id 2, :id 4, :address_id 2,
-;;                                               :authority_id "GitHub",
-;;                                               :authorised true}}
-;;                              :params {:address_id 79, :elector_id 238, :locality 5494393, :option_id "Yes"}})
-;; (current-visit-id {:session {:user {:email "simon@journeyman.cc",
-;;                                               :phone "07768 130255",
-;;                                               :roles #{"analysts" "canvassers" "admin" "teamorganisers" "issueexperts" "issueeditors"},
-;;                                               :username "simon_brooke",
-;;                                               :fullname "Simon Brooke",
-;;                                               :bio "Sinister pagan",
-;;                                               :elector_id 2, :id 4, :address_id 2,
-;;                                               :authority_id "GitHub",
-;;                                               :authorised true}}
-;;                              :params {:address_id 80, :elector_id 239, :locality 5494393, :option_id "Yes"}})
-
-
-(defmacro do-or-return-reason
-  "Clojure stacktraces are unreadable. We have to do better; evaluate
-  this `form` in a try-catch block; return a map. If the evaluation
-  succeeds, the map will have a key `:result` whose value is the result;
-  otherwise it will have a key `:error` which will be bound to the most
-  sensible error message we can construct."
-  ;; TODO: candidate for moving to adl-support.core
-  [form]
-  `(try
-     {:result ~form}
-     (catch Exception any#
-       (clojure.tools.logging/error
-         (str (.getName (.getClass any#))
-              ": "
-              (.getMessage any#)
-              (with-out-str
-                (-> any# .printStackTrace))))
-       {:error
-        s/join "\n\tcaused by: "
-        (reverse
-          (loop [ex# any# result# ()]
-            (if-not (nil? ex#)
-              (recur
-                (.getCause ex#)
-                (str (.getName (.getClass ex#)) ": " (.getMessage ex#)))
-              result#)))})))
-
-
 (defn create-intention-and-visit!
   "Doing visit creation logic server side; request params are expected to
   include an `option_id`, an `elector_id` and an `address_id`, or an `option` and
@@ -177,28 +127,23 @@
   [request]
   (let [params (massage-params request)]
     (log/debug "Creating intention with params: " params)
-    (if (-> request :session :user)
+    (valid-user-or-forbid
       (if
         (and
           (or (:locality params)
               (and (:elector_id params)
                    (:address_id params)))
           (:option_id params))
-        (let [r (do-or-return-reason
-                  (db/create-intention!
-                    db/*db*
-                    (assoc
-                      params :visit_id (current-visit-id request))))]
-          (if
-            (:result r)
-            {:status 201
-             :body (json/write-str (:result r))}
-            {:status 500
-             :body (:error r)}))
+        (do-or-server-fail
+          (db/create-intention!
+            db/*db*
+            (assoc
+              params :visit_id (current-visit-id request)))
+          201)
         {:status 400
-         :body "create-intention requires params: `option_id` and either `locality` or both `address_id` and `elector_id`."})
-      {:status 403
-       :body "You must be logged in to do that"})))
+         :body (json/write-str "create-intention requires params: `option_id`
+                               and either `locality` or both `address_id` and `elector_id`.")})
+      request)))
 
 
 (defn create-request-and-visit!
@@ -207,19 +152,20 @@
   `method_id` and `method_detail`). Ye cannae reasonably create a request
   without having recorded the visit, so let's not muck about."
   [request]
-  (let [params (massage-params request)]
-    (db/create-followuprequest!
-      db/*db*
-      (assoc
+  (let [params (assoc
+                 (massage-params request)
+                 :visit_id (current-visit-id request))]
+    (valid-user-or-forbid
+      (with-params-or-error
+        (do-or-server-fail
+          (db/create-followuprequest! db/*db* params)
+          201)
         params
-        :visit-id (current-visit-id request)))))
+        #{:elector_id :visit_id :issue_id :method_id :method_detail})
+      request)))
 
 
 (defroutes rest-routes
   (GET "/rest/get-local-data" request (route/restricted (get-local-data request)))
   (GET "/rest/create-intention" request (route/restricted (create-intention-and-visit! request)))
-  (GET "/rest/create-request" request (route/restricted (create-request-and-visit! request)))
-  ;;   (GET "/rest/get-issues" request (route/restricted (get-issues request)))
-  ;;   (GET "/rest/set-intention" request (route/restricted (set-intention request)))
-  ;;   (GET "/rest/request-followup" request (route/restricted (request-followup request))))
-  )
+  (GET "/rest/create-request" request (route/restricted (create-request-and-visit! request))))
diff --git a/src/cljs/youyesyet/canvasser_app/handlers.cljs b/src/cljs/youyesyet/canvasser_app/handlers.cljs
index 6a8f3ca..a6894ba 100644
--- a/src/cljs/youyesyet/canvasser_app/handlers.cljs
+++ b/src/cljs/youyesyet/canvasser_app/handlers.cljs
@@ -334,18 +334,18 @@
 (reg-event-db
   :send-request
   (fn [db [_ _]]
-    (if (and (:elector db) (:issue db) (:telephone db))
+    (if (and (:elector db) (:issue db) (:method_detail db))
       (do
         (js/console.log "Sending request")
         (add-to-feedback
           (add-to-outqueue
-          db
-          {:elector_id (-> db :elector :id)
-                                 :issue_id (-> db :issue :id)
-                                 :address_id (-> db :address :id)
-                                 :method_id "Phone"
-                                 :method_detail (-> db :method_detail)
-                                 :action :create-request})
+            db
+            {:address_id (-> db :address :id)
+             :elector_id (-> db :elector :id)
+             :issue_id (name (-> db :issue))
+             :method_id "Phone"
+             :method_detail (-> db :method_detail)
+             :action :create-request})
           :send-request))
       (assoc db :error "Please supply a telephone number to call"))))
 
@@ -457,7 +457,6 @@
 (reg-event-db
  :set-method-detail
  (fn [db [_ detail]]
-   (js/console.log (str "Setting method detail to " detail))
    (assoc (clear-messages db) :method_detail detail)))
 
 
@@ -513,7 +512,15 @@
 (reg-event-db
   :tx-failure
   (fn [db [_ response]]
-    (js/console.log (str "Transmission failed (" response "), requeueing" (:tx-item db)))
-    (assoc
-      (add-to-outqueue db (:tx-item db))
-      :error "Transmission failed, requeueing")))
+    (case
+      (:status response)
+      (400 403 500)
+      (do
+        (js/console.log "Server responded " (:status response) " - " (:response response) "; not requeueing")
+        (assoc db :error (:response response)))
+      ;; default
+      (do
+        (js/console.log (str "Transmission failed (" response "), requeueing" (:tx-item db)))
+        (assoc
+          (add-to-outqueue db (:tx-item db))
+          :error "Transmission failed, requeueing")))))