diff --git a/doc/specification/dummies/map.png b/doc/specification/dummies/map.png
new file mode 100644
index 0000000..1524ef0
Binary files /dev/null and b/doc/specification/dummies/map.png differ
diff --git a/doc/specification/dummies/map.xcf b/doc/specification/dummies/map.xcf
new file mode 100644
index 0000000..33abb62
Binary files /dev/null and b/doc/specification/dummies/map.xcf differ
diff --git a/project.clj b/project.clj
index 7868e2b..a3a1100 100644
--- a/project.clj
+++ b/project.clj
@@ -3,7 +3,7 @@
   :description "Canvassing tool for referenda"
   :url "https://github.com/simon-brooke/youyesyet"
 
-  :dependencies [[adl-support "0.1.0-SNAPSHOT"]
+  :dependencies [[adl-support "0.1.4-SNAPSHOT"]
                  [bouncer "1.0.1"]
                  [ch.qos.logback/logback-classic "1.2.2"]
                  [clj-oauth "1.5.5"]
diff --git a/resources/sql/queries.sql b/resources/sql/queries.sql
index a50d78f..56ca073 100644
--- a/resources/sql/queries.sql
+++ b/resources/sql/queries.sql
@@ -60,3 +60,10 @@ and request.issue_id = expertise.issue_id
 and expertise.canvasser_id = :expert
 ORDER BY visits.date desc
 
+--:name get-last-visit-by-canvasser :? :1
+--:doc returns the most recent visit record of the canvasser with the specified `:id`
+SELECT * FROM visits
+WHERE canvasser_id = :id
+ORDER BY date desc
+LIMIT 1
+
diff --git a/src/clj/youyesyet/routes/rest.clj b/src/clj/youyesyet/routes/rest.clj
index 715ea8a..cbaf5cd 100644
--- a/src/clj/youyesyet/routes/rest.clj
+++ b/src/clj/youyesyet/routes/rest.clj
@@ -85,9 +85,62 @@
     (in-get-local-data here)))
 
 
+(defn last-visit-by-current-user
+  "Return the most recent visit by the currently logged in user"
+  [request]
+  (db/get-last-visit-by-canvasser
+    db/*db*
+    (-> request :session :user)))
+
+
+(defn current-visit-id
+  "Return the id of the current visit by the current user, creating it if necessary."
+  [request]
+  (let [last-visit (last-visit-by-current-user request)]
+    (if
+      (=
+        (:address_id (massage-params request))
+        (:address_id last-visit))
+      (:id last-visit)
+      (db/create-visit! db/*db* params))))
+
+
+(defn create-intention-and-visit!
+  "Doing visit creation logic server side; request params are expected to
+  include an `option`, an `elector_id` and an `address_id`, or an `option` and
+  a `location`. If no `address_id` is provided, we simply create an
+  `intention` record from the `option` and the `locality`; if a `address_id`
+  is provided, we need to check whether the last `visit` by the current `user`
+  was to the same address, if so use that as the `visit_id`, if not create
+  a new `visit` record."
+  [request]
+  (let [params (massage-params request)]
+    (if-let [address-id (-> params :address_id)]
+      (db/create-intention!
+        db/*db*
+        (assoc
+          params :visit_id (current-visit-id request))
+        (db/create-intention! db/*db* params)))))
+
+
+(defn create-request-and-visit!
+  "Doing visit creation logic server side; request params are expected to
+  include an `issue`, an `elector_id` and an `address_id` (and also a
+  `method_id` and `method_detail`). Ye cannae reasonably create a request
+  without having recorded the visit, so let's not muck about."
+  (let [params (massage-params request)]
+    (db/create-followuprequest!
+      db/*db*
+      (assoc
+        params
+        :visit-id (current-visit-id request)))))
+
+
 (defroutes rest-routes
-   (GET "/rest/get-local-data" request (route/restricted (get-local-data 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/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))))
+  )
diff --git a/src/cljs/youyesyet/canvasser_app/handlers.cljs b/src/cljs/youyesyet/canvasser_app/handlers.cljs
index 5249b82..684c9b2 100644
--- a/src/cljs/youyesyet/canvasser_app/handlers.cljs
+++ b/src/cljs/youyesyet/canvasser_app/handlers.cljs
@@ -56,20 +56,33 @@
    })
 
 
+(defn add-to-key
+  "Return a copy of db with `x` added to the front of the list of items held
+  against the key `k`"
+  [db k x]
+  (assoc db k (cons x (db k))))
+
+
+(defn add-to-outqueue
+  [db message]
+  add-to-key db :outqueue message)
+
+
 (defn add-to-feedback
-  "Add the value of `k` in `feedback-messages` to the feedback in this `db`."
+  "Add `x` to the feedback in this `db`."
   [db k]
-  (assoc db :feedback (cons k (:feedback db))))
+  (add-to-key db :feedback x))
+
+
+(defn remove-from-key
+  [db k x]
+  (assoc db k (remove #(= x %) (db k))))
 
 
 (defn remove-from-feedback
-  "Remove the value of `k` in `feedback-messages` to the feedback in this `db`."
-  [db k]
-  (assoc db
-    :feedback
-    (remove
-      #(= % k)
-      (:feedback db))))
+  "Remove `x` from the feedback in this `db`."
+  [db x]
+  (remove-from-key db :feedback x))
 
 
 (defn coerce-to-number [v]
@@ -317,26 +330,26 @@
                          (:outqueue db))}))))))
 
 
- (reg-event-db
+(reg-event-db
   :send-request
   (fn [db [_ _]]
     (if (and (:elector db) (:issue db) (:telephone db))
       (do
         (js/console.log "Sending request")
-        (assoc (add-to-feedback db :send-request)
-          :outqueue (cons
-                     {:elector-id (:id (:elector db))
-                      :issue (:issue db)
-                      :action :add-request} (:outqueue db))))
+        (-> db
+            #(add-to-outqueue % {:elector-id (:id (:elector db))
+                                 :issue (:issue db)
+                                 :action :add-request})
+            #(add-to-feedback % :send-request)))
       (assoc db :error "Please supply a telephone number to call"))))
 
 
 (reg-event-db
- :set-active-page
- (fn [db [_ k]]
-   (if k
-     (assoc (clear-messages db) :page k)
-     db)))
+  :set-active-page
+  (fn [db [_ k]]
+    (if k
+      (assoc (clear-messages db) :page k)
+      db)))
 
 
 (reg-event-db
diff --git a/youyesyet.adl.xml b/youyesyet.adl.xml
index dd16842..d828eb4 100644
--- a/youyesyet.adl.xml
+++ b/youyesyet.adl.xml
@@ -704,6 +704,11 @@ version="0.1.1">
     column="method_id" entity="followupmethods" farkey="id">
       <prompt prompt="method_id" locale="en_GB.UTF-8"/>
     </property>
+    <property required="true" type="string" name="method-detail">
+      <documentation>
+        Phone number or email address for followup.
+      </documentation>
+    </property>
     <list properties="listed" name="Followuprequests">
       <field property="elector_id">
         <prompt prompt="elector" locale="en_GB.UTF-8"/>