diff --git a/epochs.py b/epochs.py
index 34629c898fd07d2b40238a8ac9a998953dd7241e..14ef8273928d057c24548d4a92e8701f802e635d 100644
--- a/epochs.py
+++ b/epochs.py
@@ -9,6 +9,8 @@ import nimsapiutil
 
 class Epochs(nimsapiutil.NIMSRequestHandler):
 
+    """/nimsapi/epochs """
+
     json_schema = {
         '$schema': 'http://json-schema.org/draft-04/schema#',
         'title': 'Epoch List',
@@ -43,15 +45,15 @@ class Epochs(nimsapiutil.NIMSRequestHandler):
         }
     }
 
-    def count(self, iid):
+    def count(self):
         """Return the number of Epochs."""
         self.response.write(json.dumps(self.app.db.epochs.count()))
 
-    def post(self, iid):
+    def post(self):
         """Create a new Epoch."""
         self.response.write('epochs post\n')
 
-    def get(self, iid, sid):
+    def get(self, sid):
         """Return the list of Session Epochs."""
         session = self.app.db.sessions.find_one({'_id': bson.objectid.ObjectId(sid)})
         if not session:
@@ -66,13 +68,15 @@ class Epochs(nimsapiutil.NIMSRequestHandler):
         epochs = list(self.app.db.epochs.find(query, projection))
         self.response.write(json.dumps(epochs, default=bson.json_util.default))
 
-    def put(self, iid):
+    def put(self):
         """Update many Epochs."""
         self.response.write('epochs put\n')
 
 
 class Epoch(nimsapiutil.NIMSRequestHandler):
 
+    """/nimsapi/epochs/<eid> """
+
     json_schema = {
         '$schema': 'http://json-schema.org/draft-04/schema#',
         'title': 'Epoch',
@@ -209,7 +213,7 @@ class Epoch(nimsapiutil.NIMSRequestHandler):
         'required': ['_id'],
     }
 
-    def get(self, iid, eid):
+    def get(self, eid):
         """Return one Epoch, conditionally with details."""
         epoch = self.app.db.epochs.find_one({'_id': bson.objectid.ObjectId(eid)})
         if not epoch:
@@ -224,10 +228,10 @@ class Epoch(nimsapiutil.NIMSRequestHandler):
             self.abort(403)
         self.response.write(json.dumps(epoch, default=bson.json_util.default))
 
-    def put(self, iid, eid):
+    def put(self, eid):
         """Update an existing Epoch."""
         self.response.write('epoch %s put, %s\n' % (epoch_id, self.request.params))
 
-    def delete(self, iid, eid):
+    def delete(self, eid):
         """Delete an Epoch."""
         self.response.write('epoch %s delete, %s\n' % (epoch_id, self.request.params))
diff --git a/experiments.py b/experiments.py
index e617c338c2ad24416204a91c4dcdbad53b9db279..c59785790ed8412b910a51779f2c3445b4903368 100644
--- a/experiments.py
+++ b/experiments.py
@@ -9,6 +9,8 @@ import nimsapiutil
 
 class Experiments(nimsapiutil.NIMSRequestHandler):
 
+    """/experiments """
+
     json_schema = {
         '$schema': 'http://json-schema.org/draft-04/schema#',
         'title': 'Experiment List',
@@ -35,15 +37,15 @@ class Experiments(nimsapiutil.NIMSRequestHandler):
         }
     }
 
-    def count(self, iid):
+    def count(self):
         """Return the number of Experiments."""
         self.response.write(json.dumps(self.app.db.experiments.count()))
 
-    def post(self, iid):
+    def post(self):
         """Create a new Experiment."""
         self.response.write('experiments post\n')
 
-    def get(self, iid):
+    def get(self):
         """Return the list of Experiments."""
         query = {'permissions.' + self.userid: {'$exists': 'true'}} if not self.user_is_superuser else None
         projection = ['group', 'name', 'permissions.'+self.userid]
@@ -57,13 +59,15 @@ class Experiments(nimsapiutil.NIMSRequestHandler):
             exp['timestamp'] = timestamps[exp['_id']]
         self.response.write(json.dumps(experiments, default=bson.json_util.default))
 
-    def put(self, iid):
+    def put(self):
         """Update many Experiments."""
         self.response.write('experiments put\n')
 
 
 class Experiment(nimsapiutil.NIMSRequestHandler):
 
+    """/experiments/<xid> """
+
     json_schema = {
         '$schema': 'http://json-schema.org/draft-04/schema#',
         'title': 'Experiment',
@@ -99,7 +103,7 @@ class Experiment(nimsapiutil.NIMSRequestHandler):
         'required': ['_id', 'group', 'name'],
     }
 
-    def get(self, iid, xid):
+    def get(self, xid):
         """Return one Experiment, conditionally with details."""
         experiment = self.app.db.experiments.find_one({'_id': bson.objectid.ObjectId(xid)})
         if not experiment:
@@ -115,10 +119,10 @@ class Experiment(nimsapiutil.NIMSRequestHandler):
                 experiment['permissions'] = {self.userid: experiment['permissions'][self.userid]}
         self.response.write(json.dumps(experiment, default=bson.json_util.default))
 
-    def put(self, iid, xid):
+    def put(self, xid):
         """Update an existing Experiment."""
         self.response.write('experiment %s put, %s\n' % (exp_id, self.request.params))
 
-    def delete(self, iid, xid):
+    def delete(self, xid):
         """Delete an Experiment."""
         self.response.write('experiment %s delete, %s\n' % (exp_id, self.request.params))
diff --git a/nimsapi.py b/nimsapi.py
index 030afccd00346ddfeb7cb28512ef3888155a05a3..7dbf0145d3f72f27b048f49144bc6f2d7819ad0d 100755
--- a/nimsapi.py
+++ b/nimsapi.py
@@ -28,6 +28,8 @@ log = logging.getLogger('nimsapi')
 
 class NIMSAPI(nimsapiutil.NIMSRequestHandler):
 
+    """/nimsapi """
+
     def head(self):
         """Return 200 OK."""
         self.response.set_status(200)
@@ -63,7 +65,7 @@ class NIMSAPI(nimsapiutil.NIMSRequestHandler):
         self.response.write('</style>\n')
         self.response.write('</head>\n')
         self.response.write('<body>\n')
-        self.response.write('<p>nimsapi - ' + self.app.config['site_id'] + '</p>\n')
+        self.response.write('<h1>nimsapi - ' + self.app.config['site_id'] + '</h1>\n')
         self.response.write('<table class="tftable" border="1">\n')
         self.response.write('<tr><th>Resource</th><th>Description</th></tr>\n')
         for r, d in resources:
@@ -108,6 +110,8 @@ class NIMSAPI(nimsapiutil.NIMSRequestHandler):
 
 class Users(nimsapiutil.NIMSRequestHandler):
 
+    """/nimsapi/users """
+
     json_schema = {
         '$schema': 'http://json-schema.org/draft-04/schema#',
         'title': 'User List',
@@ -144,27 +148,29 @@ class Users(nimsapiutil.NIMSRequestHandler):
         }
     }
 
-    def count(self, iid):
+    def count(self):
         """Return the number of Users."""
         self.response.write('%d users\n' % self.app.db.users.count())
 
-    def post(self, iid):
+    def post(self):
         """Create a new User"""
         self.response.write('users post\n')
 
-    def get(self, iid):
+    def get(self):
         """Return the list of Users."""
         projection = ['firstname', 'lastname', 'email_hash']
         users = list(self.app.db.users.find({}, projection))
         self.response.write(json.dumps(users, default=bson.json_util.default))
 
-    def put(self, iid):
+    def put(self):
         """Update many Users."""
         self.response.write('users put\n')
 
 
 class User(nimsapiutil.NIMSRequestHandler):
 
+    """/nimsapi/users/<uid> """
+
     json_schema = {
         '$schema': 'http://json-schema.org/draft-04/schema#',
         'title': 'User',
@@ -202,12 +208,12 @@ class User(nimsapiutil.NIMSRequestHandler):
         'required': ['_id'],
     }
 
-    def get(self, iid, uid):
+    def get(self, uid):
         """Return User details."""
         user = self.app.db.users.find_one({'_id': uid})
         self.response.write(json.dumps(user, default=bson.json_util.default))
 
-    def put(self, iid, uid):
+    def put(self, uid):
         """Update an existing User."""
         user = self.app.db.users.find_one({'_id': uid})
         if not user:
@@ -229,13 +235,15 @@ class User(nimsapiutil.NIMSRequestHandler):
             self.abort(403)
         self.response.write(json.dumps(user, default=bson.json_util.default) + '\n')
 
-    def delete(self, iid, uid):
+    def delete(self, uid):
         """Delete an User."""
         self.response.write('user %s delete, %s\n' % (uid, self.request.params))
 
 
 class Groups(nimsapiutil.NIMSRequestHandler):
 
+    """/nimsapi/groups """
+
     json_schema = {
         '$schema': 'http://json-schema.org/draft-04/schema#',
         'title': 'Group List',
@@ -252,27 +260,29 @@ class Groups(nimsapiutil.NIMSRequestHandler):
         }
     }
 
-    def count(self, iid):
+    def count(self):
         """Return the number of Groups."""
         self.response.write('%d groups\n' % self.app.db.groups.count())
 
-    def post(self, iid):
+    def post(self):
         """Create a new Group"""
         self.response.write('groups post\n')
 
-    def get(self, iid):
+    def get(self):
         """Return the list of Groups."""
         projection = ['_id']
         groups = list(self.app.db.groups.find({}, projection))
         self.response.write(json.dumps(groups, default=bson.json_util.default))
 
-    def put(self, iid):
+    def put(self):
         """Update many Groups."""
         self.response.write('groups put\n')
 
 
 class Group(nimsapiutil.NIMSRequestHandler):
 
+    """/nimsapi/groups/<gid>"""
+
     json_schema = {
         '$schema': 'http://json-schema.org/draft-04/schema#',
         'title': 'Group',
@@ -313,16 +323,16 @@ class Group(nimsapiutil.NIMSRequestHandler):
         'required': ['_id'],
     }
 
-    def get(self, iid, gid):
+    def get(self, gid):
         """Return Group details."""
         group = self.app.db.groups.find_one({'_id': gid})
         self.response.write(json.dumps(group, default=bson.json_util.default))
 
-    def put(self, iid, gid):
+    def put(self, gid):
         """Update an existing Group."""
         self.response.write('group %s put, %s\n' % (gid, self.request.params))
 
-    def delete(self, iid, gid):
+    def delete(self, gid):
         """Delete an Group."""
 
 
@@ -385,8 +395,6 @@ routes = [
         webapp2.Route(r'/dump',                                     NIMSAPI, handler_method='dump', methods=['GET']),
         webapp2.Route(r'/upload',                                   NIMSAPI, handler_method='upload', methods=['PUT']),
         webapp2.Route(r'/remotes',                                  Remotes),
-    ]),
-    webapp2_extras.routes.PathPrefixRoute(r'/nimsapi/<iid:[^/]+>', [
         webapp2.Route(r'/users',                                    Users),
         webapp2.Route(r'/users/count',                              Users, handler_method='count', methods=['GET']),
         webapp2.Route(r'/users/listschema',                         Users, handler_method='schema', methods=['GET']),
@@ -422,6 +430,7 @@ app = webapp2.WSGIApplication(routes, debug=True)
 if __name__ == '__main__':
     args = ArgumentParser().parse_args()
     nimsutil.configure_log(args.logfile, not args.quiet, args.loglevel)
+    # TODO: if pubkey not specified, throw log.warning
 
     from paste import httpserver
     app.config = dict(stage_path=args.stage_path, site_id=args.uid, pubkey=args.pubkey)
diff --git a/nimsapiutil.py b/nimsapiutil.py
index 231134761e95fa325ed45785d96b6a7b45827a0e..c45c41d66a462deaadb830bed5e5ee03b3cbf9d3 100644
--- a/nimsapiutil.py
+++ b/nimsapiutil.py
@@ -8,11 +8,12 @@ import webapp2
 import datetime
 import requests
 import bson.json_util
-from Crypto.Hash import HMAC
-from Crypto.Random import random
+import Crypto.Hash.HMAC
+import Crypto.Random.random
 
 log = logging.getLogger('nimsapi')
-
+requests_log = logging.getLogger('requests')            # configure Requests logging
+requests_log.setLevel(logging.WARNING)                  # set level to WARNING (default is INFO)
 
 class NIMSRequestHandler(webapp2.RequestHandler):
 
@@ -62,16 +63,12 @@ class NIMSRequestHandler(webapp2.RequestHandler):
         self.user = self.app.db.users.find_one({'_id': self.userid})
         self.user_is_superuser = self.user.get('superuser')
         self.response.headers['Content-Type'] = 'application/json'
-        try:
-            self.target_id = request.route_kwargs['iid']            # for what site is the request meant
-        except KeyError:
-            self.target_id = 'local'                                # change to site_id?
-        self.site_id = self.app.config['site_id']                   # what is THIS site
-        self.pubkey = open(self.app.config['pubkey']).read() if self.app.config['pubkey'] is not None else None
+        self.target_id = self.request.get('iid', None)
+        self.site_id = self.app.config['site_id']
 
         # requests coming from another NIMS instance are dealt with differently
         if self.request.user_agent.startswith('NIMS Instance'):
-            log.info("request from '{0}', interNIMS p2p initiated".format(self.request.user_agent))
+            log.debug("request from '{0}', interNIMS p2p initiated".format(self.request.user_agent))
             try:
                 authinfo = self.request.headers['authorization']
                 challenge_id, digest = base64.b64decode(authinfo).split()
@@ -85,36 +82,44 @@ class NIMSRequestHandler(webapp2.RequestHandler):
                 # purge challenge (challenges are single use)
                 self.app.db.challenges.remove({'_id': challenge_id})
                 # verify
-                h = HMAC.new(remote_pubkey, challenge)
+                h = Crypto.Hash.HMAC.new(remote_pubkey, challenge)
                 self.expected = base64.b64encode('%s %s' % (challenge_id, h.hexdigest()))
+                log.debug('recieved: %s' % authinfo)
+                log.debug('expected: %s' % self.expected)
                 if self.expected == authinfo:
-                    log.info('CRAM successful')
+                    log.debug('CRAM response accepted - %s authenticated' % challenge_id)
                 else:
                     self.abort(403, 'Not Authorized: cram failed')
-            except KeyError, e:
+            except KeyError as e:
                 # send a 401 with a fresh challenge
                 cid = self.request.get('cid')
-                if not cid: self.abort(403, 'challenge_id not in payload')
+                if not cid: self.abort(403, 'cid, challenge_id, required')
                 challenge = {'_id': cid,
-                             'challenge': str(random.getrandbits(128)),
+                             'challenge': str(Crypto.Random.random.getrandbits(128)),
                              'timestamp': datetime.datetime.now()}
                 # upsert challenge with time of creation
-                spam = self.app.db.challenges.find_and_modify(query={'_id': cid}, update=challenge, upsert=True, new=True)
+                self.app.db.challenges.find_and_modify(query={'_id': cid}, update=challenge, upsert=True, new=True)
                 # send 401 + challenge in 'www-authenticate' header
                 self.response.headers['www-authenticate'] = base64.b64encode(challenge['challenge'])
                 self.response.set_status(401)
+                log.debug('issued challenge to %s; %s' % (cid, challenge['challenge']))
 
     def dispatch(self):
         """dispatching and request forwarding"""
-        if self.target_id in ['local', self.site_id]:
-            log.info('{0} delegating to local {1}'.format(socket.gethostname(), self.request.url))
+        if self.target_id in [None, self.site_id]:
+            log.debug('{0} delegating to local {1}'.format(socket.gethostname(), self.request.url))
             super(NIMSRequestHandler, self).dispatch()
         else:
-            log.info('{0} delegating to remote {1}'.format(socket.gethostname(), self.target_id))
+            # WORK ON THIS SPOT
+            # capture error, and log.
+            self.pubkey = open(self.app.config['pubkey']).read()
+            # check if pubkey specified, throw error
+
+            log.debug('{0} delegating to remote {1}'.format(socket.gethostname(), self.target_id))
             # is target registered?
             target = self.app.db.remotes.find_one({'_id': self.target_id}, {'_id':False, 'hostname':True})
             if not target:
-                log.info('remote host {0} not in auth list. DENIED'.format(self.target_id))
+                log.debug('remote host {0} not in auth list. DENIED'.format(self.target_id))
                 self.abort(403, 'forbidden: site is not registered with interNIMS')
             self.cid = self.userid + ':' + self.site_id
             reqheaders = dict(self.request.headers)
@@ -125,16 +130,17 @@ class NIMSRequestHandler(webapp2.RequestHandler):
             target_api = 'http://{0}{1}?{2}'.format(target['hostname'], self.request.path, self.request.query_string)
             reqparams = {'cid': self.cid}
 
+            # TODO: error handling for host-down/host-unreachable
             # first attempt, expect 401, send as little as possible...
-            r = requests.request(method=self.request.method, url=target_api, params=reqparams, headers=reqheaders, cookies=self.request.cookies)
+            r = requests.request(method=self.request.method, url=target_api, params=reqparams, headers=reqheaders)
 
             if r.status_code == 401:
                 challenge = base64.b64decode(r.headers['www-authenticate'])
-                # log.info('challenge {0} recieved'.format(challenge))
-                h = HMAC.new(self.pubkey, challenge)
+                log.debug('Authorization requested - challenge: %s' % challenge)
+                h = Crypto.Hash.HMAC.new(self.pubkey, challenge)
                 response = base64.b64encode('%s %s' % (self.cid, h.hexdigest()))
-                # log.info('sending: {0} {1}'.format(self.cid, h.hexdigest()))
-                #adjust the request and try again
+                log.debug('response:  %s %s' % (self.cid, h.hexdigest()))
+                log.debug('b4encoded: %s' % response)
                 reqheaders['authorization'] = response
                 r = requests.request(method=self.request.method, url=target_api, params=reqparams, data=self.request.body, headers=reqheaders, cookies=self.request.cookies)
 
diff --git a/sessions.py b/sessions.py
index 4b69170606bcffedb8f60fcd357bbc247ca5beda..d0c43ce497be85b932dffe2af7c40a3c25300e09 100644
--- a/sessions.py
+++ b/sessions.py
@@ -9,6 +9,8 @@ import nimsapiutil
 
 class Sessions(nimsapiutil.NIMSRequestHandler):
 
+    """/sessions """
+
     json_schema = {
         '$schema': 'http://json-schema.org/draft-04/schema#',
         'title': 'Session List',
@@ -31,15 +33,15 @@ class Sessions(nimsapiutil.NIMSRequestHandler):
         }
     }
 
-    def count(self, iid):
+    def count(self):
         """Return the number of Sessions."""
         self.response.write(json.dumps(self.app.db.sessions.count()))
 
-    def post(self, iid):
+    def post(self):
         """Create a new Session"""
         self.response.write('sessions post\n')
 
-    def get(self, iid, xid):
+    def get(self, xid):
         """Return the list of Experiment Sessions."""
         experiment = self.app.db.experiments.find_one({'_id': bson.objectid.ObjectId(xid)})
         if not experiment:
@@ -51,13 +53,15 @@ class Sessions(nimsapiutil.NIMSRequestHandler):
         sessions = list(self.app.db.sessions.find(query, projection))
         self.response.write(json.dumps(sessions, default=bson.json_util.default))
 
-    def put(self, iid):
+    def put(self):
         """Update many Sessions."""
         self.response.write('sessions put\n')
 
 
 class Session(nimsapiutil.NIMSRequestHandler):
 
+    """/sessions/<sid> """
+
     json_schema = {
         '$schema': 'http://json-schema.org/draft-04/schema#',
         'title': 'Session',
@@ -106,7 +110,7 @@ class Session(nimsapiutil.NIMSRequestHandler):
         'required': ['_id', 'experiment', 'uid', 'patient_id', 'subject'],
     }
 
-    def get(self, iid, sid):
+    def get(self, sid):
         """Return one Session, conditionally with details."""
         session = self.app.db.sessions.find_one({'_id': bson.objectid.ObjectId(sid)})
         if not session:
@@ -118,15 +122,15 @@ class Session(nimsapiutil.NIMSRequestHandler):
             self.abort(403)
         self.response.write(json.dumps(session, default=bson.json_util.default))
 
-    def put(self, iid, sid):
+    def put(self, sid):
         """Update an existing Session."""
         self.response.write('session %s put, %s\n' % (sid, self.request.params))
 
-    def delete(self, iid, sid):
+    def delete(self, sid):
         """Delete an Session."""
         self.response.write('session %s delete, %s\n' % (sid, self.request.params))
 
-    def move(self, iid, sid):
+    def move(self, sid):
         """
         Move a Session to another Experiment.