How to Write a Self-Documenting API - Heyzap API release
stdout.heyzap.com
stdout.heyzap.com
"You of course need a JSON viewer plugin to do this."
Why not emit your JSON slightly prettier from the server side? http://stackoverflow.com/questions/86653/how-can-i-pretty-fo...On a couple thousand requests the latency is not so noticeable. But on the long run maybe the API user should have a plugin on the client side to do that kind of beautification.
Which, by the way leads to my single complaint with this API: it only renders JSON.
To call it truly "self-documenting", I should just browse to http://www.heyzap.com/api/v1/ (ok, second complaint: the "v1" also belongs in a header, not the URI) and get an HTML page describing the resource, and links to the other endpoints. Bonus points if this HTML allows me to run the queries with overridden parameters.
About the v1 versioning in the URL, I understand your suggestion. But I see that little characteristic as a "no developer left behind" program for developers with less experience.
Also the format as an extension for your resource serves the same purpose
I may revise if it increases server load significantly but it looks good for now: http://www.heyzap.com/api/v1/activity/android
But if you see application/json in Accept:, then you assume it's an API call from a phone or script and you minify it instead.
Edit: however, that requires cooperation from others, so is prone to failure. Perhaps also take hints from the user agent string?
Edit 2: drat, someone already beat me to this suggestion. However, I'll use this as an excuse to pimp my last weekend hack: adding an Accept: decorator to itty.py http://news.ycombinator.com/item?id=3665743
Here's a browsable example API: http://rest.ep.io/
Because your browser provides Accept: text/html by default you get back a nice html page describing the result for the API root. If you send Accept: text/json (click "json" at the bottom) you get back a json response.
You can follow the links in the html response to get to other parts of the API. You can also click "OPTIONS" to send an OPTION request to get a description of what you can send to that endpoint.
Looking at the django-rest-framework API examples, that's one thing I don't see, but is (at least for me) fairly critical.
One thing that does seem to be a bit lacking is the documentation. I've used all three django frameworks though (piston, tastypie and django-rest-framework) and django-rest-framework wins in my book.
This is a bullet from the django-rest-framework page I linked above: "Modular architecture - MixIn classes can be used without requiring the Resource or ModelResource classes."
Here's one of the examples from django-rest-framework that is not tied to models: http://django-rest-framework.readthedocs.org/en/latest/examp...
And also, from the Tastypie docs: http://django-tastypie.readthedocs.org/en/latest/resources.h...
I want to expose arbitrary view methods to GET calls, not linked to any model, and not have to write a new class for every view I want to expose. Basically I want views to return the correct filetype (json, html, xml, etc) when requested. This is basically making django a little more rails-like. I'm leaning towards django-dynamicresponse currently.
I really like how the three you mentioned tie into Django's forms though, and that's quite a feature to give up.
You just define a view that inherits from djangorestframework.views.View, and implement the action methods (get/post/put/delete) that you want. These methods must return a dictionary, and the framework handles the part of dispatch and render the view in the proper format.
I would take it further and say that truly self-documenting API's should be discoverable by software as well as individuals. This is something we have worked on hard at LedgerSMB, doing so with stored procedures even (see http://ledgersmbdev.blogspot.com/2011/10/introduction-to-sod... for more info).
Anywhere there is a connection between software, this can be a good approach. Why limit it to the web?
[1]: http://blog.steveklabnik.com/posts/2011-07-03-nobody-underst...
It's like this:
--> GET /api/ Accept: application/json
<-- Content-type: application/vnd.api.v1+json <stuff>
Then your consumers can know what version of the API they're interacting with and act accordingly.
Including the version number in the URL gets around this and even allows you to test API responses in mobile browsers if needed.
Although I tend to agree that a header-based approach is cleaner and more in the spirit of REST and even HTTP.