Search code examples
restrestful-architectureapi-design

RESTful APIs: what to return when updating an entity produces side-effects


One of our APIs has a tasks resource. Consumers of the API might create, delete and update a given task as they wish.

If a task is completed (i.e., its status is changed via PUT /tasks/<id>), a new task might be created automatically as a result.

We are trying to keep it RESTful. What would be the correct way to tell the calling user that a new task has been created? The following solutions came to my mind, but all of them have weaknesses in my opinion:

  1. Include an additional field on the PUT response which contains information about an eventual new task.
  2. Return only the updated task, and expect the user to call GET /tasks in order to check if any new tasks have been created.

Option 1 breaks the RESTful-ness in my opinion, since the API is expected to return only information regarding the updated entity. Option 2 expects the user to do stuff, but if he doesn't then no one will realize that a new task was created.

Thank you.

UPDATE: the PUT call returns an HTTP 200 code along the full JSON representation of the updated task.

@tophallen suggests having a task tree so that (if I got it right) the returned entity in option 2 contains the new task as a direct child.


Solution

  • You really have 2 options with a 200 status PUT, you can do headers (which if you do, check out this post). Certainly not a bad option, but you would want to make sure it was normalized site-wide, well documented, and that you didn't have anything such as firewalls/F5's/etc/ re-writing your headers.

    Something like this would be a fair option though:

    HTTP/1.1 200 OK
    Related-Tasks: /tasks/11;/tasks/12
    
    { ...task response... }
    

    Or you have to give some indication to the client in the response body. You could have a task structure that supports child tasks being on it, or you could normalize all responses to include room for "meta" stuff, i.e.

    HTTP/1.1 200 OK
    {
        "data": { ...the task },
        "related_tasks": [],
        "aggregate_status": "PartiallyComplete"
    }
    

    Something like this used everywhere (a bit of work as it sounds like you aren't just starting this project) can be very useful, as you can also use it for scenarios like paging.

    Personally, I think if you made the related_tasks property just contain either routes to call for the child tasks, or id's to call, that might be best, lighter responses, since the client might not always care to call to check on said child-task immediately anyways.

    EDIT: Actually, the more I think about it - the more headers would make sense in your situation - as a client can update a task at any point during the task processing, there may or may not be a child task in play - so modifying the data structure for the off-chance the client calls to update a task when a child task has started seems more work than benefit. A header would allow you to easily add a child task and notify the user at any point - you could apply the same thing for a POST of a task that happens to immediately finish and kicks off a child task, etc. It can easily support more than one task. I think this as well keeps it the most restful and reduces server calls, a client would always be able to know what is going on in the process chain. The details of the header could define, but I believe it is more traditional in a scenario like this to have it point to a resource, rather than a key within a resource.

    If there are other options though, I'm very interested to hear them.