API Design for a Trash

100 views
Skip to first unread message

Thomas Schreiner

unread,
Sep 26, 2012, 3:51:05 PM9/26/12
to api-...@googlegroups.com
Hi,

I am new to REST APIs and to learn it I am trying to build a system for managing tasks. While I was brainstorming about the api I figured that deleted tasks should be moved to a trash instead of immedeatly deleting them. So I set out designing a REST api for the trash.

Version 1:

/Tasks/1
- DELETE Moves the Task to the trash

/Users/Thomas/Tasks/Thrash
- GET Lists all Tasks in Trash
- DELETE Empties Trash

/Users/Thomas/Tasks/Thrash/1
- DELETE removes the task from the database
- PUT with Parameter ?restore=true restores the task

There are three things I dont like in this version
1. Once a Task is in the Trash it is accessible via two locations
2. the ?Restore parameter feels akward
3. Overriding the trash (think deleting with shift pressed in Windows) requires two api calls

Version 2:
Task gets a Property IsInTrash

/Tasks/1
- PUT with Property IsInTrash=true Moves the Task to the trash
- PUT with Property IsInTrash=false Restores the Task from the trash
- DELETE Removes the Task from the database

/Users/Thomas/Tasks/Thrash
- GET Lists all Tasks in Trash
- DELETE Empties Trash

Version 2 has the disadvantage of new consumers to the api might accidently bypass the trash by ignoring (or simply not knowing about) the IsInTrash Property.

What are your opinions about the design. Also any ideas about a different design are welcome.

Thanks,
Thomas

chris...@gmail.com

unread,
Sep 26, 2012, 4:06:46 PM9/26/12
to api-...@googlegroups.com
On Wed, 26 Sep 2012, Thomas Schreiner wrote:

> What are your opinions about the design. Also any ideas about a different
> design are welcome.

If recovering things from the trash is important to you, have you
considered:

Tasks
* POST /Tasks => 204 or 303, Location: /Tasks/1 (task 1 created)
OR
PUT /Tasks/1 => 204 (task 1 created, you "had" the id already)
* DELETE /Tasks/1 => 204 (task now trashed)

Trash
* GET /Trash => 200 (list of items in trash)
* GET /Trash/1 => 200 (to get the resource that is in the trash)
* GET /Tasks/1 => 404 (it's not a task, it's in the trash)
* PUT /Tasks/1 => 204 (to "restore" the resource by putting it back)
* DELETE /Trash/1 => 204 (remove (for realz this time) on task)
* DELETE /Trash => 204 (empty the trash entirely)

That last one I probably wouldn't do, but instead GET /Trash and then
send many DELETEs if what I wanted to do was irrevocably delete the
stuff in the trash.

This gives you some nice humane URIs and uncomplicated grammar in the
API.

I'm sure there are plenty of other people here who would prefer that
the state of "being in the trash" be an attribute on the resource.
This could work fine, but if you did that, I think you lose the
simplicity which comes from the task resource remaining whole, whether
it is in the trash or not.

I think you're likely to get quite a few opinions on how to do this. I
would argue that there's no right way and that the best way depends on
your own style and the kinds of styles of interaction you want to
enable. For example are you targetting machine-based hypermedia
clients, or people writing HTTP clients?

--
Chris Dent http://burningchrome.com/
[...]

Diego Magalhães

unread,
Sep 26, 2012, 4:13:24 PM9/26/12
to api-...@googlegroups.com
Chris was faster than me, but I do think that moving items to different resources works better than have it duplicated.

Diego Magalhães
http://diegomagalhaes.com
claro @ +55 21 9411 2823






--
You received this message because you are subscribed to the Google Groups "API Craft" group.
To unsubscribe from this group, send email to api-craft+unsubscribe@googlegroups.com.
Visit this group at http://groups.google.com/group/api-craft?hl=en.



Greg Brail

unread,
Sep 28, 2012, 1:39:17 PM9/28/12
to api-...@googlegroups.com
This is a cool example because I think it hinges on what your "resources" are.

Here's another way to do this:
  • Make each "task" a separate resource with its own URI
  • Give each task a "state" field
  • Use POST to change the state, for instance from "active" to "deleted"
  • Use DELETE to permanently delete the task
  • Use query parameters on the the collection of tasks to retrieve tasks in particular states
In this model, each "task" is a separate resource that goes through various state changes, and then can be deleted. I think this model is pretty easy to understand and can be applied to a lot of use cases. For instance:

POST /tasks -- create a task
GET /tasks/{id} -- Get it
DELETE /tasks/{id} -- Delete it permanently
PUT /tasks/{id} -- Completely replace the whole task, including all fields

POST /tasks/{id} 
  { "state" : "deleted" }
 
  -- this changes the state of the task to "deleted" without removing it or changing the URL but without changing other fields

GET /tasks?state=deleted -- Get me the lists of deleted tasks

--
You received this message because you are subscribed to the Google Groups "API Craft" group.
To unsubscribe from this group, send email to api-craft+unsubscribe@googlegroups.com.
Visit this group at http://groups.google.com/group/api-craft?hl=en.





--
Gregory Brail  |  Technology  |  Apigee
Reply all
Reply to author
Forward
0 new messages