Account Verification

Currently, I have an API where creating an account is a two-step process. Step one is a POST /account with a body like request body this:

{
  "data": {
    "type": "account",
    "attributes": {
      "email": "user@example.com",
      "username": "user",
      "password": "password"
    }
  }
}

And a response (201 Created) that includes the created account:

{
  "data": {
    "id": "66dd2d33-881a-462f-86e5-474183fef133",
    "type": "account",
    "attributes": {
      "avatar_url": "https://example.com/avatar.png",
      "email": "user@example.com",
      "username": "user",
      "verified_at": null,
      "created_at": "20160714T22:23:06.839252Z",
      "updated_at": "20160714T22:23:06.839252Z"
    },
    "links": {
      "self": "https://api.example.com/account"
    },
    "relationships": {
      "personal_org": {
        "data": {
          "id": "3386bf85-2b91-4699-be8a-70106d019016",
          "type": "orgs"
        }
      }
    }
  }
}

The account is now created, but it’s not really usable. We send an email to the user with a link to our web app that includes a token used for account verification purposes. The web app then makes an API call with this token in order to verify the account.

Right now, this is what the request for verification looks like but I know it’s not 100% compliant (at least in part because of a missing id, which the client does not have at this point):

POST /account/actions/verify

{
  "data": {
    "type": "account",
    "attributes": {
      "verification_token": "token"
    }
  }
}

Basically it’s an action that indicates that the account with that verification token can now be verified. Doing PATCH /account feels wrong, because we’re not changing the verification token. It already exists. The net change is actually just that verified_at is set (but obviously I’m not trusting the client to set this value).

In general, I’m having trouble with these sort of “action” endpoints in JSON API. I also need them for things like cloning resources and verifying password resets (works similar to account verification).

I suppose an alternative would be:

POST /account/actions/verify

{
  "meta": {
    "verification_token": "token"
  }
}

But cramming stuff in “meta” seems like JSON API code smell. A little insight/help would be appreciated. In general, this sort of thing is making me lean towards an API based on JSON API, but not actually implementing JSON API perfectly. Another example is that we have editable documents that I can prepend or append data to, so it really doesn’t make sense to be PATCH, because we’re not updating all of content. POST /documents/{id}/actions/append makes sense, but I can’t find a JSON API-compliant way to implement this without just cramming stuff in “meta”.

I would make a resource type called “account-validations”. A client can POST /account-validations with the proper key and this will enable the account.