3

We need to have an endpoint that allows us to check if a user's email is unique. This operation doesn't seem incredibly RESTful and we're struggling to figure out how to make it fit. We've been debating on whether we should make this more of an RPC style endpoint that might look like the following:

URL

GET identities/check_email

Response

{
  "ok": false,
  "error": "taken"
}

The rub being this doesn't fit incredibly well with everything else we're doing.

We've also considered sending a HEAD request but we're not quite sure what that would look like.

  • I usually use something like GET: email/verification, returning 200 when the verification passes, 409 on conflict, 400 on malformed input and 500 for any other error. – Andy Apr 14 '17 at 5:02
  • 1
    This question may help you stackoverflow.com/q/11676550/5934037. I wonder if you are sending the mail through the URL or in the request body. The second seems to me a little bit unatural. – Laiv Apr 14 '17 at 7:01
5

Use the HEAD verb. If GET /identities/joe@example.com would return either 200 Okay with JSON about Joe or 404 Not Found, then HEAD /identities/joe@example.com acts the same as GET but only returns the headers and status code. You can use HEAD as an "existence check" for an arbitrary resource (presuming the server hosting the resource properly understands the HEAD verb).

This presumes individual users are resources and are identifiable by email. If you currently only support identifying user by IDs such as /identities/123, you could add an /identities/emails/{email} route which either returns 404 Not Found or redirects to the matching user's URL.

1

The first two rules of REST are that everything is a resource and the only verbs you should be thinking about are the ones that HTTP specifies.

I'll go out on a limb and assume that you have a model where access to identities starts at /identities and that you can pull one out by ID with GET /identities/1234. I'm also going to assume that your API outputs JSON and the http://host/ at the beginning of any URIs is implied for brevity's sake.

Theoretically, you could GET /identities and get back an array containing references to every identity in the system:

[ "/identities/1234", "/identities/5678", "/identities/9012", ... ]

That's probably not what you want, but you can allow it in small doses using query strings to limit the list to a subset. GET /identities?email=bob@example.com would be an ideal filter for checking whether an email address exists because your business rules say they have to be unique. That means the returned array would always be zero or one elements:

GET /identities?email=bob@example.com
[ "identities/1234" ]

GET /identities?email=doug@example.com
[]

Another way to go about this is to build the filtering into the model, where there are multiple paths to the same resource:

/identities/by-id/1234
/identities/by-email/bob@example.com

Trying to retrieve the second resource would return 200 if an identifier with an email address of bob@example.com existed and 404 if it didn't. While having multiple paths to the same resource is considered acceptable in REST interfaces, you'll need to consider whether that presents any logical problems like not knowing if two non-identical URIs point to the same resource.

  • 1
    Are not your last 2 options kinda Uri tunneling approach? The by-<thing> is nothing different than /identities/filtered-by-<field>/... Which is not too RESTFUL compliant. These two URIs seems remote commands calls rather than resources identifiers. – Laiv Apr 15 '17 at 16:29
  • Allowing a way to retrieve yours system emails is not also a hole of security? – Laiv Apr 15 '17 at 16:33
  • @Laiv It's not tunneling because both paths refer to a single resource and still fit the meaning of one of the REST verbs. (Filtering in that context might be further up the tree, something like /identities/by-email?filter=....) Whether or not the query-by-email model is a security hole isn't really relevant, as the OP has a requirement that his API be able to do that. There are ways to keep the API from disclosing things it shouldn't that don't really have any bearing on how the data is modeled. – Blrfl Apr 15 '17 at 18:45
  • The requirement is to check whether and email exist or not... Not to retrieve emails as "KO" response or an empty array as "successful" response. The approach ,IMO, lacks on consistency. I think, in this case an RPC-like services will do the job. I'm having a hard time trying to look at the validation as a resource instead of a Command. On another hand, mixing a consistent RESTFUL API with some Json-RPC services is totally acceptable. – Laiv Apr 15 '17 at 21:49
  • @Blrfl It's fine for the two URLs to refer to the same resource, but I think the API should disclose that somehow either through links or a redirect response. – Jack May 15 '17 at 0:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.