Reputation: 88448
Apologies in advance for asking a "what is the best way to cram some functional operation into a RESTful way of thinking" question. There is no intent to start a debate here; I would like to see if there is an accepted pattern for doing a particular task.
Suppose I wanted an endpoint in an API for creating a "referral code" for a user/affiliate pair. I could do
POST /referral_codes
{"user":1, "affiliate":88}
and make a response with 201 CREATED and a body with the new code.
But if the code already exists, I would give back the existing referral code. In this case, a 201 is inappropriate (nothing was created). A 200 OK might make sense, and a 409 CONFLICT makes sense if you greatly stretch the intent of the 409 -- But it isn't really an error to ask for a code that already existed; the operation I am trying to mimic is called "find OR create".
Another option is to make the endpoint a GET (i.e. GET /referral_codes?customer=1&affiliate=88
), since the client need not know whether the server had to create a resource to fulfill the request. And since it is still idempotent (subsequent calls will return the code that was created the first time), I'm not doing anything for which a Restafarian would object to, or would I?
Is there an accepted pattern for "find or create"?
Upvotes: 1
Views: 1709
Reputation: 118764
I would POST and 200 with the Location to the existing resource. The semantics are simply easier.
As for the GET option, it's only idempotent the SECOND time, the first time it is, indeed, creating the resource.
You can tell this if you had any kind of aggregate resource that would "get all statuses" and you'd see that the new one is not there, but if you GET it directly, the, Shazam, is IS there, and that's a mistake.
POST with 200 is just most efficacious in this case, I think.
Upvotes: 4