Tuesday, September 1, 2015

Vocabulary negotiation

... and the need for an Accepts-Language for machines.

This is a write-up for a un-conference session I held at API-CRAFT 2015 @ Detroit as well as a follow up on the Vocabulary Fragmentation challenge I brought on my keynote at WS-REST 2014 at WWW in Seoul.

You want to read this before you continue. This is part of a series of posts.

At API-CRAFT 2015, a group of folks discussed the idea of making hypermedia API clients interoperate at the vocabulary/taxonomy level. The idea was simple: pass a parameter/header in the HTTP request to servers advertising the vocabularies/taxonomies the client understand.

GET /mountain-view HTTP/1.1
Host: api.yellowcab.com
Accepts-Vocab: http://schema.org

Sort of like how HTTP clients pass things like Accept: text/html, etc for media types and Accepts-Language: pt-BR, etc for user-visible languages.

For example, imagine this is the response you'd normally get from servers:

HTTP/1.1 200 OK
Content-Type: text/json

{
  kind: book,
  cover: "The Bible",
  id: "123",
  published: "01/01/0000"
}

What vocabulary negotiation (and more generally content negotiation) enables you is to advertise what your client "accepts/wants" the server to respond (to the extent that it *can* fulfill the request). For example, imagine your client could say:

dude, I totally don't want to have to parse this proprietary/unknown JSON blob. why don't you return it in a format and a vocabulary that I *do* understand?

It would advertise what it *does* understand with a special header, Accepts-Vocab (as well as any other other content negotiation headers, like Accept). For example:

GET /books/the-bible HTTP/1.1
Host: api.library.com
Accepts: application/json+ld
Accepts-Vocab: http://schema.org

And, as with any other content-negotiation mechanism, the server is responsible for returning the content in the requested format/vocabulary (or a 4xx in case it can't).

HTTP/1.1 200 OK
Content-Type: application/json+ld

{
  @context: "http://schema.org",
  @type: Book,
  name: "The  Bible",
  isbn: "123",
  datePublished: "01/01/0000",
}

Here is what this would look like for a different vocabulary, for example opengraph:
GET /books/the-bible HTTP/1.1
Host: api.library.com
Accepts: application/json+ld
Accepts-Vocab: http://ogp.me

Which the server can now respond:

HTTP/1.1 200 OK
Content-Type: application/json+ld

{
  @context: "http://ogp.me",
  @type: book,
  title: "The  Bible",
  isbn: "123",
  release_date: "01/01/0000",
}

This allows us, as a community, to build common/shared API clients that understand a common/shared vocabulary (whenever that's desirable/possible).

More to come, stay tuned.