http://amundsen.com/media-types/collection/examples/
This format takes into consideration collections (much like Siren). It also takes into consideration versioning. However, I'm not certain version matters in the data set if it pertains to an API version. That is best left being in the API URL. It could pertain to collection version, but I'm not sure the point. Documentation says each collection should have a version - but says nothing more about meaning or why.
Items are clearly distinct in this format and are organizationally positioned separate from links.
This is by far the most collision free structure.
However, the data format itself is a bit strange...Every field being an array. Data is always an array of objects. I understand the flexibility this presents and am not 100% against it. I just believe it's perhaps not needed as things could change based on the client application.
The queries section is very nice and something not found in other formats. However, I don't see anything for pagination and I believe it would certainly make sense to include by now.
Collection+JSON puts a lot of emphasis on the display and intended usage of data. Moreso than any other format. This is nice, but unless the client application was attempting to display a layout automatically, I don't see the need. A human engineer can interpret and decide things just fine and perhaps different clients or even access control rules would dictate a different visual representation anyway. Therefore I believe this oversteps the duties a little bit. Still clever and guidance/definition is what we're after of course.
I like how links are even more separate from the data here than any other format. Due to this structure, there is no need to prefix with underscores, etc. Links still carry the same "rel" descriptive values which are important for orientation.
However, I would still use "self" instead of "href" for the current item's link for consistency. Again, Collection+JSON puts some emphasis on how these links should appear. For example, the "render" key. However, many of these properties "render" and "prompt" etc. are optional anyway.
The only downside here is that given how much emphasis and careful consideration is put on how data is rendered, there seems to be a lack of emphasis for "actions" or forms.
The "template" section is actually intended to be used as a guide for which data should be sent to the API in these cases (POST and PUT for update, following convention). However, I don't believe it's particularly descriptive. Also, the format states there should only be one form. This isn't a bad rule of thumb, but I could see where an API response may return multiple forms every now and then (related data, etc.).
http://amundsen.com/media-types/collection/examples/#ex-error
Not shown here is another section called "errors" and I feel this is important and worth mentioning. It's very debatable that errors should be contained within HTTP reponse headers...But I believe that, often, additional detail is required and messages being returned in an API are good because it means those messages can be updated from one central location instead of many client application updates. Superior design for maintenance. Additionally, HTTP headers should be kept small and while a status code is obviously present, an entire message intended for a human is perhaps inappropriate.
{ "collection" :
{
"version" : "1.0",
"href" : "http://example.org/friends/",
"links" : [
{"rel" : "feed", "href" : "http://example.org/friends/rss"}
],
"items" : [
{
"href" : "http://example.org/friends/jdoe",
"data" : [
{"name" : "full-name", "value" : "J. Doe", "prompt" : "Full Name"},
{"name" : "email", "value" : "[email protected]", "prompt" : "Email"}
],
"links" : [
{"rel" : "blog", "href" : "http://examples.org/blogs/jdoe", "prompt" : "Blog"},
{"rel" : "avatar", "href" : "http://examples.org/images/jdoe", "prompt" : "Avatar", "render" : "image"}
]
},
{
"href" : "http://example.org/friends/msmith",
"data" : [
{"name" : "full-name", "value" : "M. Smith", "prompt" : "Full Name"},
{"name" : "email", "value" : "[email protected]", "prompt" : "Email"}
],
"links" : [
{"rel" : "blog", "href" : "http://examples.org/blogs/msmith", "prompt" : "Blog"},
{"rel" : "avatar", "href" : "http://examples.org/images/msmith", "prompt" : "Avatar", "render" : "image"}
]
},
{
"href" : "http://example.org/friends/rwilliams",
"data" : [
{"name" : "full-name", "value" : "R. Williams", "prompt" : "Full Name"},
{"name" : "email", "value" : "[email protected]", "prompt" : "Email"}
],
"links" : [
{"rel" : "blog", "href" : "http://examples.org/blogs/rwilliams", "prompt" : "Blog"},
{"rel" : "avatar", "href" : "http://examples.org/images/rwilliams", "prompt" : "Avatar", "render" : "image"}
]
}
],
"queries" : [
{"rel" : "search", "href" : "http://example.org/friends/search", "prompt" : "Search",
"data" : [
{"name" : "search", "value" : ""}
]
}
],
"template" : {
"data" : [
{"name" : "full-name", "value" : "", "prompt" : "Full Name"},
{"name" : "email", "value" : "", "prompt" : "Email"},
{"name" : "blog", "value" : "", "prompt" : "Blog"},
{"name" : "avatar", "value" : "", "prompt" : "Avatar"}
]
}
}
}
I started out separating the idea of links and actions/forms myself. The difficult part is that given a resource, there are several actions that can be done to that particular resource. For example, if you use the "edit" link relation from AtomPub, it says, "the href IRI can be used to retrieve, update, and delete the Resource represented by that Entry." So in that one link relation, which most media types would consider a "link," you actually have one "link" and two "actions" that you can do. So is that a link or an action? Maybe both?
For me, an affordance says here's a resource, and here are the things you can do with that resource. Specifying one action (like a form for Edit Customer) seems to be limiting, so with an affordance in Verbose, you can specify what all can be done to that URI.
Also, I'm not 100% on sticking with "affordances," but it does provide a way to convey both the idea of a link and an action/form. And it's a fun word!