101

I'm creating a RESTful API for creating users that enforces unique email addresses:

Successful POST /users: HTTP 201 Created

If I POST the same email address again, what should the response code be? Is 409 Conflict the appropriate response code?

Henke
  • 4,445
  • 3
  • 31
  • 44
thatmarvin
  • 2,800
  • 4
  • 22
  • 31
  • I do not think it is a good idea. If connection is made through some proxy the results might be unpredictable. – Cheery Feb 13 '12 at 22:37
  • 1
    I think it's a good idea! Because HTTP has status code, so use them! It's also very handy when you have to debug later and only have access files or other log files but if there is the HTTP code... :) – powtac Feb 13 '12 at 23:05
  • 2
    `409 - Conflict` is a very good choice for this kind of response. – Brian Kelly Feb 13 '12 at 23:48
  • @Cheery Not gonna worry about misbehaving proxies since this is a private API :) Even if I do make it public, I'd rather do my part to discourage the existence of bad proxies. – thatmarvin Feb 14 '12 at 07:42
  • 1
    In my REST API I return `HTTP 422`, `HTTP 409` is better for existing resources, e.g. versioning issues. – jnemecz May 31 '17 at 11:38
  • @Artegon HTTP 409 is not limited to versioning issues, HTTP spec does not state that. IMHO it's the most appropriate response code in the described case. I had the same choice between 422 & 409, went with 409 and put the rationale here: https://stackoverflow.com/a/70371989 – wombatonfire Dec 16 '21 at 01:06

7 Answers7

126

Yes, 409 is the most appropriate response code here. Even though you are most likely returning 201 on success, you're still POSTing to a resource which is described as a collection, and POSTing a duplicate email is definitely a conflict with "the current state of the resource" as a collection. You should return a response body with a description of the problem, and hyperlinks to help resolve the problem, if possible.

Community
  • 1
  • 1
fumanchu
  • 14,419
  • 6
  • 31
  • 36
  • Thanks for confirming my hunch with the explanation! I didn't think about the hyperlinks part, will definitely figure out a good way to include that. – thatmarvin Feb 14 '12 at 07:39
  • I don't access the content of response when I use a 409 status code. I changed to 200 and I access the attributes. – Wendel Jul 24 '20 at 18:15
  • While the explanation in this answer makes a lot of sense to me, it's still in conflict with how many major vendors (Google, Microsoft) handle the situation (returning 2xx) – ViBoNaCci Mar 30 '22 at 14:51
85

I am not really satisfied with returning a 409 Conflict for an existing registered email - in my opinion, it's not a client error. So let's take a look at how some big tech companies are handling that case (at least how they are doing it in their WEB Site APIs).

Gmail (Google) returns a 200 OK and a JSON object containing a code which is indicating that the email is already registered.

Facebook is also returning a 200 OK but re-renders the content to a recovery page to give the user the option to recover his/her existing account.

Twitter is validating the existing email by an AJAX call To another resource. The response of the email validation resource is always a 200 OK. The response contains a JSON object containing a flag to indicate if the email is already registered or not.

Amazon is doing it the same way as Facebook. Returning a 200 OK and re-rendering the content to a notification page to inform the user that the account already exists and provide him/her possibilities to take further actions like login or password change.

So all these APIs returning always a 200 OK and presenting to the client/user either additional content to recover their account or an error message which is raised by the body content of the response.

Paul Wasilewski
  • 9,762
  • 5
  • 45
  • 49
  • 7
    Upvoting this because in my opinion, this is not a failure at http protocol level. But its a logical error in application. Your application may or may not allow duplicate email IDs. But one round trip of HTTP request is successful. So I think HTTP response code should be 200 OK in this case – Mahesh Feb 26 '19 at 09:08
  • 4
    I haven't tested the GMail API directly but the Google API design guide seems to point to 409: https://cloud.google.com/apis/design/errors 409 ALREADY_EXISTS The resource that a client tried to create already exists. – kakoma Apr 22 '20 at 13:46
  • 2
    Done tests with the Google user provisioning API https://developers.google.com/admin-sdk/directory/v1/reference/users/insert and it returns 409 for an existing email address. – kakoma Apr 22 '20 at 13:57
  • And this approach helps to avoid false logs in our logger application. – krypru Nov 19 '20 at 15:04
  • 1
    @kakoma I just tried to create a Gmail user with my account name and it did return `200 OK`, where the body had suggestion for another account name, – Sven Anton Mar 26 '23 at 12:44
29

While the accepted answer is correct in showing the correct status code for the task, I want to add that you are introducing a security vulnerability.

If you return a 409 for account registration, you are just exposing a service for account enumeration.

Depends on the application, if the api is public or not, etc, you may want to return a 201 even if the account wasn't created.

Bart Calixto
  • 19,210
  • 11
  • 78
  • 114
  • 2
    And how can the client distinct between an already registered email and a successful registration? For a newsletter registration this solution might be fine but not for an account registration. – Paul Wasilewski Nov 04 '18 at 18:22
  • you tell him that he will receive an email shortly. If (s)he didn't receive the email then (s)he needs to register again. – Bart Calixto Nov 09 '18 at 09:15
  • 2
    In addition to the security vulnerability, it's also a privacy vulnerability. If I know your email address, a service shouldn't expose to me (via status code or otherwise) whether or not you are registered with them. – akivajgordon Apr 01 '20 at 02:40
  • 3
    I agree, but are there any real alternatives though outside of rate limiting an IP's requests? On a forgot password page, it's easy to mitigate with a message along the lines of, "If the account exists, an email will be sent with recovery details." On a registration page, however, if you don't display an error for a duplicate account, and say the user forgot they already registered with that email, that's going to lead to terrible UX. If you do display an error, regardless of the status code that's returned, it can be scraped by a bot that's enumerating account details. – Clark Brent Apr 15 '20 at 16:17
  • @ClarkBrent if the user is already registered, you send him a "welcome email" stating so with a login link. Since he is actually expecting that email, UX will be great. – Bart Calixto Apr 28 '20 at 10:40
8

+1 to Barts answer - for security reasons. Usually I would agree that 409 is a good status code for sth. that already exists. But in an environment of user accounts/authentication/authorization etc., I would tend to not exposing the existing user accounts in your database.

Of course there are other mechanisms of handling security at this place. If you do not mind to expose a little number of your accounts, you could add a behavior to your application that returns 401 or 403 on numerous 409-events from one IP.

Another option (in general) is to define a status code on your own to have a 2xx that differs from the existing standard 2xx variants. This could be an option if you do not want to handle an "already exists" as an error. However, this would be regarded as non-standard and would have the same unsafe character like a 409 in your concrete example.

iquellis
  • 979
  • 1
  • 8
  • 26
3

I often use the (WebDAV extension) HTTP 422 Unprocessable Entity:

The request was well-formed but was unable to be followed due to semantic errors

Community
  • 1
  • 1
Gareth
  • 133,157
  • 36
  • 148
  • 157
  • This part makes me think that 422 is inappropriate: "…but was unable to process the contained instructions". Here, there's no ambiguity regarding the semantics of the instructions — the server understood the request, it's just not going to fulfil it. (Plus I'd rather use RFC 2616 codes if I can help it) – thatmarvin Feb 14 '12 at 07:38
1
409 => Conflict
That mean.

The request could not be completed due to a conflict. For example, POST ContentStore Folder API cannot complete if the given file or folder name already exists in the parent location.

GrigorAtaryan
  • 445
  • 4
  • 10
-2

For registration it is required to have a code that is different from success 200 code, but not an error 4xx code.

As suggested in HTTP response code for POST when resource already exists look at 3XX:

302 Found
303 See Other

In particular

According to RFC 7231, a 303 See Other MAY be used If the result of processing a POST would be equivalent to a representation of an existing resource.

The concern about exposure of existing addresses to enumerating bots can be addressed by different means such as captcha.

Michael Freidgeim
  • 26,542
  • 16
  • 152
  • 170