diff --git a/lib/usergrid.js b/lib/usergrid.js
new file mode 100755
index 0000000..b29dd3f
--- /dev/null
+++ b/lib/usergrid.js
@@ -0,0 +1,2584 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+var inflection = require('inflection');
+var request = require('request');
+var Usergrid = {};
+Usergrid.USERGRID_SDK_VERSION = '0.10.07';
+
+//authentication type constants
+var AUTH_CLIENT_ID = 'CLIENT_ID';
+var AUTH_APP_USER = 'APP_USER';
+var AUTH_NONE = 'NONE';
+
+  Usergrid.Client = function(options) {
+    //usergrid enpoint
+    this.URI = options.URI || 'https://api.usergrid.com';
+
+    //Find your Orgname and Appname in the Admin portal (http://apigee.com/usergrid)
+    if (options.orgName) {
+      this.set('orgName', options.orgName);
+    }
+    if (options.appName) {
+      this.set('appName', options.appName);
+    }
+
+    //authentication data
+    this.authType = options.authType || AUTH_NONE;
+    this.clientId = options.clientId;
+    this.clientSecret = options.clientSecret;
+    this.token = options.token || null;
+
+    //other options
+    this.buildCurl = options.buildCurl || false;
+    this.logging = options.logging || false;
+
+    //timeout and callbacks
+    this._callTimeout =  options.callTimeout || 30000; //default to 30 seconds
+    this._callTimeoutCallback =  options.callTimeoutCallback || null;
+    this.logoutCallback =  options.logoutCallback || null;
+  };
+
+  /*
+  *  Main function for making requests to the API.  Can be called directly.
+  *
+  *  options object:
+  *  `method` - http method (GET, POST, PUT, or DELETE), defaults to GET
+  *  `qs` - object containing querystring values to be appended to the uri
+  *  `body` - object containing entity body for POST and PUT requests
+  *  `endpoint` - API endpoint, for example 'users/fred'
+  *  `mQuery` - boolean, set to true if running management query, defaults to false
+  *
+  *  @method request
+  *  @public
+  *  @params {object} options
+  *  @param {function} callback
+  *  @return {callback} callback(err, data)
+  */
+  Usergrid.Client.prototype.request = function (options, callback) {
+    var self = this;
+    var method = options.method || 'GET';
+    var endpoint = options.endpoint;
+    var body = options.body || {};
+    var qs = options.qs || {};
+    var mQuery = options.mQuery || false; //is this a query to the management endpoint?
+    var orgName = this.get('orgName');
+    var appName = this.get('appName');
+    if(!mQuery && !orgName && !appName){
+      if (typeof(this.logoutCallback) === 'function') {
+        return this.logoutCallback(true, 'no_org_or_app_name_specified');
+      }
+    }
+    var uri;
+    if (mQuery) {
+      uri = this.URI + '/' + endpoint;
+    } else {
+      uri = this.URI + '/' + orgName + '/' + appName + '/' + endpoint;
+    }
+
+    if (this.authType === AUTH_CLIENT_ID) {
+      qs['client_id'] = this.clientId;
+      qs['client_secret'] = this.clientSecret;
+    } else if (this.authType === AUTH_APP_USER && self.getToken()) {
+      qs['access_token'] = self.getToken();
+    }
+
+    if (this.logging) {
+      console.log('calling: ' + method + ' ' + uri);
+    }
+    this._start = new Date().getTime();
+    var callOptions = {
+      method: method,
+      uri: uri,
+      json: body,
+      qs: qs
+    };
+    request(callOptions, function (err, r, data) {
+
+      r.body = r.body || {};
+      data = data || {};
+
+      if (self.buildCurl) {
+        options.uri = r.request.uri.href;
+        self.buildCurlCall(options);
+      }
+      self._end = new Date().getTime();
+      if(r.statusCode === 200) {
+        if (self.logging) {
+          console.log('success (time: ' + self.calcTimeDiff() + '): ' + method + ' ' + uri);
+        }
+        callback(err, data);
+      } else {
+        err = true;
+        data.statusCode = r.statusCode;
+        if ((r.error === 'auth_expired_session_token') ||
+          (r.error === 'auth_missing_credentials')   ||
+          (r.error == 'auth_unverified_oath')       ||
+          (r.error === 'expired_token')   ||
+          (r.error === 'unauthorized')   ||
+          (r.error === 'auth_invalid')) {
+          //this error type means the user is not authorized. If a logout function is defined, call it
+          var error = r.body.error;
+          var errorDesc = r.body.error_description;
+          if (self.logging) {
+            console.log('Error (' + r.statusCode + ')(' + error + '): ' + errorDesc);
+          }
+          //if the user has specified a logout callback:
+          if (typeof(self.logoutCallback) === 'function') {
+            self.logoutCallback(err, data);
+          } else  if (typeof(callback) === 'function') {
+            callback(err, data);
+          }
+        } else {
+          var error = r.body.error;
+          var errorDesc = r.body.error_description;
+          if (self.logging) {
+            console.log('Error (' + r.statusCode + ')(' + error + '): ' + errorDesc);
+          }
+          if (typeof(callback) === 'function') {
+            callback(err, data);
+          }
+        }
+      }
+    });
+  };
+  /*
+   *  function for building asset urls
+   *
+   *  @method buildAssetURL
+   *  @public
+   *  @params {string} uuid
+   *  @return {string} assetURL
+   */
+   Usergrid.Client.prototype.buildAssetURL = function(uuid) {
+     var self = this;
+     var qs = {};
+     var assetURL = this.URI + '/' + this.orgName + '/' + this.appName + '/assets/' + uuid + '/data';
+
+     if (self.getToken()) {
+       qs['access_token'] = self.getToken();
+     }
+
+     //append params to the path
+     var encoded_params = encodeParams(qs);
+     if (encoded_params) {
+       assetURL += "?" + encoded_params;
+     }
+
+     return assetURL;
+   }
+
+  /*
+   *  Main function for creating new groups. Call this directly.
+   *
+   *  @method createGroup
+   *  @public
+   *  @params {string} path
+   *  @param {function} callback
+   *  @return {callback} callback(err, data)
+   */
+  Usergrid.Client.prototype.createGroup = function(options, callback) {
+    var getOnExist = options.getOnExist || false;
+    delete options.getOnExist;
+
+    var options = {
+      path: options.path,
+      client: this,
+      data:options
+    }
+
+    var group = new Usergrid.Group(options);
+    group.fetch(function(err, data){
+      var okToSave = (err && 'service_resource_not_found' === data.error || 'no_name_specified' === data.error || 'null_pointer' === data.error) || (!err && getOnExist);
+      if (okToSave) {
+        group.save(function(err, data){
+          if (typeof(callback) === 'function') {
+            callback(err, group);
+          }
+        });
+      } else {
+        if(typeof(callback) === 'function') {
+          callback(err, group);
+        }
+      }
+    });
+  }
+
+  /*
+  *  Main function for creating new entities - should be called directly.
+  *
+  *  options object: options {data:{'type':'collection_type', 'key':'value'}, uuid:uuid}}
+  *
+  *  @method createEntity
+  *  @public
+  *  @params {object} options
+  *  @param {function} callback
+  *  @return {callback} callback(err, data)
+  */
+  Usergrid.Client.prototype.createEntity = function (options, callback) {
+    // todo: replace the check for new / save on not found code with simple save
+    // when users PUT on no user fix is in place.
+    /*
+    var options = {
+      client:this,
+      data:options
+    }
+    var entity = new Usergrid.Entity(options);
+    entity.save(function(err, data) {
+      if (typeof(callback) === 'function') {
+        callback(err, entity);
+      }
+    });
+    */
+    var getOnExist = options.getOnExist || false; //if true, will return entity if one already exists
+    delete options.getOnExist;
+
+    var options = {
+      client:this,
+      data:options
+    }
+    var entity = new Usergrid.Entity(options);
+    entity.fetch(function(err, data) {
+      //if the fetch doesn't find what we are looking for, or there is no error, do a save
+      var okToSave = (err && 'service_resource_not_found' === data.error || 'no_name_specified' === data.error || 'null_pointer' === data.error) || (!err && getOnExist);
+      if(okToSave) {
+        entity.set(options.data); //add the data again just in case
+        entity.save(function(err, data) {
+          if (typeof(callback) === 'function') {
+            callback(err, entity, data);
+          }
+        });
+      } else {
+        if (typeof(callback) === 'function') {
+          callback(err, entity, data);
+        }
+      }
+    });
+
+  }
+
+  /*
+   *  Main function for getting existing entities - should be called directly.
+   *
+   *  You must supply a uuid or (username or name). Username only applies to users.
+   *  Name applies to all custom entities
+   *
+   *  options object: options {data:{'type':'collection_type', 'name':'value', 'username':'value'}, uuid:uuid}}
+   *
+   *  @method createEntity
+   *  @public
+   *  @params {object} options
+   *  @param {function} callback
+   *  @return {callback} callback(err, data)
+   */
+  Usergrid.Client.prototype.getEntity = function (options, callback) {
+    var options = {
+      client:this,
+      data:options
+    }
+    var entity = new Usergrid.Entity(options);
+    entity.fetch(function(err, data) {
+      if (typeof(callback) === 'function') {
+        callback(err, entity, data);
+      }
+    });
+  }
+
+  /*
+   *  Main function for restoring an entity from serialized data.
+   *
+   *  serializedObject should have come from entityObject.serialize();
+   *
+   *  @method restoreEntity
+   *  @public
+   *  @param {string} serializedObject
+   *  @return {object} Entity Object
+   */
+  Usergrid.Client.prototype.restoreEntity = function (serializedObject) {
+    var data = JSON.parse(serializedObject);
+    var options = {
+      client:this,
+      data:data
+    }
+    var entity = new Usergrid.Entity(options);
+    return entity;
+  }
+
+  /*
+  *  Main function for creating new collections - should be called directly.
+  *
+  *  options object: options {client:client, type: type, qs:qs}
+  *
+  *  @method createCollection
+  *  @public
+  *  @params {object} options
+  *  @param {function} callback
+  *  @return {callback} callback(err, data)
+  */
+  Usergrid.Client.prototype.createCollection = function (options, callback) {
+    options.client = this;
+    var collection = new Usergrid.Collection(options, function(err, data) {
+      if (typeof(callback) === 'function') {
+        callback(err, collection, data);
+      }
+    });
+  }
+
+  /*
+   *  Main function for restoring a collection from serialized data.
+   *
+   *  serializedObject should have come from collectionObject.serialize();
+   *
+   *  @method restoreCollection
+   *  @public
+   *  @param {string} serializedObject
+   *  @return {object} Collection Object
+   */
+  Usergrid.Client.prototype.restoreCollection = function (serializedObject) {
+    var data = JSON.parse(serializedObject);
+    data.client = this;
+    var collection = new Usergrid.Collection(data);
+    return collection;
+  }
+
+  /*
+   *  Main function for retrieving a user's activity feed.
+   *
+   *  @method getFeedForUser
+   *  @public
+   *  @params {string} username
+   *  @param {function} callback
+   *  @return {callback} callback(err, data, activities)
+   */
+  Usergrid.Client.prototype.getFeedForUser = function(username, callback) {
+    var options = {
+      method: "GET",
+      endpoint: "users/"+username+"/feed"
+    }
+
+    this.request(options, function(err, data){
+      if(typeof(callback) === "function") {
+        if(err) {
+          callback(err);
+        } else {
+          callback(err, data, data.entities);
+        }
+      }
+    });
+  }
+
+  /*
+  *  Function for creating new activities for the current user - should be called directly.
+  *
+  *  //user can be any of the following: "me", a uuid, a username
+  *  Note: the "me" alias will reference the currently logged in user (e.g. 'users/me/activties')
+  *
+  *  //build a json object that looks like this:
+  *  var options =
+  *  {
+  *    "actor" : {
+  *      "displayName" :"myusername",
+  *      "uuid" : "myuserid",
+  *      "username" : "myusername",
+  *      "email" : "myemail",
+  *      "picture": "http://path/to/picture",
+  *      "image" : {
+  *          "duration" : 0,
+  *          "height" : 80,
+  *          "url" : "http://www.gravatar.com/avatar/",
+  *          "width" : 80
+  *      },
+  *    },
+  *    "verb" : "post",
+  *    "content" : "My cool message",
+  *    "lat" : 48.856614,
+  *    "lon" : 2.352222
+  *  }
+  *
+  *  @method createEntity
+  *  @public
+  *  @params {string} user // "me", a uuid, or a username
+  *  @params {object} options
+  *  @param {function} callback
+  *  @return {callback} callback(err, data)
+  */
+  Usergrid.Client.prototype.createUserActivity = function (user, options, callback) {
+    options.type = 'users/'+user+'/activities';
+    var options = {
+      client:this,
+      data:options
+    }
+    var entity = new Usergrid.Entity(options);
+    entity.save(function(err, data) {
+      if (typeof(callback) === 'function') {
+        callback(err, entity);
+      }
+    });
+  }
+
+  /*
+   *  Function for creating user activities with an associated user entity.
+   *
+   *  user object:
+   *  The user object passed into this function is an instance of Usergrid.Entity.
+   *
+   *  @method createUserActivityWithEntity
+   *  @public
+   *  @params {object} user
+   *  @params {string} content
+   *  @param {function} callback
+   *  @return {callback} callback(err, data)
+   */
+  Usergrid.Client.prototype.createUserActivityWithEntity = function(user, content, callback) {
+    var username = user.get("username");
+    var options = {
+      actor: {
+        "displayName":username,
+        "uuid":user.get("uuid"),
+        "username":username,
+        "email":user.get("email"),
+        "picture":user.get("picture"),
+        "image": {
+          "duration":0,
+          "height":80,
+          "url":user.get("picture"),
+          "width":80
+         },
+      },
+      "verb":"post",
+      "content":content };
+
+    this.createUserActivity(username, options, callback);
+
+  }
+
+  /*
+  *  A private method to get call timing of last call
+  */
+  Usergrid.Client.prototype.calcTimeDiff = function () {
+   var time = this._end - this._start;
+   return (time/1000).toFixed(2);
+  }
+
+  /*
+   *  A public method to store the OAuth token for later use - uses localstorage if available
+   *
+   *  @method setToken
+   *  @public
+   *  @params {string} token
+   *  @return none
+   */
+  Usergrid.Client.prototype.setToken = function (token) {
+    this.set('token', token);
+  }
+
+  /*
+   *  A public method to get the OAuth token
+   *
+   *  @method getToken
+   *  @public
+   *  @return {string} token
+   */
+  Usergrid.Client.prototype.getToken = function () {
+    return this.get('token');
+  }
+
+  Usergrid.Client.prototype.setObject = function(key, value) {
+    if (value) {
+      value = JSON.stringify(value);
+    }
+    this.set(key, value);
+  }
+
+  Usergrid.Client.prototype.set = function (key, value) {
+    var keyStore =  'apigee_' + key;
+    this[key] = value;
+    if(typeof(Storage)!=="undefined"){
+      if (value) {
+        localStorage.setItem(keyStore, value);
+      } else {
+        localStorage.removeItem(keyStore);
+      }
+    }
+  }
+
+  Usergrid.Client.prototype.getObject = function(key) {
+    return JSON.parse(this.get(key));
+  }
+
+  Usergrid.Client.prototype.get = function (key) {
+    var keyStore = 'apigee_' + key;
+    if (this[key]) {
+      return this[key];
+    } else if(typeof(Storage)!=="undefined") {
+      return localStorage.getItem(keyStore);
+    }
+    return null;
+  }
+
+  /*
+   * A public facing helper method for signing up users
+   *
+   * @method signup
+   * @public
+   * @params {string} username
+   * @params {string} password
+   * @params {string} email
+   * @params {string} name
+   * @param {function} callback
+   * @return {callback} callback(err, data)
+   */
+  Usergrid.Client.prototype.signup = function(username, password, email, name, callback) {
+    var self = this;
+    var options = {
+      type:"users",
+      username:username,
+      password:password,
+      email:email,
+      name:name
+    };
+
+    this.createEntity(options, callback);
+  }
+
+  /*
+  *
+  *  A public method to log in an app user - stores the token for later use
+  *
+  *  @method login
+  *  @public
+  *  @params {string} username
+  *  @params {string} password
+  *  @param {function} callback
+  *  @return {callback} callback(err, data)
+  */
+  Usergrid.Client.prototype.login = function (username, password, callback) {
+    var self = this;
+    var options = {
+      method:'POST',
+      endpoint:'token',
+      body:{
+        username: username,
+        password: password,
+        grant_type: 'password'
+      }
+    };
+    this.request(options, function(err, data) {
+      var user = {};
+      if (err && self.logging) {
+        console.log('error trying to log user in');
+      } else {
+        var options = {
+          client:self,
+          data:data.user
+        }
+        user = new Usergrid.Entity(options);
+        self.setToken(data.access_token);
+        }
+      if (typeof(callback) === 'function') {
+        callback(err, data, user);
+      }
+    });
+  }
+
+
+  Usergrid.Client.prototype.reAuthenticateLite = function (callback) {
+    var self = this;
+    var options = {
+      method:'GET',
+      endpoint:'management/me',
+      mQuery:true
+    };
+    this.request(options, function(err, response) {
+      if (err && self.logging) {
+        console.log('error trying to re-authenticate user');
+      } else {
+
+        //save the re-authed token and current email/username
+        self.setToken(response.access_token);
+
+      }
+      if (typeof(callback) === 'function') {
+        callback(err);
+      }
+    });
+  }
+
+
+  Usergrid.Client.prototype.reAuthenticate = function (email, callback) {
+    var self = this;
+    var options = {
+      method:'GET',
+      endpoint:'management/users/'+email,
+      mQuery:true
+    };
+    this.request(options, function(err, response) {
+      var organizations = {};
+      var applications = {};
+      var user = {};
+      if (err && self.logging) {
+        console.log('error trying to full authenticate user');
+      } else {
+        var data = response.data;
+        self.setToken(data.token);
+        self.set('email', data.email);
+
+        //delete next block and corresponding function when iframes are refactored
+        localStorage.setItem('accessToken', data.token);
+        localStorage.setItem('userUUID', data.uuid);
+        localStorage.setItem('userEmail', data.email);
+        //end delete block
+
+
+        var userData = {
+          "username" : data.username,
+          "email" : data.email,
+          "name" : data.name,
+          "uuid" : data.uuid
+        }
+        var options = {
+          client:self,
+          data:userData
+        }
+        user = new Usergrid.Entity(options);
+
+        organizations = data.organizations;
+        var org = '';
+        try {
+          //if we have an org stored, then use that one. Otherwise, use the first one.
+          var existingOrg = self.get('orgName');
+          org = (organizations[existingOrg])?organizations[existingOrg]:organizations[Object.keys(organizations)[0]];
+          self.set('orgName', org.name);
+        } catch(e) {
+          err = true;
+          if (self.logging) { console.log('error selecting org'); }
+        } //should always be an org
+
+        applications = self.parseApplicationsArray(org);
+        self.selectFirstApp(applications);
+
+        self.setObject('organizations', organizations);
+        self.setObject('applications', applications);
+
+      }
+      if (typeof(callback) === 'function') {
+        callback(err, data, user, organizations, applications);
+      }
+    });
+  }
+
+  /*
+  *  A public method to log in an app user with facebook - stores the token for later use
+  *
+  *  @method loginFacebook
+  *  @public
+  *  @params {string} username
+  *  @params {string} password
+  *  @param {function} callback
+  *  @return {callback} callback(err, data)
+  */
+  Usergrid.Client.prototype.loginFacebook = function (facebookToken, callback) {
+    var self = this;
+    var options = {
+      method:'GET',
+      endpoint:'auth/facebook',
+      qs:{
+        fb_access_token: facebookToken
+      }
+    };
+    this.request(options, function(err, data) {
+      var user = {};
+      if (err && self.logging) {
+        console.log('error trying to log user in');
+      } else {
+        var options = {
+          client: self,
+          data: data.user
+        }
+        user = new Usergrid.Entity(options);
+        self.setToken(data.access_token);
+      }
+      if (typeof(callback) === 'function') {
+        callback(err, data, user);
+      }
+    });
+  }
+
+  /*
+  *  A public method to get the currently logged in user entity
+  *
+  *  @method getLoggedInUser
+  *  @public
+  *  @param {function} callback
+  *  @return {callback} callback(err, data)
+  */
+  Usergrid.Client.prototype.getLoggedInUser = function (callback) {
+    if (!this.getToken()) {
+      callback(true, null, null);
+    } else {
+      var self = this;
+      var options = {
+        method:'GET',
+        endpoint:'users/me'
+      };
+      this.request(options, function(err, data) {
+        if (err) {
+          if (self.logging) {
+            console.log('error trying to log user in');
+          }
+          if (typeof(callback) === 'function') {
+            callback(err, data, null);
+          }
+        } else {
+          var options = {
+            client:self,
+            data:data.entities[0]
+          }
+          var user = new Usergrid.Entity(options);
+          if (typeof(callback) === 'function') {
+            callback(err, data, user);
+          }
+        }
+      });
+    }
+  }
+
+  /*
+  *  A public method to test if a user is logged in - does not guarantee that the token is still valid,
+  *  but rather that one exists
+  *
+  *  @method isLoggedIn
+  *  @public
+  *  @return {boolean} Returns true the user is logged in (has token and uuid), false if not
+  */
+  Usergrid.Client.prototype.isLoggedIn = function () {
+    if (this.getToken()) {
+      return true;
+    }
+    return false;
+  }
+
+  /*
+  *  A public method to log out an app user - clears all user fields from client
+  *
+  *  @method logout
+  *  @public
+  *  @return none
+  */
+  Usergrid.Client.prototype.logout = function () {
+    this.setToken(null);
+  }
+
+  /*
+  *  A private method to build the curl call to display on the command line
+  *
+  *  @method buildCurlCall
+  *  @private
+  *  @param {object} options
+  *  @return {string} curl
+  */
+  Usergrid.Client.prototype.buildCurlCall = function (options) {
+    var curl = 'curl';
+    var method = (options.method || 'GET').toUpperCase();
+    var body = options.body || {};
+    var uri = options.uri;
+
+    //curl - add the method to the command (no need to add anything for GET)
+    if (method === 'POST') {curl += ' -X POST'; }
+    else if (method === 'PUT') { curl += ' -X PUT'; }
+    else if (method === 'DELETE') { curl += ' -X DELETE'; }
+    else { curl += ' -X GET'; }
+
+    //curl - append the path
+    curl += ' ' + uri;
+
+    //curl - add the body
+    body = JSON.stringify(body)//only in node module
+    if (body !== '"{}"' && method !== 'GET' && method !== 'DELETE') {
+      //curl - add in the json obj
+      curl += " -d '" + body + "'";
+    }
+
+    //log the curl command to the console
+    console.log(curl);
+
+    return curl;
+  }
+
+  Usergrid.Client.prototype.getDisplayImage = function (email, picture, size) {
+    try {
+      if (picture) {
+        return picture;
+      }
+      var size = size || 50;
+      if (email.length) {
+        return 'https://secure.gravatar.com/avatar/' + MD5(email) + '?s=' + size + encodeURI("&d=https://apigee.com/usergrid/images/user_profile.png");
+      } else {
+        return 'https://apigee.com/usergrid/images/user_profile.png';
+      }
+    } catch(e) {
+      return 'https://apigee.com/usergrid/images/user_profile.png';
+    }
+  }
+
+  /*
+  *  A class to Model a Usergrid Entity.
+  *  Set the type and uuid of entity in the 'data' json object
+  *
+  *  @constructor
+  *  @param {object} options {client:client, data:{'type':'collection_type', uuid:'uuid', 'key':'value'}}
+  */
+  Usergrid.Entity = function(options) {
+    if (options) {
+      this._data = options.data || {};
+      this._client = options.client || {};
+    }
+  };
+
+  /*
+   *  returns a serialized version of the entity object
+   *
+   *  Note: use the client.restoreEntity() function to restore
+   *
+   *  @method serialize
+   *  @return {string} data
+   */
+  Usergrid.Entity.prototype.serialize = function () {
+    return JSON.stringify(this._data);
+  }
+
+  /*
+  *  gets a specific field or the entire data object. If null or no argument
+  *  passed, will return all data, else, will return a specific field
+  *
+  *  @method get
+  *  @param {string} field
+  *  @return {string} || {object} data
+  */
+  Usergrid.Entity.prototype.get = function (field) {
+    if (field) {
+      return this._data[field];
+    } else {
+      return this._data;
+    }
+  }
+
+  /*
+  *  adds a specific key value pair or object to the Entity's data
+  *  is additive - will not overwrite existing values unless they
+  *  are explicitly specified
+  *
+  *  @method set
+  *  @param {string} key || {object}
+  *  @param {string} value
+  *  @return none
+  */
+  Usergrid.Entity.prototype.set = function (key, value) {
+    if (typeof key === 'object') {
+      for(var field in key) {
+        this._data[field] = key[field];
+      }
+    } else if (typeof key === 'string') {
+      if (value === null) {
+        delete this._data[key];
+      } else {
+        this._data[key] = value;
+      }
+    } else {
+      this._data = {};
+    }
+  }
+
+  /*
+  *  Saves the entity back to the database
+  *
+  *  @method save
+  *  @public
+  *  @param {function} callback
+  *  @return {callback} callback(err, data)
+  */
+  Usergrid.Entity.prototype.save = function (callback) {
+    var type = this.get('type');
+    var method = 'POST';
+    if (isUUID(this.get('uuid'))) {
+      method = 'PUT';
+      type += '/' + this.get('uuid');
+    }
+
+    //update the entity
+    var self = this;
+    var data = {};
+    var entityData = this.get();
+    var password = this.get('password');
+    var oldpassword = this.get('oldpassword');
+    var newpassword = this.get('newpassword');
+    //remove system specific properties
+    for (var item in entityData) {
+      if (item === 'metadata' || item === 'created' || item === 'modified' ||
+          item === 'oldpassword' || item === 'newpassword' || //old and new pw not added to data
+      item === 'type' || item === 'activated' || item === 'uuid') {
+      continue;
+    }
+      data[item] = entityData[item];
+    }
+    var options =  {
+      method:method,
+      endpoint:type,
+      body:data
+    };
+    //save the entity first
+    this._client.request(options, function (err, retdata) {
+      //clear out pw info if present
+      self.set('password', null);
+      self.set('oldpassword', null);
+      self.set('newpassword', null);
+      if (err && self._client.logging) {
+        console.log('could not save entity');
+        if (typeof(callback) === 'function') {
+          return callback(err, retdata, self);
+        }
+      } else {
+        if (retdata.entities) {
+          if (retdata.entities.length) {
+            var entity = retdata.entities[0];
+            self.set(entity);
+            var path = retdata.path;
+            //for connections, API returns type
+            while (path.substring(0, 1) === "/") {
+              path = path.substring(1);
+            }
+            self.set('type', path);
+          }
+        }
+        //if this is a user, update the password if it has been specified;
+        var needPasswordChange = ((self.get('type') === 'user' || self.get('type') === 'users') && oldpassword && newpassword);
+        if (needPasswordChange) {
+          //Note: we have a ticket in to change PUT calls to /users to accept the password change
+          //      once that is done, we will remove this call and merge it all into one
+          var pwdata = {};
+          pwdata.oldpassword = oldpassword;
+          pwdata.newpassword = newpassword;
+          var options = {
+            method:'PUT',
+            endpoint:type+'/password',
+            body:pwdata
+          }
+          self._client.request(options, function (err, data) {
+            if (err && self._client.logging) {
+              console.log('could not update user');
+            }
+            //remove old and new password fields so they don't end up as part of the entity object
+            self.set('oldpassword', null);
+            self.set('newpassword', null);
+            if (typeof(callback) === 'function') {
+              callback(err, data, self);
+            }
+          });
+        } else if (typeof(callback) === 'function') {
+          callback(err, retdata, self);
+        }
+      }
+    });
+  }
+
+  /*
+  *  refreshes the entity by making a GET call back to the database
+  *
+  *  @method fetch
+  *  @public
+  *  @param {function} callback
+  *  @return {callback} callback(err, data)
+  */
+  Usergrid.Entity.prototype.fetch = function (callback) {
+    var type = this.get('type');
+    var self = this;
+
+  //Check for an entity type, then if a uuid is available, use that, otherwise, use the name
+  try {
+    if (type === undefined) {
+      throw 'cannot fetch entity, no entity type specified'
+    } else if (this.get('uuid')) {
+      type += '/' + this.get('uuid');
+    } else if (type === 'users' && this.get('username')) {
+      type += '/' + this.get('username');
+    } else if (this.get('name')) {
+      type += '/' + encodeURIComponent(this.get('name'));
+    } else if (typeof(callback) === 'function') {
+      throw 'no_name_specified';
+    }
+  } catch (e) {
+    if (self._client.logging) {
+      console.log(e);
+    }
+    return callback(true, {
+      error: e
+    }, self);
+  }
+    var options = {
+      method:'GET',
+      endpoint:type
+    };
+    this._client.request(options, function (err, data) {
+      if (err && self._client.logging) {
+        console.log('could not get entity');
+      } else {
+        if (data.user) {
+          self.set(data.user);
+          self._json = JSON.stringify(data.user, null, 2);
+        } else if (data.entities) {
+          if (data.entities.length) {
+            var entity = data.entities[0];
+            self.set(entity);
+          }
+        }
+      }
+      if (typeof(callback) === 'function') {
+        callback(err, data, self);
+      }
+    });
+  }
+
+  /*
+  *  deletes the entity from the database - will only delete
+  *  if the object has a valid uuid
+  *
+  *  @method destroy
+  *  @public
+  *  @param {function} callback
+  *  @return {callback} callback(err, data)
+  *
+  */
+  Usergrid.Entity.prototype.destroy = function (callback) {
+    var self = this;
+    var type = this.get('type');
+    var id = this.getEntityId(this);
+    if (!id) {
+      if (typeof(callback) === 'function') {
+        var error = 'Error trying to delete object - no uuid or name specified.';
+        if (self._client.logging) {
+          console.log(error);
+        }
+        return callback(true, error);
+      }
+    }
+    type += '/' + this.get('uuid');
+    var options = {
+      method:'DELETE',
+      endpoint:type
+    };
+    this._client.request(options, function (err, data) {
+      if (err && self._client.logging) {
+        console.log('entity could not be deleted');
+      } else {
+        self.set(null);
+      }
+      if (typeof(callback) === 'function') {
+        callback(err, data);
+      }
+    });
+  }
+
+  /*
+  *  connects one entity to another
+  *
+  *  @method connect
+  *  @public
+  *  @param {string} connection
+  *  @param {object} entity
+  *  @param {function} callback
+  *  @return {callback} callback(err, data)
+  *
+  */
+  Usergrid.Entity.prototype.connect = function (connection, entity, callback) {
+
+    var self = this;
+
+    //connectee info
+    var connecteeType = entity.get('type');
+    var connectee = this.getEntityId(entity);
+    if (!connectee) {
+      if (typeof(callback) === 'function') {
+        var error = 'Error trying to connect object - no uuid specified.';
+        if (self._client.logging) {
+          console.log(error);
+        }
+        callback(true, error);
+      }
+      return;
+    }
+
+    //connector info
+    var connectorType = this.get('type');
+    var connector = this.getEntityId(this);
+    if (!connector) {
+      if (typeof(callback) === 'function') {
+        var error = 'Error in connect - no uuid specified.';
+        if (self._client.logging) {
+          console.log(error);
+        }
+        callback(true, error);
+      }
+      return;
+    }
+
+    var endpoint = connectorType + '/' + connector + '/' + connection + '/' + connecteeType + '/' + connectee;
+    var options = {
+      method:'POST',
+      endpoint:endpoint
+    };
+    this._client.request(options, function (err, data) {
+      if (err && self._client.logging) {
+        console.log('entity could not be connected');
+      }
+      if (typeof(callback) === 'function') {
+        callback(err, data);
+      }
+    });
+  }
+
+  /*
+  *  returns a unique identifier for an entity
+  *
+  *  @method connect
+  *  @public
+  *  @param {object} entity
+  *  @param {function} callback
+  *  @return {callback} callback(err, data)
+  *
+  */
+  Usergrid.Entity.prototype.getEntityId = function (entity) {
+    return entity.get('uuid') || entity.get('username') || entity.get('name') || false;
+  }
+
+  /*
+  *  gets an entities connections
+  *
+  *  @method getConnections
+  *  @public
+  *  @param {string} connection
+  *  @param {opts} options (actually, just options.qs for now)
+  *  @param {function} callback
+  *  @return {callback} callback(err, data, connections)
+  *
+  */
+  Usergrid.Entity.prototype.getConnections = function (connection, opts, callback) {
+
+    if (typeof(opts) == "function") { callback = opts; opts = undefined; }
+
+    var self = this;
+
+    //connector info
+    var connectorType = inflection.pluralize(this.get('type'));
+    var connector = this.getEntityId(this);
+    if (!connector) {
+      if (typeof(callback) === 'function') {
+        var error = 'Error in getConnections - no uuid specified.';
+        if (self._client.logging) {
+          console.log(error);
+        }
+        callback(true, error);
+      }
+      return;
+    }
+
+    var endpoint = connectorType + '/' + connector + '/' + connection + '/';
+    var options = {
+      method:'GET',
+      endpoint:endpoint
+    };
+    if (opts && opts.qs) { options.qs = opts.qs; }
+    this._client.request(options, function (err, data) {
+      if (err && self._client.logging) {
+        console.log('entity connections could not be retrieved');
+      }
+
+      self[connection] = {};
+
+      var length = data.entities.length;
+      for (var i=0;i<length;i++)
+      {
+        if (data.entities[i].type === 'user'){
+          self[connection][data.entities[i].username] = data.entities[i];
+        } else {
+          self[connection][data.entities[i].name] = data.entities[i];
+        }
+      }
+
+      if (typeof(callback) === 'function') {
+        callback(err, data, data.entities);
+      }
+    });
+
+  }
+
+  Usergrid.Entity.prototype.getGroups = function (callback) {
+
+    var self = this;
+
+    var endpoint = 'users' + '/' + this.get('uuid') + '/groups' ;
+    var options = {
+      method:'GET',
+      endpoint:endpoint
+    };
+    this._client.request(options, function (err, data) {
+      if (err && self._client.logging) {
+        console.log('entity could not be connected');
+      }
+
+      self['groups'] = data.entities;
+
+      if (typeof(callback) === 'function') {
+        callback(err, data, data.entities);
+      }
+    });
+
+  }
+
+  Usergrid.Entity.prototype.getActivities = function (callback) {
+
+    var self = this;
+
+    var endpoint = this.get('type') + '/' + this.get('uuid') + '/activities' ;
+    var options = {
+      method:'GET',
+      endpoint:endpoint
+    };
+    this._client.request(options, function (err, data) {
+      if (err && self._client.logging) {
+        console.log('entity could not be connected');
+      }
+
+      for(entity in data.entities) {
+        data.entities[entity].createdDate = (new Date(data.entities[entity].created)).toUTCString();
+      }
+
+      self['activities'] = data.entities;
+
+      if (typeof(callback) === 'function') {
+        callback(err, data, data.entities);
+      }
+    });
+
+  }
+
+  Usergrid.Entity.prototype.getFollowing = function (callback) {
+
+    var self = this;
+
+    var endpoint = 'users' + '/' + this.get('uuid') + '/following' ;
+    var options = {
+      method:'GET',
+      endpoint:endpoint
+    };
+    this._client.request(options, function (err, data) {
+      if (err && self._client.logging) {
+        console.log('could not get user following');
+      }
+
+      for(entity in data.entities) {
+        data.entities[entity].createdDate = (new Date(data.entities[entity].created)).toUTCString();
+        var image = self._client.getDisplayImage(data.entities[entity].email, data.entities[entity].picture);
+        data.entities[entity]._portal_image_icon =  image;
+      }
+
+      self['following'] = data.entities;
+
+      if (typeof(callback) === 'function') {
+        callback(err, data, data.entities);
+      }
+    });
+
+  }
+
+
+  Usergrid.Entity.prototype.getFollowers = function (callback) {
+
+    var self = this;
+
+    var endpoint = 'users' + '/' + this.get('uuid') + '/followers' ;
+    var options = {
+      method:'GET',
+      endpoint:endpoint
+    };
+    this._client.request(options, function (err, data) {
+      if (err && self._client.logging) {
+        console.log('could not get user followers');
+      }
+
+      for(entity in data.entities) {
+        data.entities[entity].createdDate = (new Date(data.entities[entity].created)).toUTCString();
+        var image = self._client.getDisplayImage(data.entities[entity].email, data.entities[entity].picture);
+        data.entities[entity]._portal_image_icon =  image;
+      }
+
+      self['followers'] = data.entities;
+
+      if (typeof(callback) === 'function') {
+        callback(err, data, data.entities);
+      }
+    });
+
+  }
+
+  Usergrid.Entity.prototype.getRoles = function (callback) {
+
+    var self = this;
+
+    var endpoint = this.get('type') + '/' + this.get('uuid') + '/roles' ;
+    var options = {
+      method:'GET',
+      endpoint:endpoint
+    };
+    this._client.request(options, function (err, data) {
+      if (err && self._client.logging) {
+        console.log('could not get user roles');
+      }
+
+      self['roles'] = data.entities;
+
+      if (typeof(callback) === 'function') {
+        callback(err, data, data.entities);
+      }
+    });
+
+  }
+
+  Usergrid.Client.prototype.createRole = function(roleName, permissions, callback) {
+
+      var self = this;
+      var options = {
+          type: 'role',
+          name: roleName
+      };
+
+      this.createEntity(options, function(err, entity, response) {
+          if (err) {
+              callback (err, response, self);
+          } else {
+              entity.assignPermissions(permissions, function (err, data) {
+                  if (err) {
+                      callback (err, response, self);
+                  } else {
+                      callback (err, data, data.data);
+                  }
+              })
+          }
+      });
+
+  };
+  Usergrid.Entity.prototype.assignRole = function(roleName, callback) {
+
+      var self = this;
+      var type = self.get('type');
+      var collection = type + 's';
+      var entityID;
+
+      if (type == 'user' && this.get('username') != null) {
+          entityID = self.get('username');
+      } else if (type == 'group' && this.get('name') != null) {
+          entityID = self.get('name');
+      } else if (this.get('uuid') != null) {
+          entityID = self.get('uuid');
+      }
+
+      if (type != 'users' && type != 'groups') {
+          callback ('entity must be a group or user', null, this);
+      }
+
+      var endpoint = 'roles/' + roleName + '/' + collection + '/' + entityID;
+      var options = {
+          method: 'POST',
+          endpoint: endpoint
+      };
+
+      this._client.request(options, function(err, response) {
+          if (err) {
+              console.log('Could not assign role.');
+          }
+          callback (err, response, self);
+      });
+
+  };
+
+  Usergrid.Entity.prototype.removeRole = function(roleName, callback) {
+
+      var self = this;
+      var type = self.get('type');
+      var collection = type + 's';
+      var entityID;
+
+      if (type == 'user' && this.get('username') != null) {
+          entityID = this.get('username');
+      } else if (type == 'group' && this.get('name') != null) {
+          entityID = this.get('name');
+      } else if (this.get('uuid') != null) {
+          entityID = this.get('uuid');
+      }
+
+      if (type != 'users' && type != 'groups') {
+          callback ('entity must be a group or user', null, this);
+      }
+
+      var endpoint = 'roles/' + roleName + '/' + collection + '/' + entityID;
+      var options = {
+          method: 'DELETE',
+          endpoint: endpoint
+      };
+
+      this._client.request(options, function(err, response) {
+          if (err) {
+              console.log('Could not assign role.');
+          }
+          callback (err, response, self);
+      });
+
+  };
+
+  Usergrid.Entity.prototype.assignPermissions = function(permissions, callback) {
+      var self = this;
+      var entityID;
+      var type = this.get("type");
+
+      if (type != 'user' && type != 'users' && type != 'group' && type != 'groups') {
+          callback( 'entity must be a group or user', null, this);
+      }
+
+      if (type == 'user' && this.get("username") != null) {
+          entityID = this.get("username");
+      } else if (type == 'group' && this.get("name") != null) {
+          entityID = this.get("name");
+      } else if (this.get("uuid") != null) {
+          entityID = this.get("uuid");
+      }
+
+      var endpoint = type + "/" + entityID + "/permissions";
+      var options = {
+          method: "POST",
+          endpoint: endpoint,
+          body: {
+              'permission': permissions
+          }
+      };
+      this._client.request(options, function(err, data) {
+          if (err && self._client.logging) {
+              console.log("could not assign permissions");
+          }
+          callback (err, data, data.data);
+      });
+  };
+
+  Usergrid.Entity.prototype.removePermissions = function(permissions, callback) {
+      var self = this;
+      var entityID;
+      var type = this.get("type");
+
+      if (type != 'user' && type != 'users' && type != 'group' && type != 'groups') {
+          callback ('entity must be a group or user', null, this);
+      }
+
+      if (type == 'user' && this.get("username") != null) {
+          entityID = this.get("username");
+      } else if (type == 'group' && this.get("name") != null) {
+          entityID = this.get("name");
+      } else if (this.get("uuid") != null) {
+          entityID = this.get("uuid");
+      }
+
+      var endpoint = type + "/" + entityID + "/permissions";
+      var options = {
+          method: "DELETE",
+          endpoint: endpoint,
+          qs: {
+              'permission': permissions
+          }
+      };
+      this._client.request(options, function(err, data) {
+          if (err && self._client.logging) {
+              console.log("could not remove permissions");
+          }
+          callback (err, data, data.params.permission);
+      });
+  };
+  Usergrid.Entity.prototype.getPermissions = function (callback) {
+
+    var self = this;
+
+    var endpoint = this.get('type') + '/' + this.get('uuid') + '/permissions' ;
+    var options = {
+      method:'GET',
+      endpoint:endpoint
+    };
+    this._client.request(options, function (err, data) {
+      if (err && self._client.logging) {
+        console.log('could not get user permissions');
+      }
+
+      var permissions = [];
+      if (data.data) {
+        var perms = data.data;
+        var count = 0;
+
+        for (var i in perms) {
+          count++;
+          var perm = perms[i];
+          var parts = perm.split(':');
+          var ops_part = "";
+          var path_part = parts[0];
+
+          if (parts.length > 1) {
+            ops_part = parts[0];
+            path_part = parts[1];
+          }
+
+          ops_part.replace("*", "get,post,put,delete")
+          var ops = ops_part.split(',');
+          var ops_object = {}
+          ops_object['get'] = 'no';
+          ops_object['post'] = 'no';
+          ops_object['put'] = 'no';
+          ops_object['delete'] = 'no';
+          for (var j in ops) {
+            ops_object[ops[j]] = 'yes';
+          }
+
+          permissions.push( {operations : ops_object, path : path_part, perm : perm});
+        }
+      }
+
+      self['permissions'] = permissions;
+
+      if (typeof(callback) === 'function') {
+        callback(err, data, data.entities);
+      }
+    });
+
+  }
+
+  /*
+  *  disconnects one entity from another
+  *
+  *  @method disconnect
+  *  @public
+  *  @param {string} connection
+  *  @param {object} entity
+  *  @param {function} callback
+  *  @return {callback} callback(err, data)
+  *
+  */
+  Usergrid.Entity.prototype.disconnect = function (connection, entity, callback) {
+
+    var self = this;
+
+    //connectee info
+    var connecteeType = entity.get('type');
+    var connectee = this.getEntityId(entity);
+    if (!connectee) {
+      if (typeof(callback) === 'function') {
+        var error = 'Error trying to delete object - no uuid specified.';
+        if (self._client.logging) {
+          console.log(error);
+        }
+        callback(true, error);
+      }
+      return;
+    }
+
+    //connector info
+    var connectorType = this.get('type');
+    var connector = this.getEntityId(this);
+    if (!connector) {
+      if (typeof(callback) === 'function') {
+        var error = 'Error in connect - no uuid specified.';
+        if (self._client.logging) {
+          console.log(error);
+        }
+        callback(true, error);
+      }
+      return;
+    }
+
+    var endpoint = connectorType + '/' + connector + '/' + connection + '/' + connecteeType + '/' + connectee;
+    var options = {
+      method:'DELETE',
+      endpoint:endpoint
+    };
+    this._client.request(options, function (err, data) {
+      if (err && self._client.logging) {
+        console.log('entity could not be disconnected');
+      }
+      if (typeof(callback) === 'function') {
+        callback(err, data);
+      }
+    });
+  }
+
+/*
+ *  calls delete on the database w/ the passed query
+ *
+ *  @method delete
+ *  @param {opts} options containing query (include options.qs)
+ *  @param {function} callback
+ *  @return {callback} callback(err, data)
+ *
+ */
+Usergrid.Client.prototype.delete = function(opts, callback) {
+  if (typeof(opts) == "function") { callback = opts; opts = undefined; }
+
+  if (!opts.qs.q) { opts.qs.q = '*'; }
+
+  var options = {
+    method: 'DELETE',
+    endpoint: opts.type,
+    qs: opts.qs
+  };
+  var self = this;
+  this.request(options, function (err, data) {
+    if (err && self.logging) {
+      console.log('entities could not be deleted');
+    }
+    if (typeof(callback) === 'function') {
+      callback(err, data);
+    }
+  });
+};
+
+  /*
+  *  The Collection class models Usergrid Collections.  It essentially
+  *  acts as a container for holding Entity objects, while providing
+  *  additional funcitonality such as paging, and saving
+  *
+  *  @constructor
+  *  @param {string} options - configuration object
+  *  @param {function} callback
+  *  @return {callback} callback(err, data)
+  */
+  Usergrid.Collection = function(options, callback) {
+
+    if (options) {
+      this._client = options.client;
+      this._type = options.type;
+      this.qs = options.qs || {};
+
+      //iteration
+      this._list = options.list || [];
+      this._iterator = options.iterator || -1; //first thing we do is increment, so set to -1
+
+      //paging
+      this._previous = options.previous || [];
+      this._next = options.next || null;
+      this._cursor = options.cursor || null;
+
+      //restore entities if available
+      if (options.list) {
+        var count = options.list.length;
+        for(var i=0;i<count;i++){
+          //make new entity with
+          var entity = this._client.restoreEntity(options.list[i]);
+          this._list[i] = entity;
+        }
+      }
+    }
+    if (callback) {
+      //populate the collection
+      this.fetch(callback);
+    }
+
+  }
+
+
+  /*
+   *  gets the data from the collection object for serialization
+   *
+   *  @method serialize
+   *  @return {object} data
+   */
+  Usergrid.Collection.prototype.serialize = function () {
+
+    //pull out the state from this object and return it
+    var data = {}
+    data.type = this._type;
+    data.qs = this.qs;
+    data.iterator = this._iterator;
+    data.previous = this._previous;
+    data.next = this._next;
+    data.cursor = this._cursor;
+
+    this.resetEntityPointer();
+    var i=0;
+    data.list = [];
+    while(this.hasNextEntity()) {
+      var entity = this.getNextEntity();
+      data.list[i] = entity.serialize();
+      i++;
+    }
+
+    data = JSON.stringify(data);
+    return data;
+  }
+
+  Usergrid.Collection.prototype.addCollection = function (collectionName, options, callback) {
+    self = this;
+    options.client = this._client;
+    var collection = new Usergrid.Collection(options, function(err, data) {
+      if (typeof(callback) === 'function') {
+
+        collection.resetEntityPointer();
+        while(collection.hasNextEntity()) {
+          var user = collection.getNextEntity();
+          var email = user.get('email');
+          var image = self._client.getDisplayImage(user.get('email'), user.get('picture'));
+          user._portal_image_icon = image;
+        }
+
+        self[collectionName] = collection;
+        callback(err, collection);
+      }
+    });
+  }
+
+  /*
+  *  Populates the collection from the server
+  *
+  *  @method fetch
+  *  @param {function} callback
+  *  @return {callback} callback(err, data)
+  */
+  Usergrid.Collection.prototype.fetch = function (callback) {
+    var self = this;
+    var qs = this.qs;
+
+    //add in the cursor if one is available
+    if (this._cursor) {
+      qs.cursor = this._cursor;
+    } else {
+      delete qs.cursor;
+    }
+    var options = {
+      method:'GET',
+      endpoint:this._type,
+      qs:this.qs
+    };
+    this._client.request(options, function (err, data) {
+      if(err && self._client.logging) {
+       console.log('error getting collection');
+      } else {
+        //save the cursor if there is one
+        var cursor = data.cursor || null;
+        self.saveCursor(cursor);
+        if (data.entities) {
+          self.resetEntityPointer();
+          var count = data.entities.length;
+          //save entities locally
+          self._list = []; //clear the local list first
+          for (var i=0;i<count;i++) {
+            var uuid = data.entities[i].uuid;
+            if (uuid) {
+              var entityData = data.entities[i] || {};
+              self._baseType = data.entities[i].type; //store the base type in the collection
+              entityData.type = self._type;//make sure entities are same type (have same path) as parent collection.
+              var entityOptions = {
+                type:self._type,
+                client:self._client,
+                uuid:uuid,
+                data:entityData
+              };
+
+              var ent = new Usergrid.Entity(entityOptions);
+              ent._json = JSON.stringify(entityData, null, 2);
+              var ct = self._list.length;
+              self._list[ct] = ent;
+            }
+          }
+        }
+      }
+      if (typeof(callback) === 'function') {
+        callback(err, data);
+      }
+    });
+  }
+
+  /*
+  *  Adds a new Entity to the collection (saves, then adds to the local object)
+  *
+  *  @method addNewEntity
+  *  @param {object} entity
+  *  @param {function} callback
+  *  @return {callback} callback(err, data, entity)
+  */
+  Usergrid.Collection.prototype.addEntity = function (options, callback) {
+    var self = this;
+    options.type = this._type;
+
+    //create the new entity
+    this._client.createEntity(options, function (err, entity) {
+      if (!err) {
+        //then add the entity to the list
+        var count = self._list.length;
+        self._list[count] = entity;
+      }
+      if (typeof(callback) === 'function') {
+        callback(err, entity);
+      }
+    });
+  }
+
+  Usergrid.Collection.prototype.addExistingEntity = function (entity) {
+    //entity should already exist in the db, so just add it to the list
+    var count = this._list.length;
+    this._list[count] = entity;
+  }
+
+  /*
+  *  Removes the Entity from the collection, then destroys the object on the server
+  *
+  *  @method destroyEntity
+  *  @param {object} entity
+  *  @param {function} callback
+  *  @return {callback} callback(err, data)
+  */
+  Usergrid.Collection.prototype.destroyEntity = function (entity, callback) {
+    var self = this;
+    entity.destroy(function(err, data) {
+      if (err) {
+        if (self._client.logging) {
+          console.log('could not destroy entity');
+        }
+        if (typeof(callback) === 'function') {
+          callback(err, data);
+        }
+      } else {
+        //destroy was good, so repopulate the collection
+        self.fetch(callback);
+      }
+    });
+    //remove entity from the local store
+    this.removeEntity(entity);
+  }
+
+
+  Usergrid.Collection.prototype.removeEntity = function (entity) {
+    var uuid = entity.get('uuid');
+    for (key in this._list) {
+      var listItem = this._list[key];
+      if (listItem.get('uuid') === uuid) {
+        return this._list.splice(key, 1);
+      }
+    }
+    return false;
+  }
+
+  /*
+  *  Looks up an Entity by UUID
+  *
+  *  @method getEntityByUUID
+  *  @param {string} UUID
+  *  @param {function} callback
+  *  @return {callback} callback(err, data, entity)
+  */
+  Usergrid.Collection.prototype.getEntityByUUID = function (uuid, callback) {
+
+    for (key in this._list) {
+      var listItem = this._list[key];
+      if (listItem.get('uuid') === uuid) {
+        return listItem;
+      }
+    }
+
+    //get the entity from the database
+    var options = {
+      data: {
+        type: this._type,
+        uuid:uuid
+      },
+      client: this._client
+    }
+    var entity = new Usergrid.Entity(options);
+    entity.fetch(callback);
+  }
+
+  /*
+  *  Returns the first Entity of the Entity list - does not affect the iterator
+  *
+  *  @method getFirstEntity
+  *  @return {object} returns an entity object
+  */
+  Usergrid.Collection.prototype.getFirstEntity = function () {
+    var count = this._list.length;
+    if (count > 0) {
+      return this._list[0];
+    }
+    return null;
+  }
+
+  /*
+  *  Returns the last Entity of the Entity list - does not affect the iterator
+  *
+  *  @method getLastEntity
+  *  @return {object} returns an entity object
+  */
+  Usergrid.Collection.prototype.getLastEntity = function () {
+    var count = this._list.length;
+    if (count > 0) {
+      return this._list[count-1];
+    }
+    return null;
+  }
+
+  /*
+  *  Entity iteration -Checks to see if there is a "next" entity
+  *  in the list.  The first time this method is called on an entity
+  *  list, or after the resetEntityPointer method is called, it will
+  *  return true referencing the first entity in the list
+  *
+  *  @method hasNextEntity
+  *  @return {boolean} true if there is a next entity, false if not
+  */
+  Usergrid.Collection.prototype.hasNextEntity = function () {
+    var next = this._iterator + 1;
+    var hasNextElement = (next >=0 && next < this._list.length);
+    if(hasNextElement) {
+      return true;
+    }
+    return false;
+  }
+
+  /*
+  *  Entity iteration - Gets the "next" entity in the list.  The first
+  *  time this method is called on an entity list, or after the method
+  *  resetEntityPointer is called, it will return the,
+  *  first entity in the list
+  *
+  *  @method hasNextEntity
+  *  @return {object} entity
+  */
+  Usergrid.Collection.prototype.getNextEntity = function () {
+    this._iterator++;
+    var hasNextElement = (this._iterator >= 0 && this._iterator <= this._list.length);
+    if(hasNextElement) {
+      return this._list[this._iterator];
+    }
+    return false;
+  }
+
+  /*
+  *  Entity iteration - Checks to see if there is a "previous"
+  *  entity in the list.
+  *
+  *  @method hasPrevEntity
+  *  @return {boolean} true if there is a previous entity, false if not
+  */
+  Usergrid.Collection.prototype.hasPrevEntity = function () {
+    var previous = this._iterator - 1;
+    var hasPreviousElement = (previous >=0 && previous < this._list.length);
+    if(hasPreviousElement) {
+      return true;
+    }
+    return false;
+  }
+
+  /*
+  *  Entity iteration - Gets the "previous" entity in the list.
+  *
+  *  @method getPrevEntity
+  *  @return {object} entity
+  */
+  Usergrid.Collection.prototype.getPrevEntity = function () {
+     this._iterator--;
+     var hasPreviousElement = (this._iterator >= 0 && this._iterator <= this._list.length);
+     if(hasPreviousElement) {
+      return this.list[this._iterator];
+     }
+     return false;
+  }
+
+  /*
+  *  Entity iteration - Resets the iterator back to the beginning
+  *  of the list
+  *
+  *  @method resetEntityPointer
+  *  @return none
+  */
+  Usergrid.Collection.prototype.resetEntityPointer = function () {
+     this._iterator  = -1;
+  }
+
+  /*
+  * Method to save off the cursor just returned by the last API call
+  *
+  * @public
+  * @method saveCursor
+  * @return none
+  */
+  Usergrid.Collection.prototype.saveCursor = function(cursor) {
+    //if current cursor is different, grab it for next cursor
+    if (this._next !== cursor) {
+      this._next = cursor;
+    }
+  }
+
+  /*
+  * Resets the paging pointer (back to original page)
+  *
+  * @public
+  * @method resetPaging
+  * @return none
+  */
+  Usergrid.Collection.prototype.resetPaging = function() {
+    this._previous = [];
+    this._next = null;
+    this._cursor = null;
+  }
+
+  /*
+  *  Paging -  checks to see if there is a next page od data
+  *
+  *  @method hasNextPage
+  *  @return {boolean} returns true if there is a next page of data, false otherwise
+  */
+  Usergrid.Collection.prototype.hasNextPage = function () {
+    return !!this._next;
+  }
+
+  /*
+  *  Paging - advances the cursor and gets the next
+  *  page of data from the API.  Stores returned entities
+  *  in the Entity list.
+  *
+  *  @method getNextPage
+  *  @param {function} callback
+  *  @return {callback} callback(err, data)
+  */
+  Usergrid.Collection.prototype.getNextPage = function (callback) {
+    if (this.hasNextPage()) {
+      //set the cursor to the next page of data
+      this._previous.push(this._cursor);
+      this._cursor = this._next;
+      //empty the list
+      this._list = [];
+      this.fetch(callback);
+    }
+  }
+
+  /*
+  *  Paging -  checks to see if there is a previous page od data
+  *
+  *  @method hasPreviousPage
+  *  @return {boolean} returns true if there is a previous page of data, false otherwise
+  */
+  Usergrid.Collection.prototype.hasPreviousPage = function () {
+    return (this._previous.length > 0);
+  }
+
+  /*
+  *  Paging - reverts the cursor and gets the previous
+  *  page of data from the API.  Stores returned entities
+  *  in the Entity list.
+  *
+  *  @method getPreviousPage
+  *  @param {function} callback
+  *  @return {callback} callback(err, data)
+  */
+  Usergrid.Collection.prototype.getPreviousPage = function (callback) {
+    if (this.hasPreviousPage()) {
+      this._next=null; //clear out next so the comparison will find the next item
+      this._cursor = this._previous.pop();
+      //empty the list
+      this._list = [];
+      this.fetch(callback);
+    }
+  }
+
+
+  /*
+   *  A class to model a Usergrid group.
+   *  Set the path in the options object.
+   *
+   *  @constructor
+   *  @param {object} options {client:client, data: {'key': 'value'}, path:'path'}
+   */
+  Usergrid.Group = function(options, callback) {
+    this._path = options.path;
+    this._list = [];
+    this._client = options.client;
+    this._data = options.data || {};
+    this._data.type = "groups";
+  }
+
+  /*
+   *  Inherit from Usergrid.Entity.
+   *  Note: This only accounts for data on the group object itself.
+   *  You need to use add and remove to manipulate group membership.
+   */
+  Usergrid.Group.prototype = new Usergrid.Entity();
+
+  /*
+  *  Fetches current group data, and members.
+  *
+  *  @method fetch
+  *  @public
+  *  @param {function} callback
+  *  @returns {function} callback(err, data)
+  */
+  Usergrid.Group.prototype.fetch = function(callback) {
+    var self = this;
+    var groupEndpoint = 'groups/'+this._path;
+    var memberEndpoint = 'groups/'+this._path+'/users';
+
+    var groupOptions = {
+      method:'GET',
+      endpoint:groupEndpoint
+    }
+
+    var memberOptions = {
+      method:'GET',
+      endpoint:memberEndpoint
+    }
+
+    this._client.request(groupOptions, function(err, data){
+      if(err) {
+        if(self._client.logging) {
+          console.log('error getting group');
+        }
+        if(typeof(callback) === 'function') {
+          callback(err, data);
+        }
+      } else {
+        if(data.entities) {
+          var groupData = data.entities[0];
+          self._data = groupData || {};
+          self._client.request(memberOptions, function(err, data) {
+            if(err && self._client.logging) {
+              console.log('error getting group users');
+            } else {
+              if(data.entities) {
+                var count = data.entities.length;
+                self._list = [];
+                for (var i = 0; i < count; i++) {
+                  var uuid = data.entities[i].uuid;
+                  if(uuid) {
+                    var entityData = data.entities[i] || {};
+                    var entityOptions = {
+                      type: entityData.type,
+                      client: self._client,
+                      uuid:uuid,
+                      data:entityData
+                    };
+                    var entity = new Usergrid.Entity(entityOptions);
+                    self._list.push(entity);
+                  }
+
+                }
+              }
+            }
+            if(typeof(callback) === 'function') {
+              callback(err, data, self._list);
+            }
+          });
+        }
+      }
+    });
+  }
+
+  /*
+   *  Retrieves the members of a group.
+   *
+   *  @method members
+   *  @public
+   *  @param {function} callback
+   *  @return {function} callback(err, data);
+   */
+  Usergrid.Group.prototype.members = function(callback) {
+    if(typeof(callback) === 'function') {
+      callback(null, this._list);
+    }
+  }
+
+  /*
+   *  Adds a user to the group, and refreshes the group object.
+   *
+   *  Options object: {user: user_entity}
+   *
+   *  @method add
+   *  @public
+   *  @params {object} options
+   *  @param {function} callback
+   *  @return {function} callback(err, data)
+   */
+  Usergrid.Group.prototype.add = function(options, callback) {
+    var self = this;
+    var options = {
+      method:"POST",
+      endpoint:"groups/"+this._path+"/users/"+options.user.get('username')
+    }
+
+    this._client.request(options, function(error, data){
+      if(error) {
+        if(typeof(callback) === 'function') {
+          callback(error, data, data.entities);
+        }
+      } else {
+        self.fetch(callback);
+      }
+    });
+  }
+
+  /*
+   *  Removes a user from a group, and refreshes the group object.
+   *
+   *  Options object: {user: user_entity}
+   *
+   *  @method remove
+   *  @public
+   *  @params {object} options
+   *  @param {function} callback
+   *  @return {function} callback(err, data)
+   */
+  Usergrid.Group.prototype.remove = function(options, callback) {
+    var self = this;
+
+    var options = {
+      method:"DELETE",
+      endpoint:"groups/"+this._path+"/users/"+options.user.username
+    }
+
+    this._client.request(options, function(error, data){
+      if(error) {
+        if(typeof(callback) === 'function') {
+          callback(error, data);
+        }
+      } else {
+        self.fetch(callback);
+      }
+    });
+  }
+
+  /*
+  * Gets feed for a group.
+  *
+  * @public
+  * @method feed
+  * @param {function} callback
+  * @returns {callback} callback(err, data, activities)
+  */
+  Usergrid.Group.prototype.feed = function(callback) {
+    var self = this;
+
+    var endpoint = "groups/"+this._path+"/feed";
+
+    var options = {
+      method:"GET",
+      endpoint:endpoint
+    }
+
+    this._client.request(options, function(err, data){
+      if (err && self.logging) {
+        console.log('error trying to log user in');
+      }
+      if(typeof(callback) === 'function') {
+          callback(err, data, data.entities);
+      }
+    });
+  }
+
+  /*
+  * Creates activity and posts to group feed.
+  *
+  * options object: {user: user_entity, content: "activity content"}
+  *
+  * @public
+  * @method createGroupActivity
+  * @params {object} options
+  * @param {function} callback
+  * @returns {callback} callback(err, entity)
+  */
+  Usergrid.Group.prototype.createGroupActivity = function(options, callback){
+    var user = options.user;
+    var options = {
+      actor: {
+        "displayName":user.get("username"),
+        "uuid":user.get("uuid"),
+        "username":user.get("username"),
+        "email":user.get("email"),
+        "picture":user.get("picture"),
+        "image": {
+          "duration":0,
+          "height":80,
+          "url":user.get("picture"),
+          "width":80
+         },
+      },
+      "verb":"post",
+      "content":options.content };
+
+      options.type = 'groups/'+this._path+'/activities';
+      var options = {
+        client:this._client,
+        data:options
+      }
+
+      var entity = new Usergrid.Entity(options);
+      entity.save(function(err, data) {
+        if (typeof(callback) === 'function') {
+          callback(err, entity);
+        }
+      });
+  }
+
+  /*
+  * Tests if the string is a uuid
+  *
+  * @public
+  * @method isUUID
+  * @param {string} uuid The string to test
+  * @returns {Boolean} true if string is uuid
+  */
+  function isUUID (uuid) {
+    var uuidValueRegex = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
+    if (!uuid) return false;
+    return uuidValueRegex.test(uuid);
+  }
+
+  /*
+  *  method to encode the query string parameters
+  *
+  *  @method encodeParams
+  *  @public
+  *  @params {object} params - an object of name value pairs that will be urlencoded
+  *  @return {string} Returns the encoded string
+  */
+  function encodeParams (params) {
+    tail = [];
+    var item = [];
+    if (params instanceof Array) {
+      for (i in params) {
+        item = params[i];
+        if ((item instanceof Array) && (item.length > 1)) {
+          tail.push(item[0] + "=" + encodeURIComponent(item[1]));
+        }
+      }
+    } else {
+      for (var key in params) {
+        if (params.hasOwnProperty(key)) {
+          var value = params[key];
+          if (value instanceof Array) {
+            for (i in value) {
+              item = value[i];
+              tail.push(key + "=" + encodeURIComponent(item));
+            }
+          } else {
+            tail.push(key + "=" + encodeURIComponent(value));
+          }
+        }
+      }
+    }
+    return tail.join("&");
+  }
+/*
+ *  A class to model a Usergrid event.
+ *
+ *  @constructor
+ *  @param {object} options {timestamp:0, category:'value', counters:{name : value}}
+ *  @returns {callback} callback(err, event)
+ */
+Usergrid.Counter = function(options, callback) {
+  var self=this;
+  this._client = options.client;
+  this._data = options.data || {};
+  this._data.category = options.category||"UNKNOWN";
+  this._data.timestamp = options.timestamp||0;
+  this._data.type = "events";
+  this._data.counters=options.counters||{};
+  if(typeof(callback) === 'function') {
+    callback.call(self, false, self);
+  }
+  //this.save(callback);
+};
+var COUNTER_RESOLUTIONS=[
+  'all', 'minute', 'five_minutes', 'half_hour',
+  'hour', 'six_day', 'day', 'week', 'month'
+];
+/*
+ *  Inherit from Usergrid.Entity.
+ *  Note: This only accounts for data on the group object itself.
+ *  You need to use add and remove to manipulate group membership.
+ */
+Usergrid.Counter.prototype = new Usergrid.Entity();
+
+/*
+ * overrides Entity.prototype.fetch. Returns all data for counters
+ * associated with the object as specified in the constructor
+ *
+ * @public
+ * @method increment
+ * @param {function} callback
+ * @returns {callback} callback(err, event)
+ */
+Usergrid.Counter.prototype.fetch=function(callback){
+  this.getData({}, callback);
+}
+/*
+ * increments the counter for a specific event
+ *
+ * options object: {name: counter_name}
+ *
+ * @public
+ * @method increment
+ * @params {object} options
+ * @param {function} callback
+ * @returns {callback} callback(err, event)
+ */
+Usergrid.Counter.prototype.increment=function(options, callback){
+  var self=this,
+    name=options.name,
+    value=options.value;
+  if(!name){
+    if(typeof(callback) === 'function') {
+      return callback.call(self, true, "'value' for increment, decrement must be a number");
+    }
+  }else if(isNaN(value)){
+    if(typeof(callback) === 'function') {
+      return callback.call(self, true, "'value' for increment, decrement must be a number");
+    }
+  }else{
+    self._data.counters[name]=(parseInt(value))||1;
+    return self.save(callback);
+  }
+};
+/*
+ * decrements the counter for a specific event
+ *
+ * options object: {name: counter_name}
+ *
+ * @public
+ * @method decrement
+ * @params {object} options
+ * @param {function} callback
+ * @returns {callback} callback(err, event)
+ */
+
+Usergrid.Counter.prototype.decrement=function(options, callback){
+  var self=this,
+    name=options.name,
+    value=options.value;
+  self.increment({name:name, value:-((parseInt(value))||1)}, callback);
+};
+/*
+ * resets the counter for a specific event
+ *
+ * options object: {name: counter_name}
+ *
+ * @public
+ * @method reset
+ * @params {object} options
+ * @param {function} callback
+ * @returns {callback} callback(err, event)
+ */
+
+Usergrid.Counter.prototype.reset=function(options, callback){
+  var self=this,
+    name=options.name;
+  self.increment({name:name, value:0}, callback);
+};
+
+/*
+ * gets data for one or more counters over a given
+ * time period at a specified resolution
+ *
+ * options object: {
+ *                   counters: ['counter1', 'counter2', ...],
+ *                   start: epoch timestamp or ISO date string,
+ *                   end: epoch timestamp or ISO date string,
+ *                   resolution: one of ('all', 'minute', 'five_minutes', 'half_hour', 'hour', 'six_day', 'day', 'week', or 'month')
+ *                   }
+ *
+ * @public
+ * @method getData
+ * @params {object} options
+ * @param {function} callback
+ * @returns {callback} callback(err, event)
+ */
+Usergrid.Counter.prototype.getData=function(options, callback){
+  var start_time,
+      end_time,
+      start=options.start||0,
+      end=options.end||Date.now(),
+      resolution=(options.resolution||'all').toLowerCase(),
+      counters=options.counters||Object.keys(this._data.counters),
+      res=(resolution||'all').toLowerCase();
+  if(COUNTER_RESOLUTIONS.indexOf(res)===-1){
+    res='all';
+  }
+  if(start){
+    switch(typeof start){
+      case "undefined":
+        start_time=0;
+        break;
+      case "number":
+        start_time=start;
+        break;
+      case "string":
+        start_time=(isNaN(start))?Date.parse(start):parseInt(start);
+        break;
+      default:
+        start_time=Date.parse(start.toString());
+    }
+  }
+  if(end){
+    switch(typeof end){
+      case "undefined":
+        end_time=Date.now();
+        break;
+      case "number":
+        end_time=end;
+        break;
+      case "string":
+        end_time=(isNaN(end))?Date.parse(end):parseInt(end);
+        break;
+      default:
+        end_time=Date.parse(end.toString());
+    }
+  }
+  var self=this;
+  //https://api.usergrid.com/yourorgname/sandbox/counters?counter=test_counter
+  var params=Object.keys(counters).map(function(counter){
+      return ["counter", encodeURIComponent(counters[counter])].join('=');
+    });
+  params.push('resolution='+res)
+  params.push('start_time='+String(start_time))
+  params.push('end_time='+String(end_time))
+
+  var endpoint="counters?"+params.join('&');
+  this._client.request({endpoint:endpoint}, function(err, data){
+    if(data.counters && data.counters.length){
+      data.counters.forEach(function(counter){
+        self._data.counters[counter.name]=counter.value||counter.values;
+      })
+    }
+    if(typeof(callback) === 'function') {
+      callback.call(self, err, data);
+    }
+  })
+};
+
+exports.client = Usergrid.Client;
+exports.entity = Usergrid.Entity;
+exports.collection = Usergrid.Collection;
+exports.group = Usergrid.Group;
+exports.counter = Usergrid.Counter;
+exports.AUTH_CLIENT_ID = AUTH_CLIENT_ID;
+exports.AUTH_APP_USER = AUTH_APP_USER;
+exports.AUTH_NONE = AUTH_NONE;
