Saturday, April 5, 2014

What all APIs still look like as WebPages

... or how far we are from the human web.

This is part of a series. You want to read this before carrying on.

On my last post, I tried to show you what your web API looks like to a web developer. On this post, I'll go over what your L3 API STILL looks like to a web developer.

Here are a few things we take for granted on the web that makes our APIs feel like they were designed back in 1995.

Websites are always at HEAD: The Versionless API challenge

Now whether you are a L3 API or not, we still live in a world that APIs are versioned and moving from one version to another is done out of band.

There is a premise that hypermedia APIs make transitioning from one version to another a lot easier, mostly due to the fact that you are under the control of the links.

But still, there are plenty of problems to be resolved (e.g. changing cardinality of your properties, changing your schema in a non-backward compatible manner, etc), and this is one of those promises that we'll have to let time be the judge.

Show me a respectable API, with millions of users, who has transitioned through 3-4 different versions, over more than 2-3 years, and you can call this problem done.

This is how absurd your APIs currently look like to an user of the human web:

http://example.org/index.html

Hi, welcome to our website!

Our website has multiple versions, click here to continue:

My website v1
My website v2
My website v3

The Discovery of APIs challenge

One of the biggest challenges about existing APIs is that they are non-discoverable. There is no "crawler" equivalent for APIs. Part of the problem is that they are entirely disconnected from the human web.

What that means is that, in order for me to use your API, I actually have to go to your website and read your documentation in English, rather than finding it programatically.

What we need is a google.com-like crawler for APIs (and hopefully we've learned from UDDI and the register-vs-crawl battle).

Your APIs looks like those websites that are entirely irrelevant to search engines, those that you have to copy-past the URL to get to it.

http://example.org/index.html
I have no idea how you got here, but welcome to our website!

The Vocabulary Fragmentation challenge

The third biggest challenge with your API right now is that it is in Klingon. Yeah, that's right, I don't understand a word of what's written over there, because we are not using the same vocabulary.

We need a language that everybody speak, that everybody can understand. Something like latim.

http://example.org/index.html


The Verb Taxonomy Fragmentation challenge

The fourth challenge is that your API is trying to give me affordances that I don't understand. Stop trying to make fetch happen, it is not going to happen.

We need to agree on a set of affordances that we all understand. Sort of what GET/POST/DELETE/PATCH is for HTTP, but at the application semantic level.

http://example.org/index.html

Welcome to my website! Fill the following form to "fetch" our products!

The Hypermedia media type fragmentation challenge

Fragmentation is certainly an important step that needs to be taken before unification. We need diversity and we need exploration. I love seing efforts like hydra, uber, hal and siren to pop up!

But at some point in time, we need to converge into a unified media type. Like text/html is for the human web.

http://example.org/index.html




The API Management challenge

Finally, managing APIs is done completely different than managing web sites. That's insane. You have to sign-up to an API key before you even use an API? When was the last time that you've seem that on a website?

http://example.org/index.html

Welcome to our website! We have detected that you are coming from a corporate IP!

Unfortunately, you can't use our website until your company signs some paperwork up front.

Could you please ask your company to get their "API KEYS" so that we can apply quotas and throttle?

So, where we go from here?

As usual, follow your nose :) Be part of the dialogue! If you have ideas on how to address these things, lets talk, I'd like to learn about them!

This is part of a series of posts. You can read more about that here.

Wednesday, April 2, 2014

What your API would look like as a WebPage

... or, do you really want to write your API in .txt?

Lately, I have been in many discussions where I had to make a case for hypermedia. I have found that the easiest way to introduce folks to hypermedia is to just claim that their APIs are at a "lower maturity level" (usually L2) and point them to Richardon's Maturity Model.




What I have also found is that, while the general concept of hypermedia makes sense for some people, it is hard for them to understand what that means in practice *.

* I don't blame them. There is very little on the subject in concrete terms (e.g. existing robust hypermedia APIs working in production code in a reasonably large corporation).

I thought that, if I showed them what their APIs would look like as if they were web pages, they'd get insulted enough to re-consider :) So, here it goes :)

Level 0: The Swamp of POX

Very rarely I'd come across a L0 API in my daily job, but I understand there are a bunch of enterprise code that uses SOAP. At this level, your API calls go through one endpoint and you are only using one HTTP method.

POST / HTTP/1.1
Host: www.example.org
Content-Type: application/soap+xml; charset=utf-8
Content-Length: 299
SOAPAction: "http://www.w3.org/2003/05/soap-envelope"
<?xml version="1.0"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
  <soap:Body>
    <m:ScheduleAppointment xmlns:m="http://www.example.org/doctors">
      <m:DoctorId>123</m:DoctorId>
    </m:ScheduleAppointment>
  </soap:Body>
</soap:Envelope>

This what your API looks like, seem from the perspective of the web for humans:

http://example.org/index.txt
Welcome to my website!

Here are some doctors available:

Mr. Jones and his ID is 123. He has the following available slots:

- Tuesday, 05/02
- Wednesday, 05/03

If you'd like to make an appointment, please, take your browser window and append act=create and doc=123 and slot=05/02 to our web site!

K THX BYE XOXO

As you could've imagined, all interactions with this website is via its root page. There is just index.txt and that HTTP servlet does it all.

It is also notable that the entire website is in a .txt file, as opposed to a hypermedia media type like .html. What that means is that the website is instructing you to manually construct their URLs to carry on. I know, right!

http://example.org/index.txt?act=create&doc=123&s=05/02
Appointment slot created!

Please, don't reload this page, or else we'll create another appointment! Just go away :)



Thanks for your business!

Because you are not using HTTP in its entirety (e.g. you are creating a reservation slot with a GET), you don't get the benefits that a HTTP client gives you (e.g. warning a user whether they want to re-submit the data when refreshing a page after a POST).

Level 1: Resources

This is a slightly more common case, but I still very rarely find this on my day job.
GET /doc/123/slots/05/02.txt?action=create HTTP/1.0
Host: example.com
At this level, you are breaking up your API in multiple resources but still using just one HTTP method.

http://example.org/index.txt
Hi Welcome to our website! Here is our directory of doctors:
- Mr. Jones and his ID is 123.
If you'd like to make an appointment, please, take your browser window and append doc/ and the doctor ID to our web site!






Because you are not using hypermedia (e.g. links), you are still making your users construct their URLs by hand. They get IDs from you, look at your documentation and construct the next step.

http://example.org/doc/123.txt

Hi! Welcome to doctor Jones appointment page! Here are the appointments available:

- Tuesday, 05/02
- Wednesday, 05/03

If you'd like to make an appointment, append /slots/ and the date you'd like to schedule!

I know, seriously, right!

http://example.org/doc/123/slots/05/02.txt

Hi! Welcome to doctor Jones appointments for 05/02!

If you'd like to make an appointment, append a ?action=create to this page to create!

Really? OK, I guess ...

http://example.org/doc/123/slots/05/02.txt?action=create
Appointment slot created! Thanks!

Please, don't reload this page, or else we'll create another appointment! Just go away :)






This is a step forward, albeit quite a small one. Breaking down your API into multiple resources gives you things like addressability (e.g. you can forward links to people now!) and a more scalable load balancing approach.

Level 2: HTTP Verbs

Now, this is where I'm almost sure you are at if you are reading this. You pay your taxes, you eat your vegetables and you went to an ivy league school. You are trying your best to be RESTful and you have an open mind.

You spent countless hours breaking up your resources into a layout that makes sense, each resource supports very specific verbs ("even PATCH and DELETE" you say, proudly!) and yet ... I'm comparing your API to a website circa 1990.

GET / HTTP/1.0
Host: example.com

HTTP/1.0 200 OK
Content-Type: text/json
{
  "doctors": [{
    "name": "Dr. Jones",
    "id": "123"
  }]
}

The problem is ... you are using a .txt file, like JSON or XML.

This is what your API look like:

http://example.org/doc/123/slots/05/02.txt
If you'd like to make an appointment, send a POST request to this page to create! As parameters, send a slot=7pm or 8pm which are available!



The issue here is that you are using out-of-band information to tell users what your API affords. You are literally asking them to "read your page" and "construct a POST request" in English, rather than something that the browser can understand (e.g. a <form>).

This applies to links (<a> tags) too, which you are making your clients construct by reading English.

http://example.org/doc/123/slots/05/02.txt
Appointment slot created! Thanks! Feel free to reload this page, your browser will know what to do and ask you if you want to re-submit the data!


You don't run into double-submission problems anymore (as the browser is now aware that a POST is different than a GET, and hence will ask the user whether they really want to re-submit a non safe operation).

But your API still looks like it was built by a 1990-webmaster.

Level 3: Hypermedia

Welcome to the new world :) Or not so new, if you count the fact that this has been known since the invention of the web :)

Let me introduce you to two breakthrough technologies: <a> tags and <forms>!

What hypermedia media types (e.g. HTML) does is to intermingle data and control into the same message, providing a non-linear form of reading.

Now, instead of you having to explain to your users where to go next in English, you can create <a> tags to point them to the right place.

You can also use <forms> to allow write-transitions.

There is no manual your users need to use to browse your API. There is no out-of-band information: the message has both data and control to help you transition to the next place.

GET / HTTP/1.0
Host: example.com

HTTP/1.0 200 OK
Content-Type: text/ld+json
{
  "@context": "schema.org",
  "@type": "Clinic",
  "@id": "http://example.com/",
  "doctors": [{
    "@type": "Doctor",
    "@id": "http://example.com/doctors/123",
    "name": "Dr. Jones",
    "appointments": {
      "@type": "AppointmentBook",
      "@id": "http://example.com/doctors/123/slots",
      "action": {
        "@id": "http://example.com/doctors/123/slots",
        "@type":"ScheduleAction"
      }
    }
  }]
}
This is what your API would look like at this stage:

http://example.org/index.html
Hi! Welcome to our website!

Here is a list of our doctors:

- Doctor Jones, appointments



Your users are now able to click on links to go to the next step, because browsers know how to interpret anchor tags.

http://example.org/doc/123/slots/05/02
Welcome to Doctor Jones appointments list! If you'd like to create an appointment, fill the following form:
Patient's name:  Date:


Your users are now able to schedule appointments by filling a form, since your browser understand forms.

OK, but where do I go from here?

Just follow your nose :) There are plenty of trade-offs to be made here but at least you hopefully learned something new.

And, honestly, L3 APIs still have a long way to go, so join us and come be part of the discussion!

You can find out more about this here:

(Ha! You thought I would give you instructions on how to construct those URLs by hand didn't you?)