Monday, June 17, 2013

What's The Best Structure for API Responses?

I learned something new while listening to Episode 12 of the Traffic and Weather podcast.

John Sheehan mentioned that when you return your XML or JSON from an API you should have an error envelop separate from the data envelop.

The main reason is if you're deserializing the output and mapping it to a class in a static language you can use error.message or error.code without namespace conflicts. This also gives you a consistent target for a given endpoint. John recommends avoiding returning one structure for success and another structure for error (something that I've been doing to date).

My take away is that John recommends structuring your return data like so:

Success:
{
  data: {
    id: 1,
    model: 'Mustang',
    make: 'Ford'
  },
  error: null
}

Error:
{
  error: {
    code: 3,
    message: 'Car not found'
  }
}

Continue reading to see the NOT RECOMMENDED way

The way I traditionally did it was without envelopes but the structure changes based on success vs error:

Success (the car object):
{
  id: 1,
  model: 'Mustang',
  make: 'Ford'
}
Error (the error object):
{
  code: 3,
  message: 'Car not found'
}

What I liked about my method is that you can deserialize directly to the class you want ("Car") without creating a wrapper class. For example, my way you don't have to have a class like this.

public class CarResponse 
{
  public Car Data { get; set; }
 
  public ApiError Error { get; set; }
}

The downside of my method is you have to do some extra work to parse errors into ApiError instead of Car.

I'm not 100% convinced I want to switch and have a bunch of response wrapper classes, but it's debatable whether there is another person more involved with APIs then John, so I'll probably be switching. ;)

Some questions I have for John's method (UPDATE: see comments for John's answers, my examples have been updated to reflect them).
  1. What's the recommendation for naming the envelop of the success data. Ex. "car" or always use something generic like "data"
  2. On success do you return the error envelop at all? If so, do you indicate a "no error" status code? Ex. "code: 0"

If you're working with APIs be sure to checkout John's excellent tool Runscope. It's good stuff.