2

There is /group/1 and /group/2, and /item/42 is a member of /group/1. I would like to remove /item/42 from /group/1 and put it into /group/2. My current solution is this:

GET    /group/1/item/42   => Get the item from the first group
POST   /group/2/item      => Create a clone of the item in the 2nd group
DELETE /group/1/item/42   => Delete the original item from the 1st group

There are (at least) two serious problems with this solution:

  1. If the client stops before the DELETE, the item will become a member of both groups.
  2. The ID of the item won't be the same in /group/2, which looks as if the item would lose its identity.

How should I redesign the API if I want to change an item's group membership in a single step (with retaining its identity, if possible)?

kol
  • 27,881
  • 12
  • 83
  • 120
  • Are there one-to-many or many-to-many relationships between groups and items? – supertopi Sep 13 '13 at 12:43
  • @supertopi Every item is a member of exactly one group. Groups can contain any number of items, even zero. – kol Sep 13 '13 at 12:52

2 Answers2

1

In your case, I would not use the URI to link items to groups.

If items to groups are 1 to n-relationship, every item should have a link (e.g. a database foreign key) to its group.

Therefore, your URI-space could be much simpler:

./[groups|items]/{id}

The RESTful way is to modify the item resource with a POST.

POST /items/42 { group: 2 }

In this case, your backend identifies the request as an update to an existing resource.

Here are a few demonstrations how the API could work.

GET /items --list of all items by IDs
GET /groups --list of all groups by IDs
GET /items/42 --item 42 properties

POST /items { id: 33, name: "Cool Item", group: 2} -- adds a new item, linked to group 2
PUT /groups/4 { id: 4, name: "Hot group"} --adds a new group
POST /groups/4 {name: "Cool group" } --updates the name of group 4
POST /items/33 { group: 4 } --moves the new item 33 to group 4

GET /items?group=4 --list of all items belonging to group 4

You can use POST instead of PUT if you want.

supertopi
  • 3,469
  • 26
  • 38
  • Thanks!!! Anyway, AFAIK POST is used to *create* new resource and PUT and PATCH are for *updating* existing resources. POST is used for updating only if the client or the server doesn't handle PUT or PATCH. http://jasonsirota.com/rest-partial-updates-use-post-put-or-patch – kol Sep 15 '13 at 19:47
  • It is perfectly REST-ful to create resources via PUT. The use of PUT vs. POST when creating a resource has more to do with whether the client knows the full URI of the resource it is creating or not. If the client knows the full URI of the new resource, it may (and should) PUT the content of that resource to create it. If, on the other hand, the full URI is not known in advance and will only be defined by the server, then the typical pattern is to POST to a factory resource that creates the new resource and returns its URI in the location header. – Tim Dean Sep 16 '13 at 00:52
  • 1
    That being said, the PUT examples used here are not what I would consider REST-ful: These PUT to a generic /items or /groups factory object rather than POST. That is not an appropriately idempotent use of PUT. – Tim Dean Sep 16 '13 at 00:55
  • @TimDean you're right. I modified some of the examples. I remind you, they are only examples I added to demonstrate the use of my suggested API :) – supertopi Sep 16 '13 at 11:59
0

If you need an atomic operation, I would consider

POST /group/2?moveFrom=/group/1/item/42
Eric Stein
  • 13,209
  • 3
  • 37
  • 52