diff --git a/browserid/lib/db_json.js b/browserid/lib/db_json.js
index 89cc299fec1cd2a95668976ec4c42916e34cdc4a..3bfa8991b9eeb67894d6be4f03fa2545c650c64a 100644
--- a/browserid/lib/db_json.js
+++ b/browserid/lib/db_json.js
@@ -196,7 +196,7 @@ exports.gotVerificationSecret = function(secret, hash, cb) {
           emails: [ o.email ]
         });
         flush();
-        cb();
+        cb(undefined, o.email);
       }
 
       // if this email address is known and a user has completed a re-verification of this email
diff --git a/browserid/lib/db_mysql.js b/browserid/lib/db_mysql.js
index 4f1264ce27a9f07d3ebddbc32a2137c2d81037d4..3700a7f4dc2006790516375a39132ea453d76607 100644
--- a/browserid/lib/db_mysql.js
+++ b/browserid/lib/db_mysql.js
@@ -199,7 +199,7 @@ exports.stageUser = function(email, cb) {
 
 exports.haveVerificationSecret = function(secret, cb) {
   client.query(
-    "SELECT COUNT(*) as N FROM staged WHERE secret = ?", [ email ],
+    "SELECT COUNT(*) as N FROM staged WHERE secret = ?", [ secret ],
     function(err, rows) {
       if (err) logUnexpectedError(err);
       cb(rows && rows.length > 0 && rows[0].N > 0);
@@ -235,7 +235,7 @@ exports.gotVerificationSecret = function(secret, hash, cb) {
                   [ userID, o.email ],
                   function(err, info) {
                     if (err) logUnexpectedError(err);
-                    cb(err ? err : undefined);
+                    cb(err ? err : undefined, o.email);
                   });
               }
             });
diff --git a/browserid/lib/wsapi.js b/browserid/lib/wsapi.js
index f26ea4822e0664e21a89e6337348877d79abffce..3a9ba0edc841ffddf80074541a61fd133ad215b1 100644
--- a/browserid/lib/wsapi.js
+++ b/browserid/lib/wsapi.js
@@ -72,7 +72,7 @@ function checkParams(params) {
 }
 
 function isAuthed(req) {
-  var result= (req.session && typeof req.session.authenticatedUser === 'string');
+  var result = (req.session && typeof req.session.authenticatedUser === 'string');
   return result;
 }
 
@@ -129,107 +129,180 @@ function setup(app) {
    * user via their claimed email address.  Upon timeout expiry OR clickthrough
    * the staged user account transitions to a valid user account
    */
-  app.post('/wsapi/stage_user', checkParams([ "email", "pass", "site" ]), function(req, resp) {
+  app.post('/wsapi/stage_user', checkParams([ "email", "site" ]), function(req, resp) {
+    // staging a user logs you out.
+    clearAuthenticatedUser(req.session);
+
+    try {
+      // upon success, stage_user returns a secret (that'll get baked into a url
+      // and given to the user), on failure it throws
+      db.stageUser(req.body.email, function(secret) {
+        // store the email being registered in the session data
+        if (!req.session) req.session = {};
+
+        // store the secret we're sending via email in the users session, as checking
+        // that it still exists in the database is the surest way to determine the
+        // status of the email verification.
+        req.session.pendingCreation = secret;
+
+        resp.json(true);
+
+        // let's now kick out a verification email!
+        email.sendVerificationEmail(req.body.email, req.body.site, secret);
+      });
+    } catch(e) {
+      // we should differentiate tween' 400 and 500 here.
+      httputils.badRequest(resp, e.toString());
+    }
+  });
 
-    // we should be cloning this object here.
-    var stageParams = req.body;
+  app.get('/wsapi/user_creation_status', function(req, resp) {
+    var email = req.query.email;
+    if (typeof email !== 'string') {
+      logger.warn("user_creation_status called without 'email' parameter");
+      httputils.badRequest(resp, "no 'email' parameter");
+      return;
+    }
+
+    // if the user is authenticated as the user in question, we're done
+    if (isAuthed(req) && req.session.authenticatedUser === email) {
+      return resp.json('complete');
+    }
+    // if the user isn't authenticated and there's no pendingCreation token,
+    // then they must authenticate
+    else if (!req.session.pendingCreation) {
+      return resp.json('mustAuth');
+    }
+
+    // if the secret is still in the database, it hasn't yet been verified and
+    // verification is still pending
+    db.haveVerificationSecret(req.session.pendingCreation, function (haveSecret) {
+      if (haveSecret) return resp.json('pending');
+      // if the secret isn't known, and we're not authenticated, then the user must authenticate
+      // (maybe they verified the URL on a different browser, or maybe they canceled the account
+      // creation)
+      else {
+        delete req.session.pendingCreation;
+        resp.json('mustAuth');
+      }
+    });
+  });
 
+  app.post('/wsapi/complete_user_creation', checkParams(["token", "pass"]), function(req, resp) {
     // issue #155, valid password length is between 8 and 80 chars.
-    if (stageParams.pass.length < 8 || stageParams.pass.length > 80) {
+    if (req.body.pass.length < 8 || req.body.pass.length > 80) {
       httputils.badRequest(resp, "valid passwords are between 8 and 80 chars");
       return;
     }
 
-    // bcrypt the password
-    bcrypt.gen_salt(10, function (err, salt) {
-      if (err) {
-        winston.error("error generating salt with bcrypt: " + err);
-        return resp.json(false);
-      }
+    // at the time the email verification is performed, we'll clear the pendingCreation
+    // data on the session.
+    delete req.session.pendingCreation;
+
+    // We should check to see if the verification secret is valid *before*
+    // bcrypting the password (which is expensive), to prevent a possible
+    // DoS attack.
+    db.haveVerificationSecret(req.body.token, function(valid) {
+      if (!valid) return resp.json(false);
 
-      bcrypt.encrypt(stageParams.pass, salt, function(err, hash) {
+      // now bcrypt the password
+      bcrypt.gen_salt(10, function (err, salt) {
         if (err) {
-          winston.error("error generating password hash with bcrypt: " + err);
+          logger.error("error generating salt with bcrypt: " + err);
           return resp.json(false);
         }
-
-        stageParams['hash'] = hash;
-
-        try {
-          // upon success, stage_user returns a secret (that'll get baked into a url
-          // and given to the user), on failure it throws
-          db.stageUser(stageParams, function(secret) {
-            // store the email being registered in the session data
-            if (!req.session) req.session = {};
-
-            // store inside the session the details of this pending verification
-            req.session.pendingVerification = {
-              email: stageParams.email,
-              hash: stageParams.hash // we must store both email and password to handle the case where
-              // a user re-creates an account - specifically, registration status
-              // must ensure the new credentials work to properly verify that
-              // the user has clicked throught the email link. note, this salted, bcrypted
-              // representation of a user's password will get thrust into an encrypted cookie
-              // served over an encrypted (SSL) session.  guten, yah.
-            };
-
-            resp.json(true);
-
-            // let's now kick out a verification email!
-            email.sendVerificationEmail(stageParams.email, stageParams.site, secret);
+        bcrypt.encrypt(req.body.pass, salt, function(err, hash) {
+          if (err) {
+            logger.error("error generating password hash with bcrypt: " + err);
+            return resp.json(false);
+          }
+
+          db.gotVerificationSecret(req.body.token, hash, function(err, email) {
+            if (err) {
+              logger.error("error completing the verification: " + err);
+              resp.json(false);
+            } else {
+              // at this point the user has set a password associated with an email address
+              // that they've verified.  We create an authenticated session.
+              req.session.authenticatedUser = email;
+              resp.json(true);
+            }
           });
-        } catch(e) {
-          // we should differentiate tween' 400 and 500 here.
-          httputils.badRequest(resp, e.toString());
-        }
+        });
       });
     });
   });
 
-  app.get('/wsapi/registration_status', function(req, resp) {
-    if (!req.session ||
-        (!(typeof req.session.pendingVerification === 'object') &&
-         !(typeof req.session.pendingAddition === 'string')))
+  app.post('/wsapi/stage_email', checkAuthed, checkParams(["email", "site"]), function (req, resp) {
+    try {
+      // on failure stageEmail may throw
+      db.stageEmail(req.session.authenticatedUser, req.body.email, function(secret) {
+
+        // store the email being added in session data
+        req.session.pendingAddition = secret;
+
+        resp.json(true);
+
+        // let's now kick out a verification email!
+        email.sendVerificationEmail(req.body.email, req.body.site, secret);
+      });
+    } catch(e) {
+      // we should differentiate tween' 400 and 500 here.
+      httputils.badRequest(resp, e.toString());
+    }
+  });
+
+
+  app.get('/wsapi/email_addition_status', function(req, resp) {
+
+    var email = req.query.email;
+    if (typeof email !== 'string')
     {
-      httputils.badRequest(resp, "api abuse: registration_status called without a pending email addition/verification");
+      logger.warn("email_addition_status called without an 'email' parameter");
+      httputils.badRequest(resp, "missing 'email' parameter");
       return;
     }
 
-    // Is the current session trying to add an email, or register a new one?
-    if (req.session.pendingAddition) {
-      // this is a pending email addition, it requires authentication
-      if (!isAuthed(req, resp)) {
-        return httputils.badRequest(resp, "requires authentication");
-      }
+    // this is a pending email addition, it requires authentication
+    if (!isAuthed(req, resp)) {
+      delete req.session.pendingAddition;
+      return httputils.badRequest(resp, "requires authentication");
+    }
 
-      // check if the currently authenticated user has the email stored under pendingAddition
-      // in their acct.
-      db.emailsBelongToSameAccount(req.session.pendingAddition,
-                                   req.session.authenticatedUser,
-                                   function(registered) {
-                                     if (registered) {
-                                       delete req.session.pendingAddition;
-                                       resp.json('complete');
-                                     } else {
-                                       resp.json('pending');
-                                     }
-                                   });
-    } else {
-      // this is a pending registration, let's check if the creds stored on the
-      // session are good yet.
-      var v = req.session.pendingVerification;
-      db.checkAuth(v.email, function(hash) {
-        if (hash === v.hash) {
-          delete req.session.pendingVerification;
-          req.session.authenticatedUser = v.email;
+    // check if the currently authenticated user has the email stored under pendingAddition
+    // in their acct.
+    db.emailsBelongToSameAccount(
+      email,
+      req.session.authenticatedUser,
+      function(registered) {
+        if (registered) {
+          delete req.session.pendingAddition;
           resp.json('complete');
+        } else if (!req.session.pendingAddition) {
+          resp.json('failed');
         } else {
-          resp.json('pending');
+          db.haveVerificationSecret(req.session.pendingAddition, function (haveSecret) {
+            if (haveSecret) {
+              return resp.json('pending');
+            } else {
+              delete req.session.pendingAddition;
+              resp.json('failed');
+            }
+          });
         }
       });
-    }
   });
 
+  app.post('/wsapi/complete_email_addition', checkParams(["token"]), function(req, resp) {
+    db.gotVerificationSecret(req.body.token, undefined, function(e) {
+      if (e) {
+        logger.error("error completing the verification: " + e);
+        resp.json(false);
+      } else {
+        resp.json(true);
+      }
+    });
+  });
 
   app.post('/wsapi/authenticate_user', checkParams(["email", "pass"]), function(req, resp) {
     db.checkAuth(req.body.email, function(hash) {
@@ -241,7 +314,7 @@ function setup(app) {
 
       bcrypt.compare(req.body.pass, hash, function (err, success) {
         if (err) {
-          winston.warn("error comparing passwords with bcrypt: " + err);
+          logger.warn("error comparing passwords with bcrypt: " + err);
           success = false;
         }
         if (success) {
@@ -253,25 +326,6 @@ function setup(app) {
     });
   });
 
-  app.post('/wsapi/add_email', checkAuthed, checkParams(["email", "site"]), function (req, resp) {
-    try {
-      // on failure stageEmail may throw
-      db.stageEmail(req.session.authenticatedUser, req.body.email, function(secret) {
-
-        // store the email being added in session data
-        req.session.pendingAddition = req.body.email;
-
-        resp.json(true);
-
-        // let's now kick out a verification email!
-        email.sendVerificationEmail(req.body.email, req.body.site, secret);
-      });
-    } catch(e) {
-      // we should differentiate tween' 400 and 500 here.
-      httputils.badRequest(resp, e.toString());
-    }
-  });
-
   app.post('/wsapi/remove_email', checkAuthed, checkParams(["email"]), function(req, resp) {
     var email = req.body.email;
 
@@ -307,7 +361,7 @@ function setup(app) {
       var expiration = new Date();
       expiration.setTime(new Date().valueOf() + (24*3600*1000));
       var cert = ca.certify(req.body.email, pk, expiration);
-      
+
       resp.writeHead(200, {'Content-Type': 'text/plain'});
       resp.write(cert);
       resp.end();
@@ -353,17 +407,6 @@ function setup(app) {
     });
   });
 
-  app.get('/wsapi/prove_email_ownership', checkParams(["token"]), function(req, resp) {
-    db.gotVerificationSecret(req.query.token, function(e) {
-      if (e) {
-        logger.error("error completing the verification: " + e);
-        resp.json(false);
-      } else {
-        resp.json(true);
-      }
-    });
-  });
-
   // if the BROWSERID_FAKE_VERIFICATION env var is defined, we'll include
   // fake_verification.js.  This is used during testing only and should
   // never be included in a production deployment
diff --git a/browserid/tests/ca-test.js b/browserid/tests/ca-test.js
index 58841957aec1115a1c305b9ac466caf5fef61523..2dfd984ee4120a048df26965b0b3537c76941316 100755
--- a/browserid/tests/ca-test.js
+++ b/browserid/tests/ca-test.js
@@ -57,7 +57,7 @@ var kp = jwk.KeyPair.generate("RS",64);
 
 var email_addr = "foo@foo.com";
 
-// create a new account via the api with (first address)
+// certify a key
 suite.addBatch({
   "certify a public key": {
     topic: function() {
diff --git a/browserid/tests/cert-emails-test.js b/browserid/tests/cert-emails-test.js
index ad6feeef65d7caae5f786af39501fdf4ea25aca9..afdf9a5d069ee08c1010e9267a6271861a4f7f13 100755
--- a/browserid/tests/cert-emails-test.js
+++ b/browserid/tests/cert-emails-test.js
@@ -68,7 +68,6 @@ suite.addBatch({
   "stage an account": {
     topic: wsapi.post('/wsapi/stage_user', {
       email: 'syncer@somehost.com',
-      pass: 'fakepass',
       pubkey: 'fakekey',
       site:'fakesite.com'
     }),
@@ -81,7 +80,7 @@ suite.addBatch({
 suite.addBatch({
   "verifying account ownership": {
     topic: function() {
-      wsapi.get('/wsapi/prove_email_ownership', { token: token }).call(this);
+      wsapi.post('/wsapi/complete_user_creation', { token: token, pass: 'fakepass' }).call(this);
     },
     "works": function(r, err) {
       assert.equal(r.code, 200);
@@ -90,18 +89,6 @@ suite.addBatch({
   }
 });
 
-suite.addBatch({
-  "calling registration_status after a registration is complete": {
-    topic: wsapi.get("/wsapi/registration_status"),
-    "yields a HTTP 200": function (r, err) {
-      assert.strictEqual(r.code, 200);
-    },
-    "returns a json encoded string - `complete`": function (r, err) {
-      assert.strictEqual(JSON.parse(r.body), "complete");
-    }
-  }
-});
-
 var cert_key_url = "/wsapi/cert_key";
 
 // generate a keypair, we'll use this to sign assertions, as if
diff --git a/browserid/tests/forgotten-email-test.js b/browserid/tests/forgotten-email-test.js
index a93608a45aebc3f127320d57f68e5ae790062320..13da60e37e146986010e9c7407ccd0a4c7ad59a8 100755
--- a/browserid/tests/forgotten-email-test.js
+++ b/browserid/tests/forgotten-email-test.js
@@ -60,8 +60,6 @@ suite.addBatch({
   "stage first account": {
     topic: wsapi.post('/wsapi/stage_user', {
       email: 'first@fakeemail.com',
-      pass: 'firstfakepass',
-      pubkey: 'fakepubkey',
       site:'fakesite.com'
     }),
     "the token is sane": function(r, err) {
@@ -73,7 +71,7 @@ suite.addBatch({
 suite.addBatch({
   "create first account": {
     topic: function() {
-      wsapi.get('/wsapi/prove_email_ownership', { token: token }).call(this);
+      wsapi.post('/wsapi/complete_user_creation', { token: token, pass: 'firstfakepass' }).call(this);
     },
     "account created": function(r, err) {
       assert.equal(r.code, 200);
@@ -84,7 +82,7 @@ suite.addBatch({
 
 suite.addBatch({
   "email created": {
-    topic: wsapi.get('/wsapi/registration_status'),
+    topic: wsapi.get('/wsapi/user_creation_status', { email: 'first@fakeemail.com' } ),
     "should exist": function(r, err) {
       assert.strictEqual(r.code, 200);
       assert.strictEqual(JSON.parse(r.body), "complete");
@@ -95,7 +93,7 @@ suite.addBatch({
 // add a new email address to the account (second address)
 suite.addBatch({
   "add a new email address to our account": {
-    topic: wsapi.post('/wsapi/add_email', {
+    topic: wsapi.post('/wsapi/stage_email', {
       email: 'second@fakeemail.com',
       site:'fakesite.com'
     }),
@@ -109,7 +107,7 @@ suite.addBatch({
 suite.addBatch({
   "create second account": {
     topic: function() {
-      wsapi.get('/wsapi/prove_email_ownership', { token: token }).call(this);
+      wsapi.post('/wsapi/complete_email_addition', { token: token }).call(this);
     },
     "account created": function(r, err) {
       assert.equal(r.code, 200);
@@ -146,8 +144,6 @@ suite.addBatch({
   "re-stage first account": {
     topic: wsapi.post('/wsapi/stage_user', {
       email: 'first@fakeemail.com',
-      pass: 'secondfakepass',
-      pubkey: 'fakepubkey2',
       site:'otherfakesite.com'
     }),
     "the token is sane": function(r, err) {
@@ -177,7 +173,7 @@ suite.addBatch({
 suite.addBatch({
   "re-create first email address": {
     topic: function() {
-      wsapi.get('/wsapi/prove_email_ownership', { token: token }).call(this);
+      wsapi.post('/wsapi/complete_user_creation', { token: token, pass: 'secondfakepass' }).call(this);
     },
     "account created": function(r, err) {
       assert.equal(r.code, 200);
diff --git a/browserid/tests/list-emails-wsapi-test.js b/browserid/tests/list-emails-wsapi-test.js
index e243445b070d6a0cfcb7106c58f0154362c3e564..a995323183bdc582d5d1edd3d075a63218f3aa37 100755
--- a/browserid/tests/list-emails-wsapi-test.js
+++ b/browserid/tests/list-emails-wsapi-test.js
@@ -60,7 +60,6 @@ suite.addBatch({
   "stage an account": {
     topic: wsapi.post('/wsapi/stage_user', {
       email: 'syncer@somehost.com',
-      pass: 'fakepass',
       site:'fakesite.com'
     }),
     "yields a sane token": function(r, err) {
@@ -72,18 +71,18 @@ suite.addBatch({
 suite.addBatch({
   "verifying account ownership": {
     topic: function() {
-      wsapi.get('/wsapi/prove_email_ownership', { token: token }).call(this);
+      wsapi.post('/wsapi/complete_user_creation', { token: token, pass: 'fakepass' }).call(this);
     },
     "works": function(r, err) {
       assert.equal(r.code, 200);
-      assert.strictEqual(true, JSON.parse(r.body));
+      assert.strictEqual(JSON.parse(r.body), true);
     }
   }
 });
 
 suite.addBatch({
-  "calling registration_status after a registration is complete": {
-    topic: wsapi.get("/wsapi/registration_status"),
+  "calling user_creation_status after a creation is complete": {
+    topic: wsapi.get("/wsapi/user_creation_status", { email: 'syncer@somehost.com' }),
     "yields a HTTP 200": function (r, err) {
       assert.strictEqual(r.code, 200);
     },
@@ -107,7 +106,6 @@ suite.addBatch({
   }
 });
 
-
 start_stop.addShutdownBatches(suite);
 
 // run or export the suite.
diff --git a/browserid/tests/password-length-test.js b/browserid/tests/password-length-test.js
index c6da2d8a97fcf8190e86d2e27563909d42becb78..478e572a5a98d652817df8a0665239c0a0eefe47 100755
--- a/browserid/tests/password-length-test.js
+++ b/browserid/tests/password-length-test.js
@@ -52,7 +52,8 @@ suite.options.error = false;
 start_stop.addStartupBatches(suite);
 
 // surpress console output of emails with a noop email interceptor
-email.setInterceptor(function(email, site, secret) { });
+var token = undefined;
+email.setInterceptor(function(email, site, secret) { token = secret; });
 
 suite.addBatch({
   "get csrf token": {
@@ -63,38 +64,47 @@ suite.addBatch({
   }
 });
 
-// create a new account via the api with (first address)
+// first stage the account
 suite.addBatch({
-  "a password that is too short": {
+  "account staging": {
     topic: wsapi.post('/wsapi/stage_user', {
       email: 'first@fakeemail.com',
-      pass: '0123456', // less than 8 chars, invalid
-      pubkey: 'fakepubkey',
       site:'fakesite.com'
     }),
+    "works":     function(r, err) {
+      assert.equal(r.code, 200);
+    }
+  }
+})
+
+// create a new account via the api with (first address)
+suite.addBatch({
+  "a password that is too short": {
+    topic: wsapi.post('/wsapi/complete_user_creation', {
+      token: token,
+      pass: '0123456' // less than 8 chars, invalid
+    }),
     "causes a HTTP error response": function(r, err) {
       assert.equal(r.code, 400);
+      assert.equal(r.body, "Bad Request: valid passwords are between 8 and 80 chars");
     }
   },
   "a password that is too long": {
-    topic: wsapi.post('/wsapi/stage_user', {
-      email: 'second@fakeemail.com',
+    topic: wsapi.post('/wsapi/complete_user_creation', {
+      token: token,
       pass: '012345678901234567890123456789012345678901234567890123456789012345678901234567891', // more than 81 chars, invalid.
-      pubkey: 'fakepubkey',
-      site:'fakesite.com'
     }),
     "causes a HTTP error response": function(r, err) {
       assert.equal(r.code, 400);
+      assert.equal(r.body, "Bad Request: valid passwords are between 8 and 80 chars");
     }
   },
   "but a password that is just right": {
-    topic: wsapi.post('/wsapi/stage_user', {
-      email: 'third@fakeemail.com',
-      pass: 'ahhh.  this is just right.', // valid.
-      pubkey: 'fakepubkey',
-      site:'fakesite.com'
+    topic: wsapi.post('/wsapi/complete_user_creation', {
+      token: token,
+      pass: 'ahhh.  this is just right.'
     }),
-    "causes a HTTP error response": function(r, err) {
+    "works just fine": function(r, err) {
       assert.equal(r.code, 200);
     }
   }
diff --git a/browserid/tests/registration-status-wsapi-test.js b/browserid/tests/registration-status-wsapi-test.js
index 54d6a4b3ee000723c8b78bf7319bce6a1a7813ae..a250d1aba8c10616ce122589aba610484aeff0a1 100755
--- a/browserid/tests/registration-status-wsapi-test.js
+++ b/browserid/tests/registration-status-wsapi-test.js
@@ -59,7 +59,7 @@ start_stop.addStartupBatches(suite);
 
 suite.addBatch({
   "calling registration_status without a pending reg is an error": {
-    topic: wsapi.get("/wsapi/registration_status"),
+    topic: wsapi.get("/wsapi/user_creation_status"),
     "HTTP 400": function (r, err) {
       assert.equal(400, r.code);
     }
@@ -80,8 +80,6 @@ suite.addBatch({
   "start registration": {
     topic: wsapi.post('/wsapi/stage_user', {
       email: 'first@fakeemail.com',
-      pass: 'firstfakepass',
-      pubkey: 'fakepubkey',
       site:'fakesite.com'
     }),
     "the token is sane": function(r, err) {
@@ -91,8 +89,20 @@ suite.addBatch({
 });
 
 suite.addBatch({
-  "calling registration_status when a reg is really pending": {
-    topic: wsapi.get("/wsapi/registration_status"),
+  "calling user_creation_status without an email argument": {
+    topic: wsapi.get("/wsapi/user_creation_status"),
+    "yields a HTTP 400": function (r, err) {
+      assert.strictEqual(r.code, 400);
+    },
+    "returns an error string": function (r, err) {
+      assert.strictEqual(r.body, "Bad Request: no 'email' parameter");
+    }
+  }
+});
+
+suite.addBatch({
+  "calling user_creation_status when a reg is really pending": {
+    topic: wsapi.get("/wsapi/user_creation_status", { email: 'first@fakeemail.com' }),
     "yields a HTTP 200": function (r, err) {
       assert.strictEqual(r.code, 200);
     },
@@ -103,19 +113,19 @@ suite.addBatch({
 });
 
 suite.addBatch({
-  "proving email ownership causes account creation": {
+  "completing user creation": {
     topic: function() {
-      wsapi.get('/wsapi/prove_email_ownership', { token: token }).call(this);
+      wsapi.post('/wsapi/complete_user_creation', { token: token, pass: 'firstfakepass' }).call(this);
     },
-    "and returns a 200 code": function(r, err) {
+    "works": function(r, err) {
       assert.equal(r.code, 200);
     }
   }
 });
 
 suite.addBatch({
-  "calling registration_status after a registration is complete": {
-    topic: wsapi.get("/wsapi/registration_status"),
+  "calling user_creation_status after a registration is complete": {
+    topic: wsapi.get("/wsapi/user_creation_status", { email: 'first@fakeemail.com' }),
     "yields a HTTP 200": function (r, err) {
       assert.strictEqual(r.code, 200);
     },
@@ -127,9 +137,12 @@ suite.addBatch({
 
 suite.addBatch({
   "calling registration_status a second time after a registration is complete": {
-    topic: wsapi.get("/wsapi/registration_status"),
-    "yields a HTTP 400, it's meaningless": function (r, err) {
-      assert.strictEqual(r.code, 400);
+    topic: wsapi.get("/wsapi/user_creation_status", { email: 'first@fakeemail.com' }),
+    "still yields a HTTP 200": function (r, err) {
+      assert.strictEqual(r.code, 200);
+    },
+    "and still returns a json encoded string - `complete`": function (r, err) {
+      assert.strictEqual(JSON.parse(r.body), "complete");
     }
   }
 });
@@ -161,8 +174,6 @@ suite.addBatch({
   "re-registering an existing email": {
     topic: wsapi.post('/wsapi/stage_user', {
       email: 'first@fakeemail.com',
-      pass: 'secondfakepass',
-      pubkey: 'secondfakepubkey',
       site:'secondfakesite.com'
     }),
     "yields a valid token": function(r, err) {
@@ -173,7 +184,7 @@ suite.addBatch({
 
 suite.addBatch({
   "calling registration_status when a reg is pending for an email that is already verified": {
-    topic: wsapi.get("/wsapi/registration_status"),
+    topic: wsapi.get("/wsapi/user_creation_status", { email: 'first@fakeemail.com' }),
     "should yield a HTTP 200": function (r, err) {
       assert.strictEqual(r.code, 200);
     },
@@ -184,9 +195,9 @@ suite.addBatch({
 });
 
 suite.addBatch({
-  "proving email ownership causes account creation": {
+  "proving email ownership causes account re-creation": {
     topic: function() {
-      wsapi.get('/wsapi/prove_email_ownership', { token: token }).call(this);
+      wsapi.post('/wsapi/complete_user_creation', { token: token, pass: 'secondfakepass' }).call(this);
     },
     "and returns a 200 code": function(r, err) {
       assert.equal(r.code, 200);
@@ -196,7 +207,7 @@ suite.addBatch({
 
 suite.addBatch({
   "calling registration_status after proving a re-registration": {
-    topic: wsapi.get("/wsapi/registration_status"),
+    topic: wsapi.get("/wsapi/user_creation_status", { email: 'first@fakeemail.com' }),
     "yields a HTTP 200": function (r, err) {
       assert.strictEqual(r.code, 200);
     },
@@ -208,9 +219,9 @@ suite.addBatch({
 
 suite.addBatch({
   "again, calling registration_status a second time after a registration is complete": {
-    topic: wsapi.get("/wsapi/registration_status"),
-    "yields a HTTP 400, it's meaningless": function (r, err) {
-      assert.strictEqual(r.code, 400);
+    topic: wsapi.get("/wsapi/user_creation_status", { email: 'first@fakeemail.com' }),
+    "yields a HTTP 200": function (r, err) {
+      assert.strictEqual(r.code, 200);
     }
   }
 });